diff --git a/src/index.css b/src/index.css index 4fbb6ad..0e91037 100644 --- a/src/index.css +++ b/src/index.css @@ -2149,3 +2149,79 @@ select.studio-input { background: var(--bp-paper); } color: var(--bp-navy); cursor: pointer; } .approvals-actions-toggle input { cursor: pointer; } + +/* Wizard polish — preview pane, stepper checkmarks, review summary, step controls */ +.wizard-body { + display: grid; + grid-template-columns: minmax(0, 1fr) 360px; + gap: 24px; + padding: 0 24px 24px; +} +@media (max-width: 1000px) { .wizard-body { grid-template-columns: 1fr; } } + +.wizard-progress { display: flex; gap: 6px; flex-wrap: wrap; } +.wizard-step-marker { display: inline-flex; align-items: center; gap: 6px; font-family: var(--bp-mono); font-size: 10px; color: var(--bp-muted); letter-spacing: 0.06em; text-transform: uppercase; } +.wizard-step-marker.active { color: var(--bp-navy); font-weight: 700; } +.wizard-step-marker.past { color: color-mix(in srgb, var(--bp-navy) 60%, var(--bp-muted)); } +.step-num { + display: inline-flex; align-items: center; justify-content: center; + width: 18px; height: 18px; + background: var(--bp-paper); color: var(--bp-navy); + border: 1px solid var(--bp-navy); font-size: 10px; font-weight: 700; +} +.wizard-step-marker.active .step-num { background: var(--bp-amber); color: var(--bp-paper); border-color: var(--bp-amber); } +.step-num-done { background: color-mix(in srgb, #2e7a25 70%, var(--bp-paper)) !important; color: var(--bp-paper) !important; border-color: #2e7a25 !important; } +.step-chevron { color: var(--bp-muted); } + +.panel-sub { font-size: 12px; color: var(--bp-muted); line-height: 1.5; margin: -4px 0 12px; } + +.node-controls { display: inline-flex; gap: 4px; margin-left: auto; } +.node-controls .icon-btn { padding: 2px 6px; font-size: 12px; } +.node-controls .icon-btn:disabled { opacity: 0.35; cursor: not-allowed; } +.node-meta { display: flex; align-items: center; gap: 8px; } + +.wizard-review { + display: flex; flex-direction: column; gap: 8px; + padding: 14px; + background: var(--bp-paper); + border: 1px solid var(--bp-navy); + margin-bottom: 12px; +} +.wizard-review-row { display: flex; gap: 12px; font-size: 12px; line-height: 1.5; } +.wizard-review-label { + flex: 0 0 110px; + font-family: var(--bp-mono); font-size: 10px; letter-spacing: 0.08em; + color: var(--bp-muted); text-transform: uppercase; + padding-top: 2px; +} + +.wizard-preview { + background: var(--bp-paper); + border: 1px solid var(--bp-navy); + padding: 16px; + display: flex; flex-direction: column; gap: 14px; + position: sticky; top: 60px; align-self: flex-start; + max-height: calc(100vh - 80px); overflow-y: auto; +} +.wizard-preview-head { display: flex; flex-direction: column; gap: 4px; padding-bottom: 10px; border-bottom: 1px solid color-mix(in srgb, var(--bp-navy) 20%, transparent); } +.wizard-preview-title { font-size: 14px; font-weight: 700; color: var(--bp-navy); } +.wizard-preview-desc { font-size: 11px; color: var(--bp-muted); line-height: 1.4; } +.wizard-preview-section { display: flex; flex-direction: column; gap: 6px; } +.wizard-preview-label { font-family: var(--bp-mono); font-size: 10px; letter-spacing: 0.08em; color: var(--bp-muted); text-transform: uppercase; } +.wizard-preview-chain { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 4px; } +.wizard-preview-chain-item { display: flex; align-items: center; gap: 8px; font-size: 12px; padding: 6px 8px; border: 1px solid color-mix(in srgb, var(--bp-navy) 16%, transparent); } +.wizard-preview-chain-idx { font-family: var(--bp-mono); font-size: 10px; color: var(--bp-muted); width: 18px; text-align: right; } +.wizard-preview-chain-name { flex: 1; color: var(--bp-navy); } +.wizard-preview-chain-kind { font-family: var(--bp-mono); font-size: 10px; padding: 1px 6px; border: 1px solid color-mix(in srgb, var(--bp-navy) 30%, transparent); } +.wizard-preview-chain-kind.kind-agent { background: color-mix(in srgb, var(--bp-amber) 25%, var(--bp-paper)); } +.wizard-preview-chain-kind.kind-system { background: color-mix(in srgb, var(--bp-navy) 12%, var(--bp-paper)); } +.wizard-preview-fields, .wizard-preview-rules { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 4px; font-size: 12px; } +.wizard-preview-fields li, .wizard-preview-rules li { padding: 4px 8px; border-left: 2px solid color-mix(in srgb, var(--bp-navy) 20%, transparent); } +.wizard-preview-field-name { font-weight: 600; color: var(--bp-navy); } +.wizard-preview-field-type { font-family: var(--bp-mono); font-size: 10px; color: var(--bp-muted); margin-left: 4px; } +.wizard-preview-empty { color: var(--bp-muted); font-style: italic; font-size: 11px; padding: 4px 0 !important; border-left: 0 !important; } + +@media (max-width: 700px) { + .wizard-body { padding: 0 12px 12px; } + .wizard-preview { position: static; max-height: none; } +} diff --git a/src/scenes/Wizard.tsx b/src/scenes/Wizard.tsx index cc29ca0..d5e27c2 100644 --- a/src/scenes/Wizard.tsx +++ b/src/scenes/Wizard.tsx @@ -235,15 +235,27 @@ export default function Wizard() { } } + const STEP_LABELS: Record = { + Intake: "Describe", + Analyze: "Steps", + Generate: "Form fields", + Validate: "Rules", + "Draft saved": "Review", + Publish: "Done", + }; + const renderStepNav = () => (
{STEPS.map((step, i) => { const isActive = step === draft.step; const isPast = STEPS.indexOf(step) < STEPS.indexOf(draft.step); + const isDone = isPast || draft.step === "Publish"; return ( -
- {i + 1} - {step} +
+ + {isDone ? : i + 1} + + {STEP_LABELS[step]} {i < STEPS.length - 1 && }
); @@ -251,6 +263,84 @@ export default function Wizard() {
); + const renderPreviewPane = () => { + if (draft.nodes.length === 0 && draft.fields.length === 0 && draft.rules.length === 0) return null; + return ( + + ); + }; + + const moveStep = (i: number, dir: -1 | 1) => { + const j = i + dir; + if (j < 0 || j >= draft.nodes.length) return; + const next = [...draft.nodes]; + [next[i], next[j]] = [next[j], next[i]]; + updateDraft({ nodes: next }); + }; + + const removeStep = (i: number) => { + if (draft.nodes.length <= 1) { + pushToast("err", "A process needs at least one step."); + return; + } + updateDraft({ nodes: draft.nodes.filter((_, idx) => idx !== i) }); + }; + + const addStep = () => { + const next = [...draft.nodes, { _key: `n${Date.now()}`, kind: "step", display_name: "New step", dispatch_kind: "human" }]; + updateDraft({ nodes: next }); + }; + return (
@@ -261,201 +351,207 @@ export default function Wizard() { {renderStepNav()}
-
- {draft.step === "Intake" && ( -
-

What process do you want to build?

-
- - updateDraft({ name: e.target.value })} - placeholder="e.g. Laptop Procurement" - /> +
+
+ {draft.step === "Intake" && ( +
+

What process do you want to build?

+
+ + updateDraft({ name: e.target.value })} + placeholder="e.g. Laptop Procurement" + /> +
+
+ +