Skip to main content

Steps

Overview​

The Steps component provides a multi-step progress indicator for wizard flows, checkout processes, or any multi-step workflow.

It supports horizontal and vertical layouts, customizable markers, and clickable navigation.


Import​

import { Steps } from '@allxsmith/bestax-bulma';

Usage​

Basic Steps​

A simple step indicator showing progress through a flow.

<Steps
  value={1}
  items={[{ label: 'Account' }, { label: 'Profile' }, { label: 'Complete' }]}
/>


Clickable Steps​

Steps that allow navigation by clicking.

function example() {
  const [step, setStep] = useState(1);
  return (
    <Block>
      <Steps
        value={step}
        items={[
          { label: 'Account', clickable: true },
          { label: 'Profile', clickable: true },
          { label: 'Review', clickable: true },
          { label: 'Complete', clickable: true },
        ]}
        onStepClick={setStep}
        color="primary"
      />
      <Paragraph mt="4">Current step: {step + 1}</Paragraph>
    </Block>
  );
}


Color Variants​

Steps with different color variants.

<Block display="flex" flexDirection="column">
  <Steps
    value={1}
    color="primary"
    items={[{ label: 'Step 1' }, { label: 'Step 2' }, { label: 'Step 3' }]}
  />
  <Steps
    value={1}
    color="success"
    items={[{ label: 'Step 1' }, { label: 'Step 2' }, { label: 'Step 3' }]}
  />
  <Steps
    value={1}
    color="info"
    items={[{ label: 'Step 1' }, { label: 'Step 2' }, { label: 'Step 3' }]}
  />
  <Steps
    value={1}
    color="warning"
    items={[{ label: 'Step 1' }, { label: 'Step 2' }, { label: 'Step 3' }]}
  />
  <Steps
    value={1}
    color="danger"
    items={[{ label: 'Step 1' }, { label: 'Step 2' }, { label: 'Step 3' }]}
  />
</Block>


Size Variants​

Steps with different size variants.

<Block display="flex" flexDirection="column">
  <Steps
    value={1}
    size="small"
    items={[{ label: 'Step 1' }, { label: 'Step 2' }, { label: 'Step 3' }]}
  />
  <Steps
    value={1}
    items={[{ label: 'Step 1' }, { label: 'Step 2' }, { label: 'Step 3' }]}
  />
  <Steps
    value={1}
    size="medium"
    items={[{ label: 'Step 1' }, { label: 'Step 2' }, { label: 'Step 3' }]}
  />
  <Steps
    value={1}
    size="large"
    items={[{ label: 'Step 1' }, { label: 'Step 2' }, { label: 'Step 3' }]}
  />
</Block>


With Icons​

Steps with custom icons in markers.

<Steps
  value={1}
  color="info"
  items={[
    { label: 'Cart', icon: <Icon name="shopping-cart" variant="solid" /> },
    { label: 'Shipping', icon: <Icon name="truck" variant="solid" /> },
    { label: 'Payment', icon: <Icon name="credit-card" variant="solid" /> },
    { label: 'Done', icon: <Icon name="check" variant="solid" /> },
  ]}
/>


Vertical Layout​

Steps in vertical orientation.

<Steps
  value={1}
  vertical
  color="primary"
  items={[
    { label: 'Create Account' },
    { label: 'Set Up Profile' },
    { label: 'Choose Plan' },
    { label: 'Start Using' },
  ]}
/>


Rounded Markers​

Steps with rounded (circular) markers.

<Steps
  value={2}
  rounded
  color="success"
  items={[
    { label: 'Order Placed' },
    { label: 'Processing' },
    { label: 'Shipped' },
    { label: 'Delivered' },
  ]}
/>


Checkout Flow Example​

A complete checkout flow with navigation buttons.

function example() {
  const [step, setStep] = useState(0);
  const steps = ['Cart', 'Shipping', 'Payment', 'Confirm'];

  return (
    <Block>
      <Steps
        value={step}
        items={steps.map((label, i) => ({ label, clickable: i <= step }))}
        onStepClick={s => s <= step && setStep(s)}
        color="primary"
      />
      <Box mt="4" p="4">
        <Title size="5">{steps[step]}</Title>
        <Paragraph>Content for the {steps[step]} step goes here.</Paragraph>
      </Box>
      <Buttons mt="4">
        <Button
          onClick={() => setStep(Math.max(0, step - 1))}
          disabled={step === 0}
        >
          Previous
        </Button>
        <Button
          color="primary"
          onClick={() => setStep(Math.min(3, step + 1))}
          disabled={step === 3}
        >
          {step === 2 ? 'Place Order' : 'Next'}
        </Button>
      </Buttons>
    </Block>
  );
}


Right-to-Left​

In a right-to-left page the steps run from the right, and the lines and the label gaps follow them. labelPosition="right" and "left" mean the end and the start of the line, so in this vertical example each label sits to the left of its marker.

<div dir="rtl" lang="ar">
  <Steps
    value={1}
    color="primary"
    items={[{ label: 'الحساب' }, { label: 'الملف الشخصي' }, { label: 'تم' }]}
  />
  <Steps
    value={1}
    vertical
    labelPosition="right"
    color="primary"
    items={[{ label: 'الحساب' }, { label: 'الملف الشخصي' }, { label: 'تم' }]}
  />
</div>


Compound (dot-notation) usage​

Step is also available as Steps.Step, so steps can be declared as children from the single Steps import — an alternative to the items prop.

<Steps value={1}>
  <Steps.Step label="Account" />
  <Steps.Step label="Profile" />
  <Steps.Step label="Complete" />
