Getting StartedInstall and bootstrap headless foundations 4
LayoutHeadless structural primitives for expandable and container patterns 6
OverlayHeadless modal and floating layer behavior 3
FeedbackHeadless notification and status communication patterns 5
FormHeadless input and selection contracts 17
UtilityReusable action, identity, and clipboard behavior 6
NavigationHeadless trails, trees, menus, and command surfaces 7

Stepper overview

Headless stepper models ordered progress through a list of steps. It owns value, roving focus, activation policy, and state attributes while leaving the markup and visual treatment to your application.

Primitive import

ts
import {
  TngStepper,
  TngStepperConnector,
  TngStepperDescription,
  TngStepperItem,
  TngStepperLabel,
  TngStepperPanel,
  TngStepperTrigger,
} from '@tailng-ui/primitives';

Basic composition

Attach tngStepper to the flow root, render an ordered list of tngStepperItem rows, and put a focusable tngStepperTrigger inside each row. Labels, descriptions, panels, and connectors are composable hooks.

Headless stepper composition

html
<section tngStepper ariaLabel="Release flow" defaultValue="review" linear>
  <ol class="workflow-steps">
    <li tngStepperItem value="draft" label="Draft" completed>
      <button tngStepperTrigger>
        <span tngStepperLabel>Draft</span>
      </button>
      <span tngStepperConnector></span>
    </li>
    <li tngStepperItem value="review" label="Review">
      <button tngStepperTrigger>
        <span tngStepperLabel>Review</span>
        <span tngStepperDescription>Current step</span>
      </button>
      <span tngStepperConnector></span>
      <section tngStepperPanel>Review content</section>
    </li>
    <li tngStepperItem value="publish" label="Publish">
      <button tngStepperTrigger>
        <span tngStepperLabel>Publish</span>
      </button>
    </li>
  </ol>
</section>

Style variants

The same headless stepper root rendered through a local CSS contract or a Tailwind utility shell.

Headless stepper (plain CSS)

Accessibility baseline

  • Give the root an accessible name with ariaLabel or ariaLabelledby.
  • The current trigger receives aria-current="step" and a position label.
  • Disabled or blocked triggers expose aria-disabled="true".
  • Keyboard users move through enabled triggers with arrows, Home, End, Enter, and Space.