Skeleton loader

Provide visual feedback to users while loading a content heavy page or page element.

Props

lineCount
number
Used within components that contain multiple lines. Currently only used in card skeleton type.
Defaults to 3.
maxWidth
string
Sets the maximum width. Currently only used in card skeleton type.
Defaults to 300px.
size
GoabSkeletonSize
Size can affect either the height, width or both for different skeleton types.
Defaults to 1.
testId
string
Sets a data-testid attribute for automated testing.
type
GoabSkeletonType
Sets the skeleton shape to represent your content.
mt, mr, mb, ml
Spacing
Apply margin to the top, right, bottom, and/or left of the component.
lineCount
number
Used within components that contain multiple lines. Currently only used in card skeleton type.
maxWidth
string
Sets the maximum width. Currently only used in card skeleton type.
Defaults to 300px.
size
GoabSkeletonSize
Size can affect either the height, width or both for different skeleton types.
testId
string
Sets the data-testid attribute for automated testing.
type
GoabSkeletonType
Sets the skeleton shape to represent your content.
mt, mr, mb, ml
Spacing
Apply margin to the top, right, bottom, and/or left of the component.
linecount
number
Used within components that contain multiple lines. Currently only used in card skeleton type
Defaults to 3.
maxWidth
string
Sets the maximum width. Currently only used in card skeleton type.
Defaults to 300px.
size
GoabSkeletonSize 1 | 2 | 3 | 4
Size can affect either the height, width or both for different skeleton types.
Defaults to 1.
testId
string
Sets a data-testid attribute for automated testing.
type
GoabSkeletonType image | text | title | text-small | avatar | header | paragraph | thumbnail | card | lines | profile | article
Sets the skeleton shape to represent your content.
mt, mr, mb, ml
Spacing
Apply margin to the top, right, bottom, and/or left of the component.
Examples

Basic page layout

<GoabOneColumnLayout>
      <section slot="header">
        <GoabAppHeader url="/" heading="Service name">
          <a href="/login">Sign in</a>
        </GoabAppHeader>
      </section>
      <GoabPageBlock width="704px">
        <p>
          <GoabSkeleton type="header" size="4" />
          <GoabSkeleton type="text" size="1" />
        </p>
        <p>
          <GoabSkeleton type="header" size="4" />
          <GoabSkeleton type="text" size="1" />
        </p>
        <GoabGrid minChildWidth="30ch">
          <GoabSkeleton type="card" size="2" />
          <GoabSkeleton type="card" size="2" />
        </GoabGrid>
      </GoabPageBlock>
      <section slot="footer">
        <GoabAppFooter />
      </section>
    </GoabOneColumnLayout>
<goab-one-column-layout>
  <section slot="header">
    <goab-app-header url="/" heading="Service name">
      <a href="/login">Sign in</a>
    </goab-app-header>
  </section>
  <goab-page-block width="704px">
    <p>
      <goab-skeleton type="header" size="4"></goab-skeleton>
      <goab-skeleton type="text" size="1"></goab-skeleton>
    </p>
    <p>
      <goab-skeleton type="header" size="4"></goab-skeleton>
      <goab-skeleton type="text" size="1"></goab-skeleton>
    </p>
    <goab-grid minChildWidth="30ch">
      <goab-skeleton type="card" size="2"></goab-skeleton>
      <goab-skeleton type="card" size="2"></goab-skeleton>
    </goab-grid>
  </goab-page-block>
  <section slot="footer">
    <goab-app-footer></goab-app-footer>
  </section>
</goab-one-column-layout>
<goa-one-column-layout>
  <section slot="header">
    <goa-app-header version="2" url="/" heading="Service name">
      <a href="/login">Sign in</a>
    </goa-app-header>
  </section>
  <goa-page-block width="704px">
    <p>
      <goa-skeleton type="header" size="4"></goa-skeleton>
      <goa-skeleton type="text" size="1"></goa-skeleton>
    </p>
    <p>
      <goa-skeleton type="header" size="4"></goa-skeleton>
      <goa-skeleton type="text" size="1"></goa-skeleton>
    </p>
    <goa-grid min-child-width="30ch">
      <goa-skeleton type="card" size="2"></goa-skeleton>
      <goa-skeleton type="card" size="2"></goa-skeleton>
    </goa-grid>
  </goa-page-block>
  <section slot="footer">
    <goa-app-footer version="2"></goa-app-footer>
  </section>
</goa-one-column-layout>

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>

Other

Use CircularProgress for page-level or blocking operations. Use Skeleton for content placeholders while loading.

Choose the right loading indicator for your context.
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