Form stepper

Provides a visual representation of a form through a series of steps.

Props

step
number
The current step state value (1-based index). Leaving it blank (-1) will allow any step to be accessed.
testId
string
Sets a data-testid attribute for automated testing.
mt, mr, mb, ml
Spacing
Apply margin to the top, right, bottom, and/or left of the component.
step
number
The current step state value (1-based index). Leaving it blank (-1) will allow any step to be accessed.
Defaults to -1.
testId
string
Sets the data-testid attribute for automated testing.
mt, mr, mb, ml
Spacing
Apply margin to the top, right, bottom, and/or left of the component.
step
number
The current step state value (1-based index). Leaving it blank (-1) will allow any step to be accessed.
Defaults to -1.
testId
string
Sets a data-testid attribute for automated testing.
mt, mr, mb, ml
Spacing
Apply margin to the top, right, bottom, and/or left of the component.

Events

onChange
(detail: GoabFormStepperOnChangeDetail) => void
Callback fired when the active step changes.
onChange
GoabFormStepperOnChangeDetail
Emits when the form stepper step changes. Emits the new step as GoabFormStepperOnChangeDetail.
_change
CustomEvent

Form Step Props

status
GoabFormStepStatus
The completion status of the step. Affects visual styling and icons.
text
string
The step label text displayed to users.
status
GoabFormStepStatus
The completion status of the step. Affects visual styling and icons.
text
string
The step label text displayed to users.
last
boolean
Whether this is the last step in the form stepper. Affects styling when complete.
Defaults to false.
status
"complete" | "incomplete" | "not-started"
The completion status of the step. Affects visual styling and icons.
text
string
The step label text displayed to users.

Form Step Events

_click
CustomEvent
Examples

Form stepper with controlled navigation

const [step, setStep] = useState(1);

  function setPage(page: number) {
    if (page < 1 || page > 4) return;
    setStep(page);
  }
<GoabFormStepper step={step} onChange={(event: GoabFormStepperOnChangeDetail) => setStep(event.step)}>
        <GoabFormStep text="Personal details" />
        <GoabFormStep text="Employment history" />
        <GoabFormStep text="References" />
        <GoabFormStep text="Review" />
      </GoabFormStepper>

      <GoabPages current={step} mb="3xl" mt="xl" mr="xl" ml="xl">
        <div>
          <GoabSkeleton type="article" />
        </div>
        <div>
          <GoabSkeleton type="header" size="2" />
          <GoabSkeleton type="text" />
          <GoabSkeleton type="header" size="2" />
          <GoabSkeleton type="text" />
        </div>
        <div>
          <GoabSkeleton type="text" />
          <GoabSpacer vSpacing="m" />
          <GoabSkeleton type="text" />
        </div>
        <div>
          <GoabSkeleton type="header" size="2" />
          <GoabSkeleton type="text" />
          <GoabSpacer vSpacing="m" />
          <GoabSkeleton type="text" />
        </div>
      </GoabPages>

      <div style={{ display: "flex", justifyContent: "space-between" }}>
        <GoabButton type="secondary" onClick={() => setPage(step - 1)}>
          Previous
        </GoabButton>
        <GoabButton type="primary" onClick={() => setPage(step + 1)}>
          Next
        </GoabButton>
      </div>
step = 1;

  updateStep(event: GoabFormStepperOnChangeDetail): void {
    this.step = event.step;
  }

  setPage(page: number): void {
    if (page < 1 || page > 4) return;
    this.step = page;
  }
<goab-form-stepper ml="s" mr="s" [step]="step" (onChange)="updateStep($event)">
  <goab-form-step text="Personal details"></goab-form-step>
  <goab-form-step text="Employment history"></goab-form-step>
  <goab-form-step text="References"></goab-form-step>
  <goab-form-step text="Review"></goab-form-step>
</goab-form-stepper>

