useStepper
A hook that manages stepper state, step navigation, and ARIA attributes.
Usage#
import { useStepper } from '@primereact/headless/stepper';
const stepper = useStepper({ defaultValue: '1' });
const { rootProps, state } = stepper;
return (
<div {...rootProps}>
<div {...stepper.getItemProps({ active: true })}></div>
<div {...stepper.getStepProps({ active: true, disabled: false })}></div>
<button {...stepper.getHeaderProps({ activeValue: '1', disabled: false })}></button>
{stepper.isStepActive('1') && <div {...stepper.getPanelProps({ active: true, activeValue: '1' })}></div>}
</div>
);useStepper manages active step state and returns spread-ready prop objects for each DOM element — see Primitive for a component-based API.
Features#
- Single-hook architecture with getter functions for per-element props (
rootProps,getItemProps,getStepProps,getHeaderProps,getPanelProps) - Controlled and uncontrolled value management
- Linear mode to restrict free navigation between steps
- Exposes
state,setActiveStep,isStepActive, andisStepDisabledfor custom logic
Behavior#
Default Value#
Use defaultValue to set the initially active step.
const stepper = useStepper({ defaultValue: '1' });Controlled#
Use value and onValueChange for full programmatic control. The hook never updates its own state in controlled mode.
const [value, setValue] = React.useState<string | number | null>('1');
const stepper = useStepper({
value,
onValueChange: (e) => setValue(e.value)
});The onValueChange callback receives { value } where value is the new active step key.
Linear#
Set linear to restrict step navigation. When enabled, isStepDisabled() returns true for inactive steps and getHeaderProps sets tabIndex to -1 on disabled headers.
const stepper = useStepper({ linear: true, defaultValue: '1' });Use setActiveStep to programmatically navigate between steps in linear mode (e.g., via Next/Back buttons).
Vertical Layout#
The hook itself is layout-agnostic. For a vertical stepper, use Stepper.Item to group each step header and panel together, with the separator and content nested inside the panel area.
<div {...rootProps}>
<div {...stepper.getItemProps({ active })}>
<div {...stepper.getStepProps({ active, disabled })}>
<button {...stepper.getHeaderProps({ activeValue: '1', disabled })}>Step 1</button>
</div>
{stepper.isStepActive('1') && (
<div {...stepper.getPanelProps({ active: true, activeValue: '1' })}>
<span>Separator</span>
<div>Panel content</div>
</div>
)}
</div>
</div>Using setActiveStep and isStepActive#
The hook exposes imperative methods for custom logic outside the standard header click flow.
const stepper = useStepper({ defaultValue: '1' });
// Programmatically navigate to a step
stepper.setActiveStep('3');
// Check if a step is active
if (stepper.isStepActive('2')) {
// ...
}Custom Styling with Data Attributes#
Every prop object includes data-scope="stepper" and a data-part attribute. data-active is present only on active elements; data-disabled is added automatically when applicable.
[data-scope='stepper'][data-part='step'][data-active] {
background-color: var(--primary);
}
[data-scope='stepper'][data-part='header'][disabled] {
opacity: 0.5;
pointer-events: none;
}
[data-scope='stepper'][data-part='panel'][data-active] {
display: block;
}API#
useStepper#
| Name | Type | Default |
|---|---|---|
defaultValue | string | number | — |
| Default value of the active step. | ||
value | string | number | — |
| Value of the active step. | ||
linear | boolean | false |
| Whether the steps are clickable or not. | ||
onValueChange | (event: useStepperChangeEvent) => void | — |
| Callback fired when the stepper's value changes. | ||
Accessibility#
See Stepper Primitive for WAI-ARIA compliance details and keyboard support.