Wizard
A multi-step form with a stepper header, the current panel and back/next actions; native buttons with aria-current="step".
stable · light DOM · 4.0.0. Light DOM retains static content, native semantics, label relationships and host composition without duplicating controls.
Live variants
numbered
Step 1 of 3: Project
Step 2 of 3: Preferences
Step 3 of 3: Review
All previous values remain available. Complete requests host handling; it does not send a network request.
<j3w1-wizard id="example-wizard-numbered"><div class="wizard" aria-label="Set up a local project"><ol class="wizard-steps"><li class="wizard-step"><button class="wizard-step-button" type="button" aria-current="step"><span class="wizard-step-marker" aria-hidden="true">1</span><span class="wizard-step-name">Project</span></button></li><li class="wizard-step"><button class="wizard-step-button" type="button" disabled=""><span class="wizard-step-marker" aria-hidden="true">2</span><span class="wizard-step-name">Preferences</span></button></li><li class="wizard-step"><button class="wizard-step-button" type="button" disabled=""><span class="wizard-step-marker" aria-hidden="true">3</span><span class="wizard-step-name">Review</span></button></li></ol><section class="wizard-panel" aria-labelledby="example-wizard-numbered-wizard-title-0"><h3 class="wizard-title" id="example-wizard-numbered-wizard-title-0">Step 1 of 3: Project</h3><label for="example-wizard-numbered-wizard-value-0">Project name</label><input class="text-field-input" id="example-wizard-numbered-wizard-value-0" name="example-wizard-numbered-step-0" required=""></section><section class="wizard-panel" aria-labelledby="example-wizard-numbered-wizard-title-1" hidden=""><h3 class="wizard-title" id="example-wizard-numbered-wizard-title-1">Step 2 of 3: Preferences</h3><label for="example-wizard-numbered-wizard-value-1">Preferences name</label><input class="text-field-input" id="example-wizard-numbered-wizard-value-1" name="example-wizard-numbered-step-1" required=""></section><section class="wizard-panel" aria-labelledby="example-wizard-numbered-wizard-title-2" hidden=""><h3 class="wizard-title" id="example-wizard-numbered-wizard-title-2">Step 3 of 3: Review</h3><p class="wizard-text">All previous values remain available. Complete requests host handling; it does not send a network request.</p></section><div class="wizard-actions"><button class="wizard-back" type="button">Back</button><button class="wizard-next" type="button">Next / complete</button></div></div></j3w1-wizard>icons
Step 1 of 4: Source
Step 2 of 4: Workspaces
Step 3 of 4: Bindings
Step 4 of 4: Review
All previous values remain available. Complete requests host handling; it does not send a network request.
<j3w1-wizard id="example-wizard-icons"><div class="wizard" aria-label="Set up a local project"><ol class="wizard-steps"><li class="wizard-step"><button class="wizard-step-button" type="button" aria-current="step"><span class="wizard-step-marker" aria-hidden="true">1</span><span class="wizard-step-name">Source</span></button></li><li class="wizard-step"><button class="wizard-step-button" type="button" disabled=""><span class="wizard-step-marker" aria-hidden="true">2</span><span class="wizard-step-name">Workspaces</span></button></li><li class="wizard-step"><button class="wizard-step-button" type="button" disabled=""><span class="wizard-step-marker" aria-hidden="true">3</span><span class="wizard-step-name">Bindings</span></button></li><li class="wizard-step"><button class="wizard-step-button" type="button" disabled=""><span class="wizard-step-marker" aria-hidden="true">4</span><span class="wizard-step-name">Review</span></button></li></ol><section class="wizard-panel" aria-labelledby="example-wizard-icons-wizard-title-0"><h3 class="wizard-title" id="example-wizard-icons-wizard-title-0">Step 1 of 4: Source</h3><label for="example-wizard-icons-wizard-value-0">Source name</label><input class="text-field-input" id="example-wizard-icons-wizard-value-0" name="example-wizard-icons-step-0" required=""></section><section class="wizard-panel" aria-labelledby="example-wizard-icons-wizard-title-1" hidden=""><h3 class="wizard-title" id="example-wizard-icons-wizard-title-1">Step 2 of 4: Workspaces</h3><label for="example-wizard-icons-wizard-value-1">Workspaces name</label><input class="text-field-input" id="example-wizard-icons-wizard-value-1" name="example-wizard-icons-step-1" required=""></section><section class="wizard-panel" aria-labelledby="example-wizard-icons-wizard-title-2" hidden=""><h3 class="wizard-title" id="example-wizard-icons-wizard-title-2">Step 3 of 4: Bindings</h3><label for="example-wizard-icons-wizard-value-2">Bindings name</label><input class="text-field-input" id="example-wizard-icons-wizard-value-2" name="example-wizard-icons-step-2" required=""></section><section class="wizard-panel" aria-labelledby="example-wizard-icons-wizard-title-3" hidden=""><h3 class="wizard-title" id="example-wizard-icons-wizard-title-3">Step 4 of 4: Review</h3><p class="wizard-text">All previous values remain available. Complete requests host handling; it does not send a network request.</p></section><div class="wizard-actions"><button class="wizard-back" type="button">Back</button><button class="wizard-next" type="button">Next / complete</button></div></div></j3w1-wizard>Install and register
Use the exact version. If npm publication is pending, install the release tarball from the installation guide.
npm install --save-exact @j3w1/ui@4.0.0import '@j3w1/ui/tokens.css';
import '@j3w1/ui/styles/wizard.css';
import '@j3w1/ui/register/wizard';Insert the maintained markup above after loading these imports. Its native children provide accessible names and form behavior; the empty custom tag alone does not create a control.
Copy the complete implementation
npx --package=@j3w1/ui@4.0.0 j3w1-ui copy wizard --out ./vendor/j3w1/wizardThe CLI verifies every file before writing and refuses overwrites. Serve the output over HTTP and open index.html. Keep its modules, CSS, tokens and licence notices together.
Public API
attributes
| Name | Type / signature | Meaning |
|---|---|---|
disabled | CustomEvent | Disable the native controls owned by this instance. |
loading | CustomEvent | Mark the primary control busy and prevent duplicate activation. |
properties
| Name | Type / signature | Meaning |
|---|---|---|
disabled | boolean | Delegates disabled state to native children. |
name | string | Native control name; application form keys remain explicit. |
step | number | Current zero-based step. |
methods
| Name | Type / signature | Meaning |
|---|---|---|
refresh | (): void | Reconnect behavior after replacing native child structure. |
focus | (options?: FocusOptions): void | Focus the first usable native control. |
next | (): boolean | Validate current native controls before advancing. |
back | (): void | Return without validation. |
events
| Name | Type / signature | Meaning |
|---|---|---|
j3w1-step | CustomEvent | The active step changed. |
j3w1-complete | CustomEvent | Final local validation succeeded; the host owns persistence. |
Dependencies and verification
Registered components: none. Style dependencies: text-field.
Package presence establishes an available implementation. Actual passes depend on the tested artifact and environment. Read specification execution evidence; read packed-consumer evidence; inspect the complete state matrix.
Full implementation manifest, API and token dependency closure
Canonical specification
Wizard wizard
A multi-step form with a stepper header, the current panel and back/next actions; native buttons with aria-current="step".
Report an issue with this component
Tokens
Focus a role to inspect its values; follow its link for persistent usage and source details.
| Part | Role | Value | Use |
|---|---|---|---|
steps.divider | color.border.dividerapproveduse | #482b2b | D-041 border.divider: color.primitive.modern.divider. |
step.text | color.text.defaultapproveduse | #e99499 | D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills. |
step.bg-hover | color.interaction.hover.bgapproveduse | #1c1010 | D-041 interaction.hover.bg: color.primitive.modern.hover. |
step.ring | color.interaction.focus.ringobserveduse | #e53935 | 1px dashed focus ring on controls and rows. |
step.text-current | color.text.brightapproveduse | #ffa2a7 | D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills. |
step.indicator-current | color.border.selected-indicatorobserveduse | #e53935 | 2px indicator bar on the selected tab or nav item. |
step.text-disabled | color.text.disabledapproveduse | #a3676b | D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills. |
step.marker-complete | color.status.success.textapproveduse | #82d9a0 | D-041 status.success.text: color.primitive.modern.green. |
step.marker-invalid | color.status.danger.textobserveduse | #f07178 | D-041 readable error text on neutral surfaces and native warning tints. |
step.indicator-invalid | color.status.danger.borderobserveduse | #e53935 | Danger border, 2px on invalid inputs. |
panel.bg | color.surface.defaultapproveduse | #0d0707 | D-041 surface.default: color.primitive.modern.panel. |
panel.border | color.border.defaultapproveduse | #482b2b | D-041 border.default: color.primitive.modern.divider. |
title.text | color.text.brightapproveduse | #ffa2a7 | D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills. |
text.text | color.text.defaultapproveduse | #e99499 | D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills. |
message.text | color.status.danger.textobserveduse | #f07178 | D-041 readable error text on neutral surfaces and native warning tints. |
next.bg | color.action.primary.bgapproveduse | #7d1310 | Primary button fill; D-026 darkened it off color12, which stays fixed as heritage ANSI 12. |
next.text | color.action.primary.textapproveduse | #ffa2a7 | Primary action labels: bright rose across rest, hover and pressed states (D-033). |
next.bg-hover | color.action.primary.hover-bgobserveduse | #911410 | Primary button hover; pair with action.primary.text (D-033). |
next.bg-pressed | color.action.primary.pressed-bgobserveduse | #630f0d | Primary button pressed. |
next.border | color.action.primary.borderobserveduse | #9e231f | Primary button border. |
next.ring | color.interaction.focus.ring-containerobserveduse | #ffa2a7 | Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry. |
back.text | color.action.secondary.textapproveduse | #ffa2a7 | D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills. |
back.border | color.action.secondary.borderapproveduse | #986f72 | D-041 action.secondary.border: color.primitive.modern.control. |
back.bg-hover | color.action.secondary.hover-bgobserveduse | #630f0d | Secondary button hover. |
busy.glyph | color.action.primary.textapproveduse | #ffa2a7 | Primary action labels: bright rose across rest, hover and pressed states (D-033). |
State matrix
Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).
| State | Numbered steps | Glyph markers |
|---|---|---|
default | Step 2 of 3: TokensChoose the profile the tokens resolve against. The extended overlay can be added later. | Step 3 of 4: BindingsKeep the existing hjkl bindings or replace them with the imported set. |
hover | ||
focus-visible | ||
current | ||
disabled | ||
invalid | ||
busy |
Purpose
A form too long for one screen, split into ordered steps validated one at a time. Steps are not tabs: a future step is unreachable until the steps before it pass.
Anatomy
Parts as listed in the anatomy; the panel heading reads “Step n of m”.
States
| State | Visual | Non-colour channel |
|---|---|---|
| default | steps in color.text.default; complete steps carry ✓ in color.status.success.text | the ✓ glyph; the numbers |
| hover | step → color.interaction.hover.bg; Next → color.action.primary.hover-bg; Back → color.action.secondary.hover-bg | cursor: pointer |
| focus-visible | 1px dashed color.interaction.focus.ring ring at −2px; color.interaction.focus.ring-container on Next’s fill | the ring |
| current | 2px color.border.selected-indicator under the step; name in color.text.bright | aria-current="step"; the indicator bar; the heading reads “Step n of m” |
| disabled | a future step in color.text.disabled; no hover | disabled; cursor: not-allowed; skipped by Tab |
| invalid | marker becomes ✕ in color.status.danger.text; indicator color.status.danger.border; the panel shows the message | glyph; message text; aria-invalid on the failing fields |
| busy | Next shows the static ⋯ before its label and ignores activation; size unchanged | aria-busy on the wizard; the glyph; cursor: progress |
Precedence: disabled > busy > invalid > current > hover; focus-visible is always drawn.
Keyboard
As in the key table. A failed Next moves focus to the first invalid field; a successful one to the new panel heading. No arrow keys between steps: the stepper is a list of buttons, not a tablist.
Accessibility
The wizard is a region named by aria-label; the <ol> announces count and
position. Complete steps append a visually hidden ”, complete”. Unreachable
steps are disabled, not aria-disabled, because they cannot be activated.
Validation failures are announced through the form’s live region and the ✕
marker. Text meets 4.5:1; the indicator and rings 3:1; future step text is
exempt (house floor 3:1).
Portability
Text, a 2px bottom border and the button tones; markers are text glyphs, no icon font. A toolkit without a native assistant draws the stepper as a row of buttons and records any deviation in the indicator width.
Non-examples
Tabs restyled as steps. A progress bar instead of the stepper. Circles with connecting lines that need a radius. Future steps that look enabled and reject the click. A spinner on Next. Colour-only completion marks. Validation that blocks Back. Animated slides between panels.
Contrast report
19 declared pairs measured on resolved sRGB values with the WCAG 2.x formula; 1 waived (decorative only), 0 failing. A pass is a design target for the named role, not an application-wide conformance claim.
| Pair | State | Kind | Foreground | Background | Ratio | Min | Result |
|---|---|---|---|---|---|---|---|
| wizard default text | default | text | color.text.default #e99499 | color.surface.canvas #000000 | 9.16 | 4.5 | pass |
| wizard hover text | hover | text | color.text.default #e99499 | color.interaction.hover.bg #1c1010 | 8.10 | 4.5 | pass |
| wizard focus-visible text | focus-visible | text | color.text.bright #ffa2a7 | color.surface.canvas #000000 | 10.98 | 4.5 | pass |
| wizard focus-visible outline | focus-visible | ui | color.interaction.focus.ring #e53935 | color.surface.canvas #000000 | 4.97 | 3 | pass |
| wizard current text | current | text | color.text.bright #ffa2a7 | color.surface.canvas #000000 | 10.98 | 4.5 | pass |
| wizard current border | current | ui | color.border.selected-indicator #e53935 | color.surface.canvas #000000 | 4.97 | 3 | pass |
| wizard invalid text | invalid | text | color.status.danger.text #f07178 | color.surface.canvas #000000 | 7.34 | 4.5 | pass |
| wizard invalid border | invalid | ui | color.status.danger.border #e53935 | color.surface.canvas #000000 | 4.97 | 3 | pass |
| wizard busy text | busy | text | color.action.primary.text #ffa2a7 | color.action.primary.bg #7d1310 | 5.57 | 4.5 | pass |
| complete marker on the canvas | — | text | color.status.success.text #82d9a0 | color.surface.canvas #000000 | 12.38 | 4.5 | pass |
| panel title on the panel surface | — | text | color.text.bright #ffa2a7 | color.surface.default #0d0707 | 10.45 | 4.5 | pass |
| panel text on the panel surface | — | text | color.text.default #e99499 | color.surface.default #0d0707 | 8.72 | 4.5 | pass |
| step message on the panel surface | — | text | color.status.danger.text #f07178 | color.surface.default #0d0707 | 6.98 | 4.5 | pass |
| panel edge (decorative) | — | ui | color.border.default #482b2b | color.surface.canvas #000000 | 1.66 | 1 | pass |
| back button text | — | text | color.action.secondary.text #ffa2a7 | color.surface.canvas #000000 | 10.98 | 4.5 | pass |
| back button boundary | — | ui | color.action.secondary.border #986f72 | color.surface.canvas #000000 | 4.85 | 3 | pass |
| next button boundary | — | ui | color.action.primary.border #9e231f | color.surface.canvas #000000 | 2.71 | 3 | waived: the primary button is identified by its text on the fill and by its position; the low-contrast fill and border against the canvas are a documented property of the actions family |
| ring on the next button's fill | focus-visible | ui | color.interaction.focus.ring-container #ffa2a7 | color.action.primary.bg #7d1310 | 5.57 | 3 | pass |
| future step text (exempt; house floor 3:1) | disabled | ui | color.text.disabled #a3676b | color.surface.canvas #000000 | 4.71 | 3 | pass |
Keys
| Key | Action |
|---|---|
| Tab / Shift+Tab | Reaches each enabled step button, the panel's fields, then Back and Next; future steps are disabled and skipped. |
| Enter / Space | On a step button, goes to that step if it is reachable; on Next, validates the panel and advances; on Back, returns without validating. |
| Escape | Nothing; leaving a wizard is an explicit Cancel or the host's navigation. |
For agents
Component JSON ·Implementation brief ·Build a task kit ·
Related: button fieldset tabs breadcrumbs progress admin-form
Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-STATE-MATRIX