<goab-pages [current]="step" mb="3xl" mt="xl" mr="xl" ml="xl">
  <div>
    <goab-skeleton type="article"></goab-skeleton>
  </div>
  <div>
    <goab-skeleton type="header" size="2"></goab-skeleton>
    <goab-skeleton type="text"></goab-skeleton>
    <goab-skeleton type="header" size="2"></goab-skeleton>
    <goab-skeleton type="text"></goab-skeleton>
  </div>
  <div>
    <goab-skeleton type="text"></goab-skeleton>
    <goab-spacer vSpacing="m"></goab-spacer>
    <goab-skeleton type="text"></goab-skeleton>
  </div>
  <div>
    <goab-skeleton type="header" size="2"></goab-skeleton>
    <goab-skeleton type="text"></goab-skeleton>
    <goab-spacer vSpacing="m"></goab-spacer>
    <goab-skeleton type="text"></goab-skeleton>
  </div>
</goab-pages>

<div style="display: flex; justify-content: space-between">
  <goab-button (onClick)="setPage(step - 1)" type="secondary">Previous</goab-button>
  <goab-button (onClick)="setPage(step + 1)" type="primary">Next</goab-button>
</div>
const formStepper = document.getElementById('form-stepper');
const formPages = document.getElementById('form-pages');
const prevBtn = document.getElementById('prev-btn');
const nextBtn = document.getElementById('next-btn');

let currentStep = 1;

function updateStep(step) {
  if (step < 1 || step > 4) return;
  currentStep = step;
  formStepper.setAttribute('step', currentStep);
  formPages.setAttribute('current', currentStep);
}

formStepper.addEventListener('_change', (e) => {
  updateStep(e.detail.step);
});

prevBtn.addEventListener('_click', () => {
  updateStep(currentStep - 1);
});

nextBtn.addEventListener('_click', () => {
  updateStep(currentStep + 1);
});
<goa-form-stepper id="form-stepper" ml="s" mr="s" step="1">
  <goa-form-step text="Personal details"></goa-form-step>
  <goa-form-step text="Employment history"></goa-form-step>
  <goa-form-step text="References"></goa-form-step>
  <goa-form-step text="Review"></goa-form-step>
</goa-form-stepper>

<goa-pages id="form-pages" current="1" mb="3xl" mt="xl" mr="xl" ml="xl">
  <div>
    <goa-skeleton type="article"></goa-skeleton>
  </div>
  <div>
    <goa-skeleton type="header" size="2"></goa-skeleton>
    <goa-skeleton type="text"></goa-skeleton>
    <goa-skeleton type="header" size="2"></goa-skeleton>
    <goa-skeleton type="text"></goa-skeleton>
  </div>
  <div>
    <goa-skeleton type="text"></goa-skeleton>
    <goa-spacer vspacing="m"></goa-spacer>
    <goa-skeleton type="text"></goa-skeleton>
  </div>
  <div>
    <goa-skeleton type="header" size="2"></goa-skeleton>
    <goa-skeleton type="text"></goa-skeleton>
    <goa-spacer vspacing="m"></goa-spacer>
    <goa-skeleton type="text"></goa-skeleton>
  </div>
</goa-pages>

<div style="display: flex; justify-content: space-between">
  <goa-button version="2" id="prev-btn" type="secondary">Previous</goa-button>
  <goa-button version="2" id="next-btn" type="primary">Next</goa-button>
</div>

Set the status of step on a form stepper

const [step, setStep] = useState<number>(-1);
  const status: GoabFormStepStatus[] = [
    "complete",
    "complete",
    "incomplete",
    "not-started"
  ];

  function setPage(page: number) {
    if (page < 1 || page > 4) return;
    setStep(page);
  }
