J3W1 / DESIGN SYSTEM
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 · 1.1.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@1.1.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@1.1.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
Purpose
A form too long for one screen, split into ordered steps that are validated one at a time. The stepper shows where the person is and which steps are complete; the panel holds the current step; Back and Next move through the sequence. Steps are not tabs: a future step is unreachable until the steps before it pass.
Anatomy
The stepper, an ordered list of step buttons over a color.border.divider
rule; each step’s marker and name; the panel on color.surface.default with
its “Step n of m” heading in color.text.bright; the actions row with Back
(secondary) and Next (primary, color.action.primary.bg with
color.action.primary.text).
States
| State | Visual | Non-colour channel |
|---|---|---|
| default | steps in color.text.default; complete steps carry the ✓ in color.status.success.text | the ✓ glyph; the numbers |
| hover | step background → color.interaction.hover.bg; Next → color.action.primary.hover-bg; Back → color.action.secondary.hover-bg | cursor: pointer |
| focus-visible | ring 1px dashed color.interaction.focus.ring at −2px; on Next’s fill the ring takes color.interaction.focus.ring-container | 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 | the step’s marker becomes ✕ in color.status.danger.text; its indicator takes color.status.danger.border; the panel shows the message | glyph; message text; aria-invalid on the failing fields |
| busy | Next shows the static ⋯ glyph before its label and does not respond; size unchanged | aria-busy on the wizard; the glyph; cursor: progress |
Precedence when several apply: disabled > busy > invalid > current > hover; focus-visible is always drawn.
Keyboard
Tab walks the enabled step buttons in order, then the panel’s fields, then Back and Next. Enter or Space on a reachable step goes to it; on Next it validates the panel, and on failure moves focus to the first invalid field, on success advances and moves focus to the new panel heading. Back never validates. There is no arrow-key navigation between steps, because the stepper is a list of buttons, not a tablist.
Accessibility
The wizard is a region named by aria-label; the stepper is an <ol> so
count and position are announced; the current step carries
aria-current="step"; complete steps append visually hidden ”, complete”;
unreachable steps are disabled, not aria-disabled, because they cannot be
activated. The panel is a <section> named by its heading, which receives
focus after each step change. Validation failures are announced through the
form’s live region and the ✕ marker; aria-busy marks the wizard while Next
is in progress. Contrast: step text 8.65:1, current name 10.37:1, complete
marker 7.13:1, indicator 4.69:1, Next text 9.28:1 on its fill, ring 5.57:1 on
the primary fill, future step text 3.33:1 (exempt).
Portability
Everything is text, a 2px bottom border and the button tones; no icon font (the markers are text glyphs). Toolkits with a native assistant use its page list and map the indicator to the current page; toolkits with none draw the stepper as a row of buttons and record any deviation in the indicator width.
Non-examples
Tabs restyled as steps. A progress bar in place of the stepper. Circles with connecting lines that need a rounded 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.