</Steps>


Accessibility​

  • The active step has aria-current="step", on its list item, or on its button when it's clickable
  • A clickable step stays a list item and puts its marker and label in a <button type="button"> inside it, so the list keeps its list items and assistive technology can count them. The button takes Tab, Enter and Space, and the focus ring goes around the whole step, which is what you can click
  • The list has role="list". That's the role a <ul> already has, set again for Safari, whose WebKit stops exposing a <ul> as a list once its markers are hidden, as they are here, unless the role is written out
  • Use descriptive labels for each step
  • The step markers show completion state with checkmarks
  • In forced colors (Windows' contrast themes), the lines and a completed step's fill are drawn in the theme's text color, and the current step's marker gets an outline, so completed, current and upcoming steps still look different without color

  • Progress - For linear progress indication

Additional Resources​

Pro Tip

Use the onStepClick callback with clickable: true on items to allow users to navigate back to previous steps.


Props​

PropTypeDefaultDescription
valuenumber0Current active step (0-indexed).
itemsStepItemProps[]—Array of step items.
size'small' | 'medium' | 'large'—Size of the steps.
color'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger'—Color variant.
hasMarkerbooleantrueShow step markers. Default: true.
animatedbooleantrueEnable animations. Default: true.
roundedbooleantrueUse rounded markers. Default: true.
verticalbooleanfalseVertical layout.
labelPosition'bottom' | 'right' | 'left''bottom'Position of labels. right and left mean the end and the start of the line, so in a right-to-left page right puts each label to the left of its marker, and left to the right.
mobileMode'minimal' | 'compact' | 'right'—Mobile display mode.
showStepNumbersbooleantrueDisplays step numbers in the markers.
hasNavigationbooleanfalseShows previous/next navigation buttons. They render type="button", so a multi-step form wrapped around the steps is not submitted by moving between them.
prevLabelstring—Label for the previous button.
nextLabelstring—Label for the next button.
onPrev() => void—Callback when previous button is clicked.
onNext() => void—Callback when next button is clicked.
onStepClick(step: number) => void—Callback when a step is clicked.
childrenReact.ReactNode—Step children (alternative to items).
classNamestring—Additional CSS classes.
...All standard <div> attributes and Bulma helper props—See Helper Props

Subcomponents:

  • Steps.Step: Individual Step component for use inside Steps.

Steps.Step​

PropTypeDefaultDescription
isActivebooleanfalseWhether this step is active
isCompletedbooleanfalseWhether this step is completed
labelReact.ReactNode—Step label/title, or pass it as children. On a clickable step it's rendered inside the step's <button>, so it has to be phrasing content, like text, a <span> or an icon, with no link, button or other control in it.
iconReact.ReactNode—Icon for the step marker
clickablebooleanfalseWhether this step is clickable. A clickable step puts its marker and label in a <button type="button"> inside the <li>, which calls onClick, and aria-current goes on that button. The <li> keeps the rest of the props.
onClick() => void—Click handler
stepNumbernumber—Step number to display in marker (1-indexed)
completedIconReact.ReactNode'✓'Icon shown when the step is completed.
classNamestring—Additional CSS classes.
childrenReact.ReactNode—Content rendered inside the component.
...All standard <li> attributes and Bulma helper props—See Helper Props

StepItemProps​

PropTypeDefaultDescription
labelReact.ReactNode—Step label/title. On a clickable step it's rendered inside the step's <button>, so it has to be phrasing content, like text, a <span> or an icon, with no link, button or other control in it.
iconReact.ReactNode—Icon for the step marker.
clickablebooleanfalseWhether this step is clickable. A clickable step puts its marker and label in a <button type="button"> inside its list item, which calls onStepClick.
completedIconReact.ReactNode'✓'Icon shown when the step is completed.
classNamestring—Additional class for this step.

CSS & Sass Variables​

Steps registers these variables on its own .steps element. Override them there (or via className) — a value set on an ancestor is only inherited, and loses to the component-level declaration. See Theme.

CSS VariableSass VariableDefault
--bulma-steps-marker-size$steps-marker-size2rem
--bulma-steps-marker-size-small$steps-marker-size-small1.5rem
--bulma-steps-marker-size-medium$steps-marker-size-medium2.5rem
--bulma-steps-marker-size-large$steps-marker-size-large3rem
--bulma-steps-divider-height$steps-divider-height0.2em
--bulma-steps-default-color$steps-default-colorvar(--bulma-grey-light)
--bulma-steps-marker-background$steps-marker-backgroundvar(--bulma-scheme-main)
--bulma-steps-marker-font-size$steps-marker-font-sizevar(--bulma-size-small)
--bulma-steps-marker-font-weight$steps-marker-font-weightvar(--bulma-weight-bold)
--bulma-steps-title-size$steps-title-sizevar(--bulma-size-small)
--bulma-steps-title-weight$steps-title-weightvar(--bulma-weight-medium)
--bulma-steps-title-color$steps-title-colorvar(--bulma-text-weak)
--bulma-steps-title-active-color$steps-title-active-colorvar(--bulma-text-strong)
--bulma-steps-title-active-weight$steps-title-active-weightvar(--bulma-weight-semibold)
--bulma-steps-content-margin-top$steps-content-margin-top0.5rem
--bulma-steps-vertical-padding$steps-vertical-padding1.5rem
--bulma-steps-vertical-content-margin-left$steps-vertical-content-margin-left1rem
--bulma-steps-animation-duration$steps-animation-duration0.3s
--bulma-steps-navigation-margin-top$steps-navigation-margin-top1rem