<GoabFormStepper step={step} onChange={(event) => setStep(event.step)}>
        <GoabFormStep text="Personal details" status={status[0]} />
        <GoabFormStep text="Employment history" status={status[1]} />
        <GoabFormStep text="References" status={status[2]} />
        <GoabFormStep text="Review" status={status[3]} />
      </GoabFormStepper>
      <GoabPages current={step} mb="3xl" mt="xl" mr="xl" ml="xl">
        <div>
          <GoabSkeleton type="article" />
        </div>
        <div>
          <GoabSkeleton type="header" size="2" />
          <GoabSkeleton type="text" />
          <GoabSkeleton type="header" size="2" />
          <GoabSkeleton type="text" />
        </div>
        <div>
          <GoabSkeleton type="text" />
          <GoabSpacer vSpacing="m" />
          <GoabSkeleton type="text" />
        </div>
        <div>
          <GoabSkeleton type="header" size="2" />
          <GoabSkeleton type="text" />
          <GoabSpacer vSpacing="m" />
          <GoabSkeleton type="text" />
        </div>
      </GoabPages>
      <div style={{ display: "flex", justifyContent: "space-between" }}>
        <GoabButton type="secondary" onClick={() => setPage(step - 1)}>
          Previous
        </GoabButton>
        <GoabButton type="primary" onClick={() => setPage(step + 1)}>
          Next
        </GoabButton>
      </div>
step = -1;
  status: GoabFormStepStatus[] = ["complete", "complete", "incomplete", "not-started"];

  updateStep(event: GoabFormStepperOnChangeDetail): void {
    this.step = event.step;
  }

  setPage(page: number): void {
    if (page < 1 || page > 4) return;
    this.step = page;
  }
<goab-form-stepper ml="s" mr="s" [step]="step" (onChange)="updateStep($event)">
  <goab-form-step text="Personal details" [status]="status[0]"></goab-form-step>
  <goab-form-step text="Employment history" [status]="status[1]"></goab-form-step>
  <goab-form-step text="References" [status]="status[2]"></goab-form-step>
  <goab-form-step text="Review" [status]="status[3]"></goab-form-step>
</goab-form-stepper>
<goab-pages [current]="step" mb="3xl" mt="xl" mr="xl" ml="xl">
  <div><!-- Page 1 content --></div>
  <div><!-- Page 2 content --></div>
  <div><!-- Page 3 content --></div>
  <div><!-- Page 4 content --></div>
</goab-pages>
<div style="display: flex; justify-content: space-between">
  <goab-button (onClick)="setPage(step-1)" type="secondary">Previous</goab-button>
  <goab-button (onClick)="setPage(step+1)" type="primary">Next</goab-button>
</div>
const stepper = document.querySelector('goa-form-stepper');
const pages = document.querySelector('goa-pages');
const prevBtn = document.querySelector('goa-button[type="secondary"]');
const nextBtn = document.querySelector('goa-button[type="primary"]');
let step = -1;

stepper.addEventListener('_change', (e) => {
  step = e.detail.step;
  stepper.step = step;
  pages.current = step;
});

prevBtn.addEventListener('_click', () => {
  if (step > 1) {
    step--;
    stepper.step = step;
    pages.current = step;
  }
});

nextBtn.addEventListener('_click', () => {
  if (step < 4) {
    step++;
    stepper.step = step;
    pages.current = step;
  }
});
<goa-form-stepper ml="s" mr="s" step="-1">
  <goa-form-step text="Personal details" status="complete"></goa-form-step>
  <goa-form-step text="Employment history" status="complete"></goa-form-step>
  <goa-form-step text="References" status="incomplete"></goa-form-step>
  <goa-form-step text="Review" status="not-started"></goa-form-step>
</goa-form-stepper>
<goa-pages current="-1" mb="3xl" mt="xl" mr="xl" ml="xl">
  <div><!-- Page 1 content --></div>
  <div><!-- Page 2 content --></div>
  <div><!-- Page 3 content --></div>
  <div><!-- Page 4 content --></div>
</goa-pages>
<div style="display: flex; justify-content: space-between">
  <goa-button version="2" type="secondary">Previous</goa-button>
  <goa-button version="2" type="primary">Next</goa-button>
</div>

No usage guidelines have been documented for this component yet.

All GoA Design System components are built to meet WCAG 2.2 AA standards. The following guidelines provide additional context for accessible implementation.

No accessibility-specific guidelines have been documented for this component yet.

View old component docs