Skip to content

Import#

import { StepIndicator } from '@dnb/eufemia'

Description#

The step indicator (progress indicator) is a visual representation of a user's progress through a set of steps or series of actions. Their purpose is to both guide the user through the process and to help them create a mental model of the amount of time and effort that is required to fulfill the process.

Relevant links#

If the user should be able to navigate back and forth, use the mode="loose" property. More about the modes further down.

The current active step is set with the currentStep property or within the data with the isCurrent object property.

NB: Whenever possible, ensure you bind the currentStep to the browsers path location. See the example below.

Modes#

The mode property is mandatory. It tells the component how it should behave.

Strict mode#

Use strict for a chronological step order.

The user can navigate between the visited steps and the current step. The component keeps track of these reached steps.

Loose mode#

Use loose if the user should be able to navigate freely between all steps. Also, those which are not visited before.

Static mode#

Use static for non-interactive steps.

Modify a step#

You can easily modify a step – e.g. should one step not be interactive, you can use the inactive property on that step:

const steps = [
{ title: 'Active' },
{ title: 'Not active', inactive: true },
]

More details about modifying steps in the properties panel.

Accessibility#

When openOnFind is enabled, find-in-page support is powered by HeightAnimation; see its accessibility notes for behavior details and browser support.

Related components#

StepIndicator is part of the Navigation category. Other components for similar needs:

  • Breadcrumb — to show where someone is and let them move back up the path.
  • InfinityScroller — to load more content automatically as people scroll.
  • Pagination — to split long content into pages or load more content as people move through it.
  • SkipContent — to help keyboard users jump past large or repeated content.
  • Tabs — to let people switch between related views on the same page.

Demos#

StepIndicator in loose mode#

Every step can be clicked.

const InteractiveDemo = () => {
  const [step, setStep] = useState(1)
  return (
    <div
      style={{
        display: 'flex',
      }}
    >
      <Space stretch>
        <StepIndicator
          mode="loose"
          currentStep={step}
          onChange={({ currentStep }) => {
            setStep(currentStep)
          }}
          data={[
            'Cum odio si bolig bla et ta',
            'Auctor tortor vestibulum placerat bibendum sociis aliquam nunc sed venenatis massa eget duis',
            'Bibendum sociis',
          ]}
          bottom
        />

        <Button
          variant="secondary"
          onClick={() => {
            setStep((step) => {
              if (step >= 2) {
                step = -1
              }
              return step + 1
            })
          }}
        >
          Next step
        </Button>
      </Space>
    </div>
  )
}
render(<InteractiveDemo />)

StepIndicator in strict mode#

Every visited step can be clicked, including the current step.

<StepIndicator
  mode="strict"
  currentStep={1}
  onChange={({ currentStep }) => {
    console.log('onChange', currentStep)
  }}
  data={[
    {
      title: 'Velg mottaker',
    },
    {
      title: 'Bestill eller erstatt',
      onClick: ({ currentStep }) =>
        console.log('currentStep:', currentStep),
      status:
        'Du må velge bestill nytt kort eller erstatt kort for å kunne fullføre bestillingen din.',
    },
    {
      title: 'Oppsummering',
    },
  ]}
/>

StepIndicator in static mode#

None of the steps are clickable.

<StepIndicator
  mode="static"
  currentStep={1}
  onChange={({ currentStep }) => {
    console.log('onChange', currentStep)
  }}
  data={[
    {
      title: 'Om din nye bolig',
    },
    {
      title: 'Ditt lån og egenkapital',
      onClick: ({ currentStep }) => console.log(currentStep),
    },
    {
      title: 'Oppsummering',
    },
  ]}
/>

StepIndicator with a router#

const StepIndicatorWithRouter = () => {
  const [currentStep, setCurrentStep] = useState(1)
  useEffect(() => {
    const step =
      parseFloat(window.location.search?.replace(/[?]/, '')) || 1
    setCurrentStep(step)
  }, [])
  return (
    <>
      <StepIndicator
        mode="loose"
        currentStep={currentStep - 1}
        onChange={({ currentStep }) => {
          const step = currentStep + 1
          setCurrentStep(step)
          window.history.pushState({}, '', '?' + step)
        }}
        data={[
          {
            title: 'Om din nye bolig',
          },
          {
            title: 'Ditt lån og egenkapital',
          },
          {
            title: 'Oppsummering',
          },
        ]}
      />
    </>
  )
}
render(<StepIndicatorWithRouter />)

StepIndicator customized#

Completely customized step indicator.

function CustomStepIndicator({ children, data, ...props }) {
  const [step, setStep] = useState(0)
  return (
    <>
      <StepIndicator
        mode="loose"
        data={data}
        currentStep={step}
        onChange={({ currentStep }) => setStep(currentStep)}
        bottom
        {...props}
      />
      <Section variant="information" innerSpace>
        {children(step)}
      </Section>
    </>
  )
}
render(
  <CustomStepIndicator
    data={[
      {
        title: 'First',
        isCurrent: true,
      },
      {
        title: 'Second',
      },
      {
        title: 'Last',
      },
    ]}
  >
    {(step) => {
      switch (step) {
        case 0:
          return <>Step One</>
        case 1:
          return <>Step Two</>
        default:
          return <>Fallback</>
      }
    }}
  </CustomStepIndicator>
)

StepIndicator with text only#

This example also demonstrates the expandedInitially property.

  1. Om din nye bolig
  2. Ditt lån og egenkapital
  3. Oppsummering
<StepIndicator
  expandedInitially
  mode="static"
  currentStep={1}
  data={['Om din nye bolig', 'Ditt lån og egenkapital', 'Oppsummering']}
/>

With skeleton#

  1. Om din nye bolig
  2. Ditt lån og egenkapital
  3. Oppsummering
<StepIndicator
  mode="static"
  skeleton
  currentStep={1}
  expandedInitially
  data={[
    {
      title: 'Om din nye bolig',
    },
    {
      title: 'Ditt lån og egenkapital',
    },
    {
      title: 'Oppsummering',
    },
  ]}
/>
Edit on GitHub