Steps

Shows where the reader is in a flow of several steps: which are done, which is current, and which are still to come.

Installation

bash
npx @smicolon/fasla-ui@latest add steps

Run init once per project before adding components. See Installation.

Preview

  1. Cart, completed
  2. Shipping
  3. Payment, not started

Variants

Two bullet shapes: square or round.

Standard
  1. Cart, completed
  2. Shipping
  3. Payment, not started
Rounded
  1. Cart, completed
  2. Shipping
  3. Payment, not started

Orientation

Steps run in a row, or in a column when there are many steps or long labels.

Standard
  1. Cart, completed
  2. Shipping
  3. Payment, not started
Rounded
  1. Cart, completed
  2. Shipping
  3. Payment, not started

Icon and description

A done step can show a check instead of its number, and any step can have a description.

  1. Cart, completed3 items
  2. ShippingAddress
  3. Payment, not startedBy card
  1. Cart, completed3 items
  2. ShippingAddress and delivery
  3. Payment, not startedCard or wallet

Accessibility

  • Steps is an ordered list, so screen readers say how many steps there are and where each one sits.
  • The current step has aria-current="step", so screen readers say it is the current one.
  • Done and upcoming steps say their status after the label, "completed" or "not started", in the page's language. Change it with statusLabel.
  • The steps only show progress. None is a link or a button, so Tab never stops on them.
  • Direction is inherited from dir, never a prop. On a right-to-left page the first step is on the right. The numbers stay Western.

Props

Steps

PropTypeDefaultDescription
orientation"horizontal" | "vertical""horizontal"A row with the labels under the bullets, or a column with the labels beside them.
radius"standard" | "rounded""standard"The bullet shape for every step: an 8px square or a circle.
aria-labelstring—Names the list for screen readers, such as the name of the flow.
childrenReactNode—The steps, as StepsItems, in order. Each is numbered, and every step but the last gets a tail.
classNamestring—Extra classes for the list.

StepsItem

PropTypeDefaultDescription
status"done" | "current" | "upcoming""upcoming"Whether the step is done, current or still to come. Sets the bullet's and tail's colours, and aria-current on the current step.
labelReactNode—The step's name.
descriptionReactNode—A line of text under the label.
iconbooleanfalseShows a check instead of the number. Meant for done steps.
statusLabelstring—What screen readers hear after the label. Defaults to "completed" or "not started" in the page's language. "" turns it off.
classNamestring—Extra classes for the step.

Usage

Checkout steps

tsx
import { Steps, StepsItem } from "@/components/ui/steps"

export function CheckoutSteps() {
  return (
    <Steps aria-label="Checkout">
      <StepsItem status="done" label="Cart" />
      <StepsItem status="done" label="Shipping" />
      <StepsItem status="current" label="Payment" />
      <StepsItem status="upcoming" label="Review" />
    </Steps>
  )
}

Statuses from the current step

tsx
import { Steps, StepsItem } from "@/components/ui/steps"

const steps = ["Cart", "Shipping", "Payment", "Review"]

export function CheckoutProgress({ current }: { current: number }) {
  return (
    <Steps aria-label="Checkout" radius="rounded">
      {steps.map((label, index) => (
        <StepsItem
          key={label}
          label={label}
          status={index < current ? "done" : index === current ? "current" : "upcoming"}
          icon={index < current}
        />
      ))}
    </Steps>
  )
}

Vertical, with descriptions

tsx
import { Steps, StepsItem } from "@/components/ui/steps"

export function OrderSteps() {
  return (
    <Steps aria-label="Checkout" orientation="vertical">
      <StepsItem status="done" label="Cart" description="3 items" />
      <StepsItem status="done" label="Shipping" description="Address and delivery" />
      <StepsItem status="current" label="Payment" description="Card or wallet" />
      <StepsItem status="upcoming" label="Review" description="Check your order" />
    </Steps>
  )
}