LayoutReact
The steps of a process, one shown at a time, with the current step marked and the steps before it completed.
Rendered by React 19.3.1
Loading React…Installation
npm i @hamur/reactNot on npm yet. The package goes out under the chosen name.
Anatomy
Import the component and assemble its parts:
<Stepper.Root>
<Stepper.List>
<Stepper.Item>
<Stepper.Trigger>
<Stepper.Indicator />
<Stepper.Title />
</Stepper.Trigger>
<Stepper.Separator />
</Stepper.Item>
</Stepper.List>
<Stepper.Panel />
<Stepper.Previous />
<Stepper.Value />
<Stepper.Next />
</Stepper.Root>
// Not in this example: Stepper.DescriptionExamples
Tabs
pattern="tabs" with linear={false}: four steps of a new project, one optional, moved between with the arrow keys; the controlled value is shown below.
Form
A sign-up inside a Form: Next refuses a step while its required field is empty and focuses it, and the last step submits every step's values.
Vertical
orientation="vertical": each step's panel under its title, with a Description and Back and Continue inside the panel; the last step is optional.
API reference
27 props across 12 parts, in React syntax. className, style, render are listed once, under Shared props.
DescriptionStepper.Description
A description of the step, which describes its Trigger. Renders a <span>.
IndicatorStepper.Indicator
The step's marker, hidden from assistive technology. Shows the step's 1-based position unless it has children. Renders a <span>.
ItemStepper.Item
A step of the process: its Trigger, Indicator, Title, Description and Separator, and in pattern="list" its Panel too. Renders a <li>.
| Prop | Type | Default |
|---|---|---|
valuerequiredThe value of the step. | any | — |
disabledWhether the step cannot be activated. | boolean | false |
optionalWhether the step does not block reaching the steps after it. | boolean | false |
completedWhether the step is completed, overriding the state the Root tracks. | boolean | — |
invalidWhether the step has errors: it shows the error state and, with linear, refuses a forward | boolean | — |
labelThe step's name in announcements. | string | — |
| Data attribute | Description |
|---|---|
data-index | The 0-based position of the step. |
data-current | Present when the step is the current one. |
data-completed | Present when the step is completed. |
data-invalid | Present when the step has errors. |
data-optional | Present when the step is optional. |
data-disabled | Present when the step is disabled. |
data-unreachable | Present when the step cannot be reached yet. |
data-orientation | Indicates the orientation of the stepper. |
ListStepper.List
The list of steps: an ordered list, or the tablist in pattern="tabs". Renders an <ol>.
NextStepper.Next
Goes to the next enabled step, validating the current one with linear. It is never a submit button, and is aria-disabled, not disabled, at the last enabled step. Renders a <button>.
| Prop | Type | Default |
|---|---|---|
nativeButtonWhether the component renders a native <button> element when replacing it | boolean | true |
focusableWhenDisabledWhether the button stays focusable while it is disabled, with aria-disabled. | boolean | true |
PanelStepper.Panel
The content of a step, shown while it is current: a group in pattern="list", a tabpanel in pattern="tabs", labelled by the step's Title. Renders a <div>.
| Prop | Type | Default |
|---|---|---|
valuerequiredThe value of the step this panel belongs to. | any | — |
keepMountedWhether to keep the element in the DOM while the step is not current, so its fields keep | boolean | true |
initialFocusThe element to focus when a move made from inside the stepper shows this panel. | boolean | React.RefObject<HTMLElement | null> | (() => boolean | void | HTMLElement | null) | true |
| Data attribute | Description |
|---|---|
data-index | The 0-based position of the panel's step. |
data-hidden | Present when the panel is hidden. |
data-current | Present when the panel's step is the current one. |
data-completed | Present when the panel's step is completed. |
data-invalid | Present when the panel's step has errors. |
data-orientation | Indicates the orientation of the stepper. |
data-activation-direction | Indicates the direction of the last step change. |
data-starting-style | Present when the panel begins animating in. |
data-ending-style | Present when the panel is animating out. |
PreviousStepper.Previous
Goes to the previous enabled step, without validating. It is aria-disabled, not disabled, at the first enabled step, so it keeps focus. Renders a <button>.
| Prop | Type | Default |
|---|---|---|
nativeButtonWhether the component renders a native <button> element when replacing it | boolean | true |
focusableWhenDisabledWhether the button stays focusable while it is disabled, with aria-disabled. | boolean | true |
RootStepper.Root
Groups all parts of the stepper: the steps of a process, their panels and the Previous and Next buttons., followed by the status region. Renders a <div>.
| Prop | Type | Default |
|---|---|---|
valueThe value of the current step. | any | — |
defaultValueThe value of the step that is current when the stepper is first rendered. | any | 0 |
onValueChangeEvent handler called before the current step changes. | ((value: any, eventDetails: StepperRootChangeEventDetails) => void) | — |
patternThe pattern of the stepper. | StepperPattern | 'list' |
linearWhether a forward move validates the current step and is refused while it is invalid, and a | boolean | true |
orientationThe orientation of the step list. | StepperOrientation | 'horizontal' |
loopFocus'tabs' only: whether the arrow keys wrap at the ends of the list. | boolean | false |
disabledWhether the component should ignore user interaction. | boolean | false |
getStepHref'list' only: the href of each step. | ((value: any) => string) | — |
actionsRefA ref to move and validate from the app. | React.RefObject<StepperRootActions | null> | — |
labelsThe texts of the status region, the Value part and the state of each Title. | Partial<StepperLabels> | — |
| Data attribute | Description |
|---|---|
data-orientation | Indicates the orientation of the stepper. |
data-pattern | Indicates the pattern of the stepper. |
data-linear | Present when a forward move validates the current step. |
data-disabled | Present when the stepper is disabled. |
SeparatorStepper.Separator
The line between steps, hidden from assistive technology and styled by its step's state. Renders a <div>.
TitleStepper.Title
The step's name: it names the Trigger and the Panel, and ends with a visually hidden text of the step's state (completed, error, optional). Renders a <span>.
TriggerStepper.Trigger
Activates its step and is named by the step's Title: a button, a tab in pattern="tabs", or a link when the Root has getStepHref., or an <a> element with getStepHref. Renders a <button>.
| Prop | Type | Default |
|---|---|---|
nativeButtonWhether the component renders a native <button> element when replacing it | boolean | true |
focusableWhenDisabledWhether the Trigger stays focusable while its step is disabled or cannot be reached, with | boolean | true |
ValueStepper.Value
The current step's position as text: "Step 2 of 4". Plain text, not a live region. Renders a <span>.
| Prop | Type | Default |
|---|---|---|
childrenThe text, or a function of the current step's position, the number of steps, its value and | React.ReactNode | ((values: StepperValueValues) => React.ReactNode) | — |
Shared props
Every part that renders an element takes these.
| Prop | Type |
|---|---|
classNameCSS class applied to the element, or a function that
returns a class based on the component's state. | string | ((state: State) => string | undefined) |
styleStyle applied to the element, or a function that
returns a style object based on the component's state. | React.CSSProperties | ((state: State) => React.CSSProperties | undefined) |
renderAllows you to replace the component's HTML element
with a different tag, or compose it with another component. | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, State> |
Keyboard and accessibility
Keyboard
| Keys | Does | Part |
|---|---|---|
| Tab | In 'list', moves through every step's button; the arrow keys do nothing | Trigger |
| Tab | In 'tabs', enters the list on the current step's tab | List |
| ArrowRightArrowLeft | In 'tabs', moves to the next or previous tab without changing the step | List |
| ArrowDownArrowUp | In vertical 'tabs', moves to the next or previous tab | List |
| HomeEnd | In 'tabs', moves to the first or last tab | List |
| EnterSpace | In 'tabs', shows the focused tab's step, validating the current one first | Trigger |
Accessibility
| Part | Sets | So that |
|---|---|---|
| List | the native ol; role="tablist" in 'tabs', with aria-orientation when vertical | the steps are read as a numbered list, or as tabs; a development build warns without a name |
| Item | the native li; role="presentation" in 'tabs' | the count of steps comes from the list |
| Trigger | a button with aria-current="step" on the current step in 'list', or role="tab" with aria-selected in 'tabs'; aria-disabled while unreachable | the current step is announced, and a step that cannot be reached says so |
| Title | the Trigger's name, plus a visually hidden ", completed", ", error" or ", optional" | a step's state is read with its name, not only shown by its color or icon |
| Description | the Trigger's aria-describedby | the hint is read after the name |
| Indicator | aria-hidden | the number and the check are not read twice |
| Separator | aria-hidden | the line between steps is for sight |
| Panel | role="group" named by its Title, tabindex="-1"; a tabpanel in 'tabs'; hidden and inert while not current | focus can move to the new step, and a hidden step's fields are out of reach |
| Root | one polite role="status" region after the stepper, always mounted | a change of step is announced ("Step 2 of 3: Shipping"), since readers do not announce aria-current moving |
Focus order
- In
'list'every step's button is a Tab stop, in the list's order, then the panel's fields, thenPreviousandNext. - In
'tabs'the list is one Tab stop on the current step's tab; the arrow keys,HomeandEndmove between tabs, andEnterorSpaceshows one. PreviousandNextstay focusable at their bounds, witharia-disabled, so a reader does not lose their place.