Button

Carry out an important action or navigate to another page.

Props

type
primary | submit | secondary | tertiary | start | text
Sets the visual style of the button. Use "primary" for main actions, "secondary" for alternative actions, "tertiary" for low-emphasis actions, "start" for prominent call-to-action buttons, and "text" for text-only buttons.
Defaults to primary.
size
normal | compact
Controls the size of the button. Use "compact" for inline actions or space-constrained layouts.
Defaults to normal.
variant
normal | destructive | inverse | dark
Sets the color variant for semantic meaning. Use "destructive" for delete or irreversible actions, "inverse" for light-colored text on dark backgrounds, and "dark" for dark text color on text buttons only. Note: "dark" has no effect on non-text button types.
Defaults to normal.
disabled
boolean
When true, prevents user interaction and applies disabled styling.
Defaults to false.
leadingIcon
GoAIconType
Icon displayed before the button text.
trailingIcon
GoAIconType
Icon displayed after the button text.
testId
string
Sets a data-testid attribute for automated testing.
width
string
Sets a custom width for the button (e.g., "200px" or "100%").
mt, mr, mb, ml
none | 3xs | 2xs | xs | s | m | l | xl | 2xl | 3xl | 4xl
Apply margin to the top, right, bottom, and/or left of the component.

Events

onClick
(event: Event) => void
_click
CustomEvent
Examples

Restricted access (401)

.error-page-content {
  text-align: center;
}
.error-page-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 7.5rem;
  height: 7.5rem;
  border-radius: 50%;
  background-color: var(--goa-color-greyscale-100);
}
/* Icon scaled beyond xlarge (2.5rem cap) to match the page-scale visual weight. */
/* Tracked in icon-sizes-above-xlarge gap ticket. */
.error-page-icon goa-icon,
.error-page-icon goab-icon {
  transform: scale(1.35);
}
.error-page-underline {
  width: 6.875rem;
  height: var(--goa-space-xs);
  background-color: var(--goa-color-info-default);
}
<GoabPageBlock>
  <div className="error-page-content">
    <GoabBlock
      direction="column"
      alignment="center"
      gap="xl"
      width="100%"
      mt="3xl"
      mb="3xl"
    >
      <GoabBlock direction="column" alignment="center" gap="m" width="100%">
        <div className="error-page-icon">
          <GoabIcon role="presentation" type="warning" size="xlarge" />
        </div>
        <GoabText size="body-m" color="secondary" mt="none" mb="none">
          Error 401
        </GoabText>
        <div className="error-page-underline" aria-hidden="true" />
      </GoabBlock>

      <GoabBlock direction="column" alignment="center" gap="l" width="100%">
        <GoabText tag="h1" size="heading-l" mt="none" mb="none">
          Restricted access
        </GoabText>
        <GoabText size="body-m" mt="none" mb="none">
          We cannot provide access to this page without valid credentials. Please sign in or
          contact support at{" "}
          <GoabLink>
            <a href="mailto:cs.licensingsupport@gov.ab.ca">cs.licensingsupport@gov.ab.ca</a>
          </GoabLink>{" "}
          to request access.
        </GoabText>
      </GoabBlock>

      <GoabButton type="primary" size="compact" onClick={() => (window.location.href = "/")}>
        Go to home page
      </GoabButton>
    </GoabBlock>
  </div>
</GoabPageBlock>
goHome() {
  window.location.href = "/";
}
<goab-page-block>
  <div class="error-page-content">
    <goab-block direction="column" alignment="center" gap="xl" width="100%" mt="3xl" mb="3xl">
      <goab-block direction="column" alignment="center" gap="m" width="100%">
        <div class="error-page-icon">
          <goab-icon role="presentation" type="warning" size="xlarge"></goab-icon>
        </div>
        <goab-text size="body-m" color="secondary" mt="none" mb="none">Error 401</goab-text>
        <div class="error-page-underline" aria-hidden="true"></div>
      </goab-block>

      <goab-block direction="column" alignment="center" gap="l" width="100%">
        <goab-text tag="h1" size="heading-l" mt="none" mb="none">Restricted access</goab-text>
        <goab-text size="body-m" mt="none" mb="none">
          We cannot provide access to this page without valid credentials. Please sign in or
          contact support at
          <goab-link>
            <a href="mailto:cs.licensingsupport@gov.ab.ca">cs.licensingsupport@gov.ab.ca</a>
          </goab-link>
          to request access.
        </goab-text>
      </goab-block>

      <goab-button type="primary" size="compact" (onClick)="goHome()">Go to home page</goab-button>
    </goab-block>
  </div>
</goab-page-block>
<goa-page-block>
  <div style="text-align: center;">
    <goa-block direction="column" alignment="center" gap="xl" width="100%" mt="3xl" mb="3xl">
      <goa-block direction="column" alignment="center" gap="m" width="100%">
        <div
          style="display: flex; align-items: center; justify-content: center; width: 7.5rem; height: 7.5rem; border-radius: 50%; background-color: var(--goa-color-greyscale-100);"
        >
          <goa-icon role="presentation" type="warning" size="xlarge" style="transform: scale(1.35);"></goa-icon>
        </div>
        <goa-text size="body-m" color="secondary" mt="none" mb="none">Error 401</goa-text>
        <div
          aria-hidden="true"
          style="width: 6.875rem; height: 0.5rem; background-color: var(--goa-color-info-default);"
        ></div>
      </goa-block>

      <goa-block direction="column" alignment="center" gap="l" width="100%">
        <goa-text as="h1" size="heading-l" mt="none" mb="none">Restricted access</goa-text>
        <goa-text size="body-m" mt="none" mb="none">
          We cannot provide access to this page without valid credentials. Please sign in or
          contact support at
          <goa-link>
            <a href="mailto:cs.licensingsupport@gov.ab.ca">cs.licensingsupport@gov.ab.ca</a>
          </goa-link>
          to request access.
        </goa-text>
      </goa-block>

      <goa-button version="2" type="primary" size="compact" onclick="window.location.href='/'">Go to home page</goa-button>
    </goa-block>
  </div>
</goa-page-block>

Uses a plain h1 as the page landmark. The decorative icon and accent bar are aria-hidden. The support email is a real mailto link inside GoabLink so keyboard users can activate it. No role="alert" is applied because the ARIA alert role is reserved for dynamically inserted messages.

Server problem (500)

.error-page-content {
  text-align: center;
}
.error-page-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 7.5rem;
  height: 7.5rem;
  border-radius: 50%;
  background-color: var(--goa-color-greyscale-100);
}
/* Icon scaled beyond xlarge (2.5rem cap) to match the page-scale visual weight. */
/* Tracked in icon-sizes-above-xlarge gap ticket. */
.error-page-icon goa-icon,
.error-page-icon goab-icon {
  transform: scale(1.35);
}
.error-page-underline {
  width: 6.875rem;
  height: var(--goa-space-xs);
  background-color: var(--goa-color-info-default);
}
<GoabPageBlock>
  <div className="error-page-content">
    <GoabBlock
      direction="column"
      alignment="center"
      gap="xl"
      width="100%"
      mt="3xl"
      mb="3xl"
    >
      <GoabBlock direction="column" alignment="center" gap="m" width="100%">
        <div className="error-page-icon">
          <GoabIcon role="presentation" type="warning" size="xlarge" />
        </div>
        <GoabText size="body-m" color="secondary" mt="none" mb="none">
          Error 500
        </GoabText>
        <div className="error-page-underline" aria-hidden="true" />
      </GoabBlock>

      <GoabBlock direction="column" alignment="center" gap="l" width="100%">
        <GoabText tag="h1" size="heading-l" mt="none" mb="none">
          We are experiencing a problem
        </GoabText>
        <GoabText size="body-m" mt="none" mb="none">
          We cannot load this page right now. Please try again in a few minutes. We apologize
          for the inconvenience.
        </GoabText>
      </GoabBlock>

      <GoabButton type="primary" size="compact" onClick={() => (window.location.href = "/")}>
        Go to home page
      </GoabButton>
    </GoabBlock>
  </div>
</GoabPageBlock>
goHome() {
  window.location.href = "/";
}
<goab-page-block>
  <div class="error-page-content">
    <goab-block direction="column" alignment="center" gap="xl" width="100%" mt="3xl" mb="3xl">
      <goab-block direction="column" alignment="center" gap="m" width="100%">
        <div class="error-page-icon">
          <goab-icon role="presentation" type="warning" size="xlarge"></goab-icon>
        </div>
        <goab-text size="body-m" color="secondary" mt="none" mb="none">Error 500</goab-text>
        <div class="error-page-underline" aria-hidden="true"></div>
      </goab-block>

      <goab-block direction="column" alignment="center" gap="l" width="100%">
        <goab-text tag="h1" size="heading-l" mt="none" mb="none">We are experiencing a problem</goab-text>
        <goab-text size="body-m" mt="none" mb="none">
          We cannot load this page right now. Please try again in a few minutes. We apologize for the inconvenience.
        </goab-text>
      </goab-block>

      <goab-button type="primary" size="compact" (onClick)="goHome()">Go to home page</goab-button>
    </goab-block>
  </div>
</goab-page-block>
<goa-page-block>
  <div style="text-align: center;">
    <goa-block direction="column" alignment="center" gap="xl" width="100%" mt="3xl" mb="3xl">
      <goa-block direction="column" alignment="center" gap="m" width="100%">
        <div
          style="display: flex; align-items: center; justify-content: center; width: 7.5rem; height: 7.5rem; border-radius: 50%; background-color: var(--goa-color-greyscale-100);"
        >
          <goa-icon role="presentation" type="warning" size="xlarge" style="transform: scale(1.35);"></goa-icon>
        </div>
        <goa-text size="body-m" color="secondary" mt="none" mb="none">Error 500</goa-text>
        <div
          aria-hidden="true"
          style="width: 6.875rem; height: 0.5rem; background-color: var(--goa-color-info-default);"
        ></div>
      </goa-block>

      <goa-block direction="column" alignment="center" gap="l" width="100%">
        <goa-text as="h1" size="heading-l" mt="none" mb="none">We are experiencing a problem</goa-text>
        <goa-text size="body-m" mt="none" mb="none">
          We cannot load this page right now. Please try again in a few minutes. We apologize for the inconvenience.
        </goa-text>
      </goa-block>

      <goa-button version="2" type="primary" size="compact" onclick="window.location.href='/'">Go to home page</goa-button>
    </goa-block>
  </div>
</goa-page-block>

Uses a plain h1 as the page landmark. The decorative icon and accent bar are aria-hidden. No role="alert" is applied because the ARIA alert role is reserved for dynamically inserted messages; a static error route does not meet that criterion.

Page not found (404)

.error-page-content {
  text-align: center;
}
.error-page-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 7.5rem;
  height: 7.5rem;
  border-radius: 50%;
  background-color: var(--goa-color-greyscale-100);
}
/* Icon scaled beyond xlarge (2.5rem cap) to match the page-scale visual weight. */
/* Tracked in icon-sizes-above-xlarge gap ticket. */
.error-page-icon goa-icon,
.error-page-icon goab-icon {
  transform: scale(1.35);
}
.error-page-underline {
  width: 6.875rem;
  height: var(--goa-space-xs);
  background-color: var(--goa-color-info-default);
}
<GoabPageBlock>
  <div className="error-page-content">
    <GoabBlock
      direction="column"
      alignment="center"
      gap="xl"
      width="100%"
      mt="3xl"
      mb="3xl"
    >
      <GoabBlock direction="column" alignment="center" gap="m" width="100%">
        <div className="error-page-icon">
          <GoabIcon role="presentation" type="warning" size="xlarge" />
        </div>
        <GoabText size="body-m" color="secondary" mt="none" mb="none">
          Error 404
        </GoabText>
        <div className="error-page-underline" aria-hidden="true" />
      </GoabBlock>

      <GoabBlock direction="column" alignment="center" gap="l" width="100%">
        <GoabText tag="h1" size="heading-l" mt="none" mb="none">
          Page not found
        </GoabText>
        <GoabText size="body-m" mt="none" mb="none">
          The page you're looking for doesn't exist or has been moved.
        </GoabText>
      </GoabBlock>

      <GoabButton type="primary" size="compact" onClick={() => (window.location.href = "/")}>
        Go to home page
      </GoabButton>
    </GoabBlock>
  </div>
</GoabPageBlock>
goHome() {
  window.location.href = "/";
}
<goab-page-block>
  <div class="error-page-content">
    <goab-block direction="column" alignment="center" gap="xl" width="100%" mt="3xl" mb="3xl">
      <goab-block direction="column" alignment="center" gap="m" width="100%">
        <div class="error-page-icon">
          <goab-icon role="presentation" type="warning" size="xlarge"></goab-icon>
        </div>
        <goab-text size="body-m" color="secondary" mt="none" mb="none">Error 404</goab-text>
        <div class="error-page-underline" aria-hidden="true"></div>
      </goab-block>

      <goab-block direction="column" alignment="center" gap="l" width="100%">
        <goab-text tag="h1" size="heading-l" mt="none" mb="none">Page not found</goab-text>
        <goab-text size="body-m" mt="none" mb="none">The page you're looking for doesn't exist or has been moved.</goab-text>
      </goab-block>

      <goab-button type="primary" size="compact" (onClick)="goHome()">Go to home page</goab-button>
    </goab-block>
  </div>
</goab-page-block>
<goa-page-block>
  <div style="text-align: center;">
    <goa-block direction="column" alignment="center" gap="xl" width="100%" mt="3xl" mb="3xl">
      <goa-block direction="column" alignment="center" gap="m" width="100%">
        <div
          style="display: flex; align-items: center; justify-content: center; width: 7.5rem; height: 7.5rem; border-radius: 50%; background-color: var(--goa-color-greyscale-100);"
        >
          <goa-icon role="presentation" type="warning" size="xlarge" style="transform: scale(1.35);"></goa-icon>
        </div>
        <goa-text size="body-m" color="secondary" mt="none" mb="none">Error 404</goa-text>
        <div
          aria-hidden="true"
          style="width: 6.875rem; height: 0.5rem; background-color: var(--goa-color-info-default);"
        ></div>
      </goa-block>

      <goa-block direction="column" alignment="center" gap="l" width="100%">
        <goa-text as="h1" size="heading-l" mt="none" mb="none">Page not found</goa-text>
        <goa-text size="body-m" mt="none" mb="none">The page you're looking for doesn't exist or has been moved.</goa-text>
      </goa-block>

      <goa-button version="2" type="primary" size="compact" onclick="window.location.href='/'">Go to home page</goa-button>
    </goa-block>
  </div>
</goa-page-block>

Uses a plain h1 as the page landmark. The decorative icon and accent bar are aria-hidden. No role="alert" is applied because the ARIA alert role is reserved for dynamically inserted messages; a static error route does not meet that criterion.

Add a filter chip

const [activeFilters, setActiveFilters] = useState<string[]>([]);

const addFilter = () => {
  const randomFilter = `Filter ${Math.floor(Math.random() * 100)}`;
  if (!activeFilters.includes(randomFilter)) {
    setActiveFilters((prevFilters) => [...prevFilters, randomFilter]);
  }
};

const removeFilter = (filter: string) => {
  setActiveFilters((prevFilters) => prevFilters.filter((f) => f !== filter));
};
<div>
  {activeFilters.map((filter) => (
    <GoabFilterChip
      key={filter}
      content={filter}
      onClick={() => removeFilter(filter)}
      mr="s"
      mb="s"
      mt="s"
    />
  ))}
</div>
<GoabButton mt="l" onClick={addFilter}>
  Add Random Filter
</GoabButton>
activeFilters: string[] = [];

removeFilter(filter: string): void {
  this.activeFilters = this.activeFilters.filter((f) => f !== filter);
}

addFilter(): void {
  const randomFilter = "Filter " + Math.floor(Math.random() * 100);
  if (!this.activeFilters.includes(randomFilter)) {
    this.activeFilters.push(randomFilter);
  }
}
<div>
  @for (filter of activeFilters; track filter) {
  <goab-filter-chip
    [content]="filter"
    (onClick)="removeFilter(filter)"
    mr="s"
    mb="s"
    mt="s"
  >
  </goab-filter-chip>
  }
</div>
<goab-button mt="l" (onClick)="addFilter()">Add Random Filter</goab-button>
const activeFilters = [];
const container = document.getElementById("filter-container");
const addBtn = document.getElementById("add-filter-btn");

function renderFilters() {
  container.innerHTML = "";
  activeFilters.forEach((filter) => {
    const chip = document.createElement("goa-filter-chip");
    chip.setAttribute("version", "2");
    chip.setAttribute("content", filter);
    chip.setAttribute("mr", "s");
    chip.setAttribute("mb", "s");
    chip.setAttribute("mt", "s");
    chip.addEventListener("_click", () => removeFilter(filter));
    container.appendChild(chip);
  });
}

function addFilter() {
  const randomFilter = "Filter " + Math.floor(Math.random() * 100);
  if (!activeFilters.includes(randomFilter)) {
    activeFilters.push(randomFilter);
    renderFilters();
  }
}

function removeFilter(filter) {
  const index = activeFilters.indexOf(filter);
  if (index > -1) {
    activeFilters.splice(index, 1);
    renderFilters();
  }
}

addBtn.addEventListener("_click", addFilter);
<div id="filter-container"></div>
<goa-button version="2" mt="l" id="add-filter-btn">Add Random Filter</goa-button>

Add a record using a drawer

const [open, setOpen] = useState(false);
<GoabButton leadingIcon="add" onClick={() => setOpen(true)}>
  Add Record
</GoabButton>
<GoabDrawer
  maxSize="492px"
  open={open}
  heading="Add Record"
  position="right"
  onClose={() => setOpen(false)}
  actions={
    <GoabButtonGroup alignment="start">
      <GoabButton type="primary" size="compact" onClick={() => setOpen(false)}>
        Add record
      </GoabButton>
      <GoabButton type="tertiary" size="compact" onClick={() => setOpen(false)}>
        Cancel
      </GoabButton>
    </GoabButtonGroup>
  }
>
  <GoabFormItem label="Level of education">
    <GoabDropdown onChange={() => {}} name="education" value="university">
      <GoabDropdownItem value="high-school" label="High School Diploma" />
      <GoabDropdownItem value="college" label="College Diploma" />
      <GoabDropdownItem value="university" label="University Degree" />
      <GoabDropdownItem value="masters" label="Master's Degree" />
      <GoabDropdownItem value="doctorate" label="Doctorate" />
    </GoabDropdown>
  </GoabFormItem>
  <GoabFormItem label="Educational institution" mt="l">
    <GoabInput name="education" type="text" onChange={() => {}} />
  </GoabFormItem>
  <GoabFormItem label="Field of study" requirement="optional" mt="l">
    <GoabInput name="fieldOfStudy" type="text" onChange={() => {}} />
  </GoabFormItem>
  <GoabFormItem label="Is the person currently attending?" mt="l">
    <GoabRadioGroup
      name="attendTraining"
      orientation="horizontal"
      onChange={() => {}}
    >
      <GoabRadioItem value="yes" label="Yes" />
      <GoabRadioItem value="no" label="No" />
    </GoabRadioGroup>
  </GoabFormItem>
  <GoabFormItem label="Start date" mt="l">
    <GoabDatePicker onChange={() => {}} value={new Date("2022-09-01")} />
    <GoabCheckbox
      name="startDateApproximate"
      text="Approximate date"
      value="y"
      mt="s"
    />
  </GoabFormItem>
  <GoabFormItem label="Credential received?" mt="l">
    <GoabRadioGroup
      name="credentialReceived"
      orientation="horizontal"
      onChange={() => {}}
    >
      <GoabRadioItem value="yes" label="Yes" />
      <GoabRadioItem value="no" label="No" />
    </GoabRadioGroup>
  </GoabFormItem>
</GoabDrawer>
open = false;

onClick() {
  this.open = true;
}

onClose() {
  this.open = false;
}

dropdownOnChange(event: any) {
  console.log(event);
}

inputOnChange(event: any) {
  console.log(event);
}

radioOnChange(event: any) {
  console.log(event);
}

dateOnChange(event: any) {
  console.log(event);
}

closeDrawer() {
  this.open = false;
}
<goab-button leadingIcon="add" (onClick)="onClick()">Add Record</goab-button>
<goab-drawer
  maxSize="492px"
  [open]="open"
  heading="Add Record"
  position="right"
  (onClose)="onClose()"
  [actions]="actions"
>
  <goab-form-item label="Level of education">
    <goab-dropdown
      (onChange)="dropdownOnChange($event)"
      name="education"
      value="university"
    >
      <goab-dropdown-item
        value="high-school"
        label="High School Diploma"
      ></goab-dropdown-item>
      <goab-dropdown-item value="college" label="College Diploma"></goab-dropdown-item>
      <goab-dropdown-item
        value="university"
        label="University Degree"
      ></goab-dropdown-item>
      <goab-dropdown-item value="masters" label="Master's Degree"></goab-dropdown-item>
      <goab-dropdown-item value="doctorate" label="Doctorate"></goab-dropdown-item>
    </goab-dropdown>
  </goab-form-item>
  <goab-form-item label="Educational institution" mt="l">
    <goab-input
      name="education"
      type="text"
      (onChange)="inputOnChange($event)"
    ></goab-input>
  </goab-form-item>
  <goab-form-item label="Field of study" requirement="optional" mt="l">
    <goab-input
      name="fieldOfStudy"
      type="text"
      (onChange)="inputOnChange($event)"
    ></goab-input>
  </goab-form-item>
  <goab-form-item label="Is the person currently attending?" mt="l">
    <goab-radio-group
      name="attendTraining"
      orientation="horizontal"
      (onChange)="radioOnChange($event)"
    >
      <goab-radio-item value="yes" label="Yes"></goab-radio-item>
      <goab-radio-item value="no" label="No"></goab-radio-item>
    </goab-radio-group>
  </goab-form-item>
  <goab-form-item label="Start date" mt="l">
    <goab-date-picker (onChange)="dateOnChange($event)"></goab-date-picker>
    <goab-checkbox
      name="startDateApproximate"
      text="Approximate date"
      value="y"
      mt="s"
    ></goab-checkbox>
  </goab-form-item>
  <goab-form-item label="Credential received?" mt="l">
    <goab-radio-group
      name="credentialReceived"
      orientation="horizontal"
      (onChange)="radioOnChange($event)"
    >
      <goab-radio-item value="yes" label="Yes"></goab-radio-item>
      <goab-radio-item value="no" label="No"></goab-radio-item>
    </goab-radio-group>
  </goab-form-item>
  <ng-template #actions>
    <goab-button-group alignment="start">
      <goab-button type="primary" size="compact" (onClick)="closeDrawer()"
        >Add record</goab-button
      >
      <goab-button type="tertiary" size="compact" (onClick)="closeDrawer()"
        >Cancel</goab-button
      >
    </goab-button-group>
  </ng-template>
</goab-drawer>
const drawer = document.getElementById("record-drawer");
const openBtn = document.getElementById("open-drawer-btn");
const addBtn = document.getElementById("add-record-btn");
const cancelBtn = document.getElementById("cancel-btn");

openBtn.addEventListener("_click", () => {
  drawer.setAttribute("open", "true");
});

drawer.addEventListener("_close", () => {
  drawer.removeAttribute("open");
});

addBtn.addEventListener("_click", () => {
  drawer.removeAttribute("open");
});

cancelBtn.addEventListener("_click", () => {
  drawer.removeAttribute("open");
});
<goa-button version="2" id="open-drawer-btn" leadingicon="add">Add Record</goa-button>
<goa-drawer
  version="2"
  id="record-drawer"
  max-size="492px"
  heading="Add Record"
  position="right"
>
  <goa-form-item version="2" label="Level of education">
    <goa-dropdown version="2" name="education" value="university">
      <goa-dropdown-item
        value="high-school"
        label="High School Diploma"
      ></goa-dropdown-item>
      <goa-dropdown-item value="college" label="College Diploma"></goa-dropdown-item>
      <goa-dropdown-item value="university" label="University Degree"></goa-dropdown-item>
      <goa-dropdown-item value="masters" label="Master's Degree"></goa-dropdown-item>
      <goa-dropdown-item value="doctorate" label="Doctorate"></goa-dropdown-item>
    </goa-dropdown>
  </goa-form-item>
  <goa-form-item version="2" label="Educational institution" mt="l">
    <goa-input version="2" name="education" type="text"></goa-input>
  </goa-form-item>
  <goa-form-item version="2" label="Field of study" requirement="optional" mt="l">
    <goa-input version="2" name="fieldOfStudy" type="text"></goa-input>
  </goa-form-item>
  <goa-form-item version="2" label="Is the person currently attending?" mt="l">
    <goa-radio-group version="2" name="attendTraining" orientation="horizontal">
      <goa-radio-item value="yes" label="Yes"></goa-radio-item>
      <goa-radio-item value="no" label="No"></goa-radio-item>
    </goa-radio-group>
  </goa-form-item>
  <goa-form-item version="2" label="Start date" mt="l">
    <goa-date-picker version="2"></goa-date-picker>
    <goa-checkbox
      version="2"
      name="startDateApproximate"
      text="Approximate date"
      value="y"
      mt="s"
    ></goa-checkbox>
  </goa-form-item>
  <goa-form-item version="2" label="Credential received?" mt="l">
    <goa-radio-group version="2" name="credentialReceived" orientation="horizontal">
      <goa-radio-item value="yes" label="Yes"></goa-radio-item>
      <goa-radio-item value="no" label="No"></goa-radio-item>
    </goa-radio-group>
  </goa-form-item>
  <div slot="actions">
    <goa-button-group alignment="start">
      <goa-button version="2" id="add-record-btn" type="primary" size="compact"
        >Add record</goa-button
      >
      <goa-button version="2" id="cancel-btn" type="tertiary" size="compact"
        >Cancel</goa-button
      >
    </goa-button-group>
  </div>
</goa-drawer>

Add another item in a modal

const [open, setOpen] = useState(false);
const [type, setType] = useState<string>();
const [name, setName] = useState<string>();
const [description, setDescription] = useState<string>();
<GoabButton type="tertiary" leadingIcon="add" onClick={() => setOpen(true)}>
  Add another item
</GoabButton>
<GoabModal
  heading="Add a new item"
  open={open}
  actions={
    <GoabButtonGroup alignment="end">
      <GoabButton type="tertiary" size="compact" onClick={() => setOpen(false)}>
        Cancel
      </GoabButton>
      <GoabButton type="primary" size="compact" onClick={() => setOpen(false)}>
        Save new item
      </GoabButton>
    </GoabButtonGroup>
  }
>
  <p>Fill in the information to create a new item</p>
  <GoabFormItem label="Type" mt="l">
    <GoabDropdown onChange={(e) => setType(e.value)} value={type}>
      <GoabDropdownItem value="1" label="Option 1" />
      <GoabDropdownItem value="2" label="Option 2" />
    </GoabDropdown>
  </GoabFormItem>
  <GoabFormItem label="Name" mt="l">
    <GoabInput
      onChange={(e) => setName(e.value)}
      value={name}
      name="name"
      width="100%"
    />
  </GoabFormItem>
  <GoabFormItem label="Description" mt="l">
    <GoabTextArea
      name="description"
      rows={3}
      width="100%"
      onChange={(e) => setDescription(e.value)}
      value={description}
    />
  </GoabFormItem>
</GoabModal>
open = false;
type: string | undefined = "";
name = "";
description = "";

toggleModal() {
  this.open = !this.open;
}

updateType(event: any) {
  this.type = event.value;
}

updateName(event: any) {
  this.name = event.value;
}

updateDescription(event: any) {
  this.description = event.value;
}
<goab-button type="tertiary" leadingIcon="add" (onClick)="toggleModal()"
  >Add another item</goab-button
>
<goab-modal
  [open]="open"
  (onClose)="toggleModal()"
  heading="Add a new item"
  [actions]="actions"
>
  <p>Fill in the information to create a new item</p>
  <goab-form-item label="Type" mt="l">
    <goab-dropdown (onChange)="updateType($event)" [value]="type">
      <goab-dropdown-item value="1" label="Option 1"></goab-dropdown-item>
      <goab-dropdown-item value="2" label="Option 2"></goab-dropdown-item>
    </goab-dropdown>
  </goab-form-item>
  <goab-form-item label="Name" mt="l">
    <goab-input
      name="name"
      width="100%"
      (onChange)="updateName($event)"
      [value]="name"
    ></goab-input>
  </goab-form-item>
  <goab-form-item label="Description" mt="l">
    <goab-textarea
      name="description"
      width="100%"
      [rows]="3"
      (onChange)="updateDescription($event)"
      [value]="description"
    ></goab-textarea>
  </goab-form-item>
  <ng-template #actions>
    <goab-button-group alignment="end">
      <goab-button type="tertiary" size="compact" (onClick)="toggleModal()"
        >Cancel</goab-button
      >
      <goab-button type="primary" size="compact" (onClick)="toggleModal()"
        >Save new item</goab-button
      >
    </goab-button-group>
  </ng-template>
</goab-modal>
const modal = document.getElementById("add-item-modal");
const openBtn = document.getElementById("open-modal-btn");
const cancelBtn = document.getElementById("cancel-btn");
const saveBtn = document.getElementById("save-btn");

openBtn.addEventListener("_click", () => {
  modal.setAttribute("open", "true");
});

modal.addEventListener("_close", () => {
  modal.removeAttribute("open");
});

cancelBtn.addEventListener("_click", () => {
  modal.removeAttribute("open");
});

saveBtn.addEventListener("_click", () => {
  modal.removeAttribute("open");
});
<goa-button version="2" id="open-modal-btn" type="tertiary" leadingicon="add"
  >Add another item</goa-button
>
<goa-modal version="2" id="add-item-modal" heading="Add a new item">
  <p>Fill in the information to create a new item</p>
  <goa-form-item version="2" label="Type" mt="l">
    <goa-dropdown version="2" id="type-dropdown">
      <goa-dropdown-item value="1" label="Option 1"></goa-dropdown-item>
      <goa-dropdown-item value="2" label="Option 2"></goa-dropdown-item>
    </goa-dropdown>
  </goa-form-item>
  <goa-form-item version="2" label="Name" mt="l">
    <goa-input version="2" name="name" width="100%" id="name-input"></goa-input>
  </goa-form-item>
  <goa-form-item version="2" label="Description" mt="l">
    <goa-textarea
      version="2"
      name="description"
      width="100%"
      rows="3"
      id="description-textarea"
    ></goa-textarea>
  </goa-form-item>
  <div slot="actions">
    <goa-button-group alignment="end">
      <goa-button version="2" id="cancel-btn" type="tertiary" size="compact"
        >Cancel</goa-button
      >
      <goa-button version="2" id="save-btn" type="primary" size="compact"
        >Save new item</goa-button
      >
    </goa-button-group>
  </div>
</goa-modal>

Add and edit lots of filters

const [open, setOpen] = useState(false);
<GoabButton onClick={() => setOpen(true)}>Filters</GoabButton>
<GoabDrawer
  heading="Filters"
  open={open}
  onClose={() => setOpen(false)}
  position="right"
  actions={
    <GoabButtonGroup alignment="start">
      <GoabButton type="primary" size="compact" onClick={() => setOpen(false)}>
        Apply filters
      </GoabButton>
      <GoabButton type="tertiary" size="compact" onClick={() => setOpen(false)}>
        Cancel
      </GoabButton>
    </GoabButtonGroup>
  }
>
  <GoabFormItem label="Entry status">
    <GoabCheckboxList name="entryStatus" onChange={() => {}}>
      <GoabCheckbox name="draft" text="Draft" value="draft" />
      <GoabCheckbox name="published" text="Published" value="published" />
    </GoabCheckboxList>
  </GoabFormItem>
  <GoabFormItem label="Assigned to - Region" mt="l">
    <GoabCheckboxList name="region" onChange={() => {}}>
      <GoabCheckbox name="calgary" text="Calgary" value="calgary" />
      <GoabCheckbox name="central" text="Central" value="central" />
      <GoabCheckbox name="edmonton" text="Edmonton" value="edmonton" />
      <GoabCheckbox name="north" text="North" value="north" />
      <GoabCheckbox name="south" text="South" value="south" />
    </GoabCheckboxList>
  </GoabFormItem>
  <GoabFormItem label="Assigned to" mt="l">
    <GoabDropdown name="assignedTo" onChange={() => {}}>
      <GoabDropdownItem value="1" label="Person 1" />
      <GoabDropdownItem value="2" label="Person 2" />
    </GoabDropdown>
  </GoabFormItem>
  <GoabFormItem label="Date taken" mt="l">
    <GoabRadioGroup name="dateTaken" onChange={() => {}}>
      <GoabRadioItem value="24" label="Last 24 hours" />
      <GoabRadioItem value="72" label="Last 72 hours" />
    </GoabRadioGroup>
  </GoabFormItem>
</GoabDrawer>
open = false;
assignedTo = "";
takenBy = "";

onClick() {
  this.open = true;
}

onClose() {
  this.open = false;
}

radioOnChange(event: any) {
  console.log(event);
}

onChangeAssignedTo(e: any) {
  this.assignedTo = e.value as string;
}

closeDrawer() {
  this.open = false;
}
<goab-button (onClick)="onClick()">Filters</goab-button>
<goab-drawer
  heading="Filters"
  [open]="open"
  (onClose)="onClose()"
  position="right"
  [actions]="actions"
>
  <goab-form-item label="Entry status">
    <goab-checkbox-list name="entryStatus" (onChange)="onCheckboxChange($event)">
      <goab-checkbox name="draft" text="Draft" value="draft"></goab-checkbox>
      <goab-checkbox name="published" text="Published" value="published"></goab-checkbox>
    </goab-checkbox-list>
  </goab-form-item>
  <goab-form-item label="Assigned to - Region" mt="l">
    <goab-checkbox-list name="region" (onChange)="onCheckboxChange($event)">
      <goab-checkbox name="calgary" text="Calgary" value="calgary"></goab-checkbox>
      <goab-checkbox name="central" text="Central" value="central"></goab-checkbox>
      <goab-checkbox name="edmonton" text="Edmonton" value="edmonton"></goab-checkbox>
      <goab-checkbox name="north" text="North" value="north"></goab-checkbox>
      <goab-checkbox name="south" text="South" value="south"></goab-checkbox>
    </goab-checkbox-list>
  </goab-form-item>
  <goab-form-item label="Assigned to" mt="l">
    <goab-dropdown
      [value]="assignedTo"
      name="assignedToData"
      (onChange)="onChangeAssignedTo($event)"
    >
      <goab-dropdown-item value="1" label="Person 1"></goab-dropdown-item>
      <goab-dropdown-item value="2" label="Person 2"></goab-dropdown-item>
    </goab-dropdown>
  </goab-form-item>
  <goab-form-item label="Date taken" mt="l">
    <goab-radio-group name="dateTaken" (onChange)="radioOnChange($event)">
      <goab-radio-item value="24" label="Last 24 hours"></goab-radio-item>
      <goab-radio-item value="72" label="Last 72 hours"></goab-radio-item>
    </goab-radio-group>
  </goab-form-item>
  <ng-template #actions>
    <goab-button-group alignment="start">
      <goab-button type="primary" size="compact" (onClick)="closeDrawer()"
        >Apply filters</goab-button
      >
      <goab-button type="tertiary" size="compact" (onClick)="closeDrawer()"
        >Cancel</goab-button
      >
    </goab-button-group>
  </ng-template>
</goab-drawer>
const drawer = document.getElementById("filters-drawer");
const openBtn = document.getElementById("open-filters-btn");
const applyBtn = document.getElementById("apply-filters-btn");
const cancelBtn = document.getElementById("cancel-btn");

openBtn.addEventListener("_click", () => {
  drawer.setAttribute("open", "true");
});

drawer.addEventListener("_close", () => {
  drawer.removeAttribute("open");
});

applyBtn.addEventListener("_click", () => {
  drawer.removeAttribute("open");
});

cancelBtn.addEventListener("_click", () => {
  drawer.removeAttribute("open");
});
<goa-button version="2" id="open-filters-btn">Filters</goa-button>
<goa-drawer version="2" id="filters-drawer" heading="Filters" position="right">
  <goa-form-item version="2" label="Entry status">
    <goa-checkbox-list name="entryStatus">
      <goa-checkbox version="2" name="draft" text="Draft" value="draft"></goa-checkbox>
      <goa-checkbox
        version="2"
        name="published"
        text="Published"
        value="published"
      ></goa-checkbox>
    </goa-checkbox-list>
  </goa-form-item>
  <goa-form-item version="2" label="Assigned to - Region" mt="l">
    <goa-checkbox-list name="region">
      <goa-checkbox
        version="2"
        name="calgary"
        text="Calgary"
        value="calgary"
      ></goa-checkbox>
      <goa-checkbox
        version="2"
        name="central"
        text="Central"
        value="central"
      ></goa-checkbox>
      <goa-checkbox
        version="2"
        name="edmonton"
        text="Edmonton"
        value="edmonton"
      ></goa-checkbox>
      <goa-checkbox version="2" name="north" text="North" value="north"></goa-checkbox>
      <goa-checkbox version="2" name="south" text="South" value="south"></goa-checkbox>
    </goa-checkbox-list>
  </goa-form-item>
  <goa-form-item version="2" label="Assigned to" mt="l">
    <goa-dropdown version="2" name="assignedTo">
      <goa-dropdown-item value="1" label="Person 1"></goa-dropdown-item>
      <goa-dropdown-item value="2" label="Person 2"></goa-dropdown-item>
    </goa-dropdown>
  </goa-form-item>
  <goa-form-item version="2" label="Date taken" mt="l">
    <goa-radio-group version="2" name="dateTaken">
      <goa-radio-item value="24" label="Last 24 hours"></goa-radio-item>
      <goa-radio-item value="72" label="Last 72 hours"></goa-radio-item>
    </goa-radio-group>
  </goa-form-item>
  <div slot="actions">
    <goa-button-group alignment="start">
      <goa-button version="2" id="apply-filters-btn" type="primary" size="compact"
        >Apply filters</goa-button
      >
      <goa-button version="2" id="cancel-btn" type="tertiary" size="compact"
        >Cancel</goa-button
      >
    </goa-button-group>
  </div>
</goa-drawer>

Ask a user for an address

const [address, setAddress] = useState("");
const [suite, setSuite] = useState("");
const [city, setCity] = useState("");
const [province, setProvince] = useState("");
const [postalCode, setPostalCode] = useState("");
<GoabText size="heading-l" mt="none" mb="xl">
  What is your address?
</GoabText>
<GoabFormItem label="Street Address">
  <GoabInput
    name="address"
    type="text"
    value={address}
    onChange={(e) => setAddress(e.value)}
    width="100%"
  />
</GoabFormItem>
<GoabFormItem label="Suite or unit #" mt="l">
  <GoabInput
    name="suite"
    type="text"
    value={suite}
    onChange={(e) => setSuite(e.value)}
    width="100%"
  />
</GoabFormItem>
<GoabFormItem label="City or town" mt="l">
  <GoabInput
    name="city"
    type="text"
    value={city}
    onChange={(e) => setCity(e.value)}
    width="100%"
  />
</GoabFormItem>
<GoabBlock direction="row" gap="l" mt="l">
  <GoabFormItem label="Province or territory">
    <GoabDropdown
      onChange={(e) => setProvince(e.value ?? "")}
      name="province"
      value={province}
      width="100%"
    >
      <GoabDropdownItem label="Alberta" value="AB" />
      <GoabDropdownItem label="British Columbia" value="BC" />
      <GoabDropdownItem label="Manitoba" value="MB" />
      <GoabDropdownItem label="New Brunswick" value="NB" />
      <GoabDropdownItem label="Newfoundland and Labrador" value="NL" />
      <GoabDropdownItem label="Northwest Territories" value="NT" />
      <GoabDropdownItem label="Nova Scotia" value="NS" />
      <GoabDropdownItem label="Nunavut" value="NU" />
      <GoabDropdownItem label="Ontario" value="ON" />
      <GoabDropdownItem label="Prince Edward Island" value="PE" />
      <GoabDropdownItem label="Quebec" value="QC" />
      <GoabDropdownItem label="Saskatchewan" value="SK" />
      <GoabDropdownItem label="Yukon" value="YT" />
    </GoabDropdown>
  </GoabFormItem>
  <GoabFormItem label="Postal Code">
    <GoabInput
      name="postalCode"
      type="text"
      value={postalCode}
      onChange={(e) => setPostalCode(e.value)}
      width="7ch"
    />
  </GoabFormItem>
</GoabBlock>
<GoabButtonGroup alignment="start" mt="2xl">
  <GoabButton type="primary" onClick={() => {}}>
    Save and continue
  </GoabButton>
  <GoabButton type="secondary" onClick={() => {}}>
    Cancel
  </GoabButton>
</GoabButtonGroup>
form!: FormGroup;

constructor(private fb: FormBuilder) {
  this.form = this.fb.group({
    address: [""],
    suite: [""],
    city: [""],
    province: [""],
    postalCode: [""],
  });
}

onClick() {
  // Handle form submission
}
<goab-text size="heading-l" mt="none" mb="xl">What is your address?</goab-text>
<goab-form-item label="Street Address">
  <goab-input
    name="address"
    type="text"
    [formControl]="form.controls.address"
    width="100%"
  ></goab-input>
</goab-form-item>
<goab-form-item label="Suite or unit #" mt="l">
  <goab-input
    name="suite"
    type="text"
    [formControl]="form.controls.suite"
    width="100%"
  ></goab-input>
</goab-form-item>
<goab-form-item label="City or town" mt="l">
  <goab-input
    name="city"
    type="text"
    [formControl]="form.controls.city"
    width="100%"
  ></goab-input>
</goab-form-item>
<goab-block direction="row" gap="l" mt="l">
  <goab-form-item label="Province or territory">
    <goab-dropdown name="province" [formControl]="form.controls.province" width="100%">
      <goab-dropdown-item label="Alberta" value="AB"></goab-dropdown-item>
      <goab-dropdown-item label="British Columbia" value="BC"></goab-dropdown-item>
      <goab-dropdown-item label="Manitoba" value="MB"></goab-dropdown-item>
      <goab-dropdown-item label="New Brunswick" value="NB"></goab-dropdown-item>
      <goab-dropdown-item
        label="Newfoundland and Labrador"
        value="NL"
      ></goab-dropdown-item>
      <goab-dropdown-item label="Northwest Territories" value="NT"></goab-dropdown-item>
      <goab-dropdown-item label="Nova Scotia" value="NS"></goab-dropdown-item>
      <goab-dropdown-item label="Nunavut" value="NU"></goab-dropdown-item>
      <goab-dropdown-item label="Ontario" value="ON"></goab-dropdown-item>
      <goab-dropdown-item label="Prince Edward Island" value="PE"></goab-dropdown-item>
      <goab-dropdown-item label="Quebec" value="QC"></goab-dropdown-item>
      <goab-dropdown-item label="Saskatchewan" value="SK"></goab-dropdown-item>
      <goab-dropdown-item label="Yukon" value="YT"></goab-dropdown-item>
    </goab-dropdown>
  </goab-form-item>
  <goab-form-item label="Postal Code">
    <goab-input
      name="postalCode"
      type="text"
      [formControl]="form.controls.postalCode"
      width="7ch"
    ></goab-input>
  </goab-form-item>
</goab-block>
<goab-button-group alignment="start" mt="2xl">
  <goab-button type="primary" (onClick)="onClick()">Save and continue</goab-button>
  <goab-button type="secondary" (onClick)="onClick()">Cancel</goab-button>
</goab-button-group>
document.getElementById("save-btn")?.addEventListener("_click", () => {
  console.log("Form submitted");
});
<goa-text size="heading-l" mt="none" mb="xl">What is your address?</goa-text>
<goa-form-item version="2" label="Street Address">
  <goa-input
    version="2"
    name="address"
    type="text"
    width="100%"
    id="address-input"
  ></goa-input>
</goa-form-item>
<goa-form-item version="2" label="Suite or unit #" mt="l">
  <goa-input
    version="2"
    name="suite"
    type="text"
    width="100%"
    id="suite-input"
  ></goa-input>
</goa-form-item>
<goa-form-item version="2" label="City or town" mt="l">
  <goa-input version="2" name="city" type="text" width="100%" id="city-input"></goa-input>
</goa-form-item>
<goa-block direction="row" gap="l" mt="l">
  <goa-form-item version="2" label="Province or territory">
    <goa-dropdown version="2" name="province" id="province-dropdown" width="100%">
      <goa-dropdown-item label="Alberta" value="AB"></goa-dropdown-item>
      <goa-dropdown-item label="British Columbia" value="BC"></goa-dropdown-item>
      <goa-dropdown-item label="Manitoba" value="MB"></goa-dropdown-item>
      <goa-dropdown-item label="New Brunswick" value="NB"></goa-dropdown-item>
      <goa-dropdown-item label="Newfoundland and Labrador" value="NL"></goa-dropdown-item>
      <goa-dropdown-item label="Northwest Territories" value="NT"></goa-dropdown-item>
      <goa-dropdown-item label="Nova Scotia" value="NS"></goa-dropdown-item>
      <goa-dropdown-item label="Nunavut" value="NU"></goa-dropdown-item>
      <goa-dropdown-item label="Ontario" value="ON"></goa-dropdown-item>
      <goa-dropdown-item label="Prince Edward Island" value="PE"></goa-dropdown-item>
      <goa-dropdown-item label="Quebec" value="QC"></goa-dropdown-item>
      <goa-dropdown-item label="Saskatchewan" value="SK"></goa-dropdown-item>
      <goa-dropdown-item label="Yukon" value="YT"></goa-dropdown-item>
    </goa-dropdown>
  </goa-form-item>
  <goa-form-item version="2" label="Postal Code">
    <goa-input
      version="2"
      name="postalCode"
      type="text"
      width="7ch"
      id="postal-input"
    ></goa-input>
  </goa-form-item>
</goa-block>
<goa-button-group alignment="start" mt="2xl">
  <goa-button version="2" type="primary" id="save-btn">Save and continue</goa-button>
  <goa-button version="2" type="secondary" id="cancel-btn">Cancel</goa-button>
</goa-button-group>

Ask a user one question at a time

<GoabLink leadingIcon="arrow-back" size="small">
  <a href="#">Back</a>
</GoabLink>
<GoabFormItem
  mt="xl"
  label="Are you currently in school?"
  labelSize="large"
  helpText="School includes foundational, skills and employment training, micro-credentials, post-secondary and continuing education."
>
  <GoabRadioGroup
    name="school"
    ariaLabel="are you currently in school?"
    onChange={() => {}}
  >
    <GoabRadioItem value="yes" label="Yes" />
    <GoabRadioItem value="no" label="No" />
  </GoabRadioGroup>
</GoabFormItem>
<GoabButton type="submit" mt="2xl">
  Save and continue
</GoabButton>
selectedValue = "";

onSchoolChange(event: GoabRadioGroupOnChangeDetail): void {
  this.selectedValue = event.value as string;
}
<goab-link leadingIcon="arrow-back" size="small">
  <a href="#">Back</a>
</goab-link>
<goab-form-item
  mt="xl"
  label="Are you currently in school?"
  labelSize="large"
  helpText="School includes foundational, skills and employment training, micro-credentials, post-secondary and continuing education."
>
  <goab-radio-group
    name="school"
    ariaLabel="are you currently in school?"
    (onChange)="onSchoolChange($event)"
  >
    <goab-radio-item value="yes" label="Yes"></goab-radio-item>
    <goab-radio-item value="no" label="No"></goab-radio-item>
  </goab-radio-group>
</goab-form-item>
<goab-button type="submit" mt="2xl"> Save and continue </goab-button>
document.querySelector("goa-radio-group").addEventListener("_change", (e) => {
  console.log("Selected:", e.detail.value);
});
<goa-link leadingicon="arrow-back" size="small">
  <a href="#">Back</a>
</goa-link>
<goa-form-item
  version="2"
  mt="xl"
  label="Are you currently in school?"
  labelsize="large"
  helptext="School includes foundational, skills and employment training, micro-credentials, post-secondary and continuing education."
>
  <goa-radio-group version="2" name="school" aria-label="are you currently in school?">
    <goa-radio-item value="yes" label="Yes"></goa-radio-item>
    <goa-radio-item value="no" label="No"></goa-radio-item>
  </goa-radio-group>
</goa-form-item>
<goa-button version="2" type="submit" mt="2xl"> Save and continue </goa-button>

Button with Icon

<GoabButtonGroup alignment="start">
  <GoabButton leadingIcon="arrow-back">Go back</GoabButton>
  <GoabButton trailingIcon="arrow-forward">Continue</GoabButton>
  <GoabButton type="secondary" leadingIcon="add">
    Add item
  </GoabButton>
</GoabButtonGroup>
<goab-button-group alignment="start">
  <goab-button leadingIcon="arrow-back">Go back</goab-button>
  <goab-button trailingIcon="arrow-forward">Continue</goab-button>
  <goab-button type="secondary" leadingIcon="add">Add item</goab-button>
</goab-button-group>
<goa-button-group alignment="start">
  <goa-button version="2" leadingicon="arrow-back">Go back</goa-button>
  <goa-button version="2" trailingicon="arrow-forward">Continue</goa-button>
  <goa-button version="2" type="secondary" leadingicon="add">Add item</goa-button>
</goa-button-group>

When using icons in buttons, the button text provides the accessible name. The icon is decorative and should be hidden from screen readers with aria-hidden.

Card view of case files

.case-file-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: var(--goa-space-m);
}
<GoabContainer mt="l">
  <div className="case-file-row">
    <GoabBlock direction="column" gap="2xs">
      <GoabText size="heading-xs" mt="none" mb="2xs">
        Fiscal year: 2021/2022
      </GoabText>
      <GoabText size="body-s" mt="none" mb="none">
        Submitted: April 23, 2023
      </GoabText>
    </GoabBlock>
    <GoabBlock direction="row" gap="l" alignment="center">
      <GoabBadge type="default" content="Not started" />
      <GoabButton type="tertiary" size="compact">
        Start
      </GoabButton>
    </GoabBlock>
  </div>
</GoabContainer>

<GoabContainer>
  <div className="case-file-row">
    <GoabBlock direction="column" gap="2xs">
      <GoabText size="heading-xs" mt="none" mb="2xs">
        Fiscal year: 2020/2021
      </GoabText>
      <GoabText size="body-s" mt="none" mb="none">
        Submitted: April 9, 2022
      </GoabText>
    </GoabBlock>
    <GoabBlock direction="row" gap="l" alignment="center">
      <GoabBadge type="important" content="Information needed" />
      <GoabButton type="tertiary" size="compact">
        Edit
      </GoabButton>
    </GoabBlock>
  </div>
</GoabContainer>

<GoabContainer>
  <div className="case-file-row">
    <GoabBlock direction="column" gap="2xs">
      <GoabText size="heading-xs" mt="none" mb="2xs">
        Fiscal year: 2019/2020
      </GoabText>
      <GoabText size="body-s" mt="none" mb="none">
        Submitted: April 14, 2021
      </GoabText>
    </GoabBlock>
    <GoabBlock direction="row" gap="l" alignment="center">
      <GoabBadge type="success" content="Approved" />
      <GoabButton type="tertiary" size="compact">
        View
      </GoabButton>
    </GoabBlock>
  </div>
</GoabContainer>
<goab-container mt="l">
  <div class="case-file-row">
    <goab-block direction="column" gap="2xs">
      <goab-text size="heading-xs" mt="none" mb="2xs">Fiscal year: 2021/2022</goab-text>
      <goab-text size="body-s" mt="none" mb="none">Submitted: April 23, 2023</goab-text>
    </goab-block>
    <goab-block direction="row" gap="l" alignment="center">
      <goab-badge type="default" content="Not started"></goab-badge>
      <goab-button type="tertiary" size="compact">Start</goab-button>
    </goab-block>
  </div>
</goab-container>

<goab-container>
  <div class="case-file-row">
    <goab-block direction="column" gap="2xs">
      <goab-text size="heading-xs" mt="none" mb="2xs">Fiscal year: 2020/2021</goab-text>
      <goab-text size="body-s" mt="none" mb="none">Submitted: April 9, 2022</goab-text>
    </goab-block>
    <goab-block direction="row" gap="l" alignment="center">
      <goab-badge type="important" content="Information needed"></goab-badge>
      <goab-button type="tertiary" size="compact">Edit</goab-button>
    </goab-block>
  </div>
</goab-container>

<goab-container>
  <div class="case-file-row">
    <goab-block direction="column" gap="2xs">
      <goab-text size="heading-xs" mt="none" mb="2xs">Fiscal year: 2019/2020</goab-text>
      <goab-text size="body-s" mt="none" mb="none">Submitted: April 14, 2021</goab-text>
    </goab-block>
    <goab-block direction="row" gap="l" alignment="center">
      <goab-badge type="success" content="Approved"></goab-badge>
      <goab-button type="tertiary" size="compact">View</goab-button>
    </goab-block>
  </div>
</goab-container>
.case-file-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: var(--goa-space-m);
}
<goa-container mt="l">
  <div class="case-file-row">
    <goa-block direction="column" gap="2xs">
      <goa-text size="heading-xs" mt="none" mb="2xs">Fiscal year: 2021/2022</goa-text>
      <goa-text size="body-s" mt="none" mb="none">Submitted: April 23, 2023</goa-text>
    </goa-block>
    <goa-block direction="row" gap="l" alignment="center">
      <goa-badge version="2" type="default" content="Not started"></goa-badge>
      <goa-button version="2" type="tertiary" size="compact">Start</goa-button>
    </goa-block>
  </div>
</goa-container>

<goa-container>
  <div class="case-file-row">
    <goa-block direction="column" gap="2xs">
      <goa-text size="heading-xs" mt="none" mb="2xs">Fiscal year: 2020/2021</goa-text>
      <goa-text size="body-s" mt="none" mb="none">Submitted: April 9, 2022</goa-text>
    </goa-block>
    <goa-block direction="row" gap="l" alignment="center">
      <goa-badge version="2" type="important" content="Information needed"></goa-badge>
      <goa-button version="2" type="tertiary" size="compact">Edit</goa-button>
    </goa-block>
  </div>
</goa-container>

<goa-container>
  <div class="case-file-row">
    <goa-block direction="column" gap="2xs">
      <goa-text size="heading-xs" mt="none" mb="2xs">Fiscal year: 2019/2020</goa-text>
      <goa-text size="body-s" mt="none" mb="none">Submitted: April 14, 2021</goa-text>
    </goa-block>
    <goa-block direction="row" gap="l" alignment="center">
      <goa-badge version="2" type="success" content="Approved"></goa-badge>
      <goa-button version="2" type="tertiary" size="compact">View</goa-button>
    </goa-block>
  </div>
</goa-container>

Confirm a change

const [open, setOpen] = useState(false);
const [effectiveDate, setEffectiveDate] = useState<Date | undefined>(new Date());

const onChangeEffectiveDate = (detail: GoabDatePickerOnChangeDetail) => {
  setEffectiveDate(detail.value as Date);
};
<GoabButton onClick={() => setOpen(true)}>Save and continue</GoabButton>

<GoabModal
  heading="Address has changed"
  open={open}
  onClose={() => setOpen(false)}
  actions={
    <GoabButtonGroup alignment="end">
      <GoabButton type="secondary" size="compact" onClick={() => setOpen(false)}>
        Undo address change
      </GoabButton>
      <GoabButton type="primary" size="compact" onClick={() => setOpen(false)}>
        Confirm
      </GoabButton>
    </GoabButtonGroup>
  }
>
  <GoabContainer
    type="non-interactive"
    accent="filled"
    padding="compact"
    width="full"
  >
    <GoabText tag="h4" mt="none" mb="s">
      Before
    </GoabText>
    <GoabText mt="none">123456 78 Ave NW, Edmonton, Alberta</GoabText>
    <GoabText tag="h4" mt="none" mb="s">
      After
    </GoabText>
    <GoabText mt="none" mb="none">
      881 12 Ave NW, Edmonton, Alberta
    </GoabText>
  </GoabContainer>
  <GoabFormItem label="Effective date" mt="l">
    <GoabDatePicker
      onChange={onChangeEffectiveDate}
      name="effectiveDate"
      value={effectiveDate}
    />
  </GoabFormItem>
</GoabModal>
open = false;
effectiveDate = new Date();

toggleModal(): void {
  this.open = !this.open;
}

onChangeEffectiveDate(event: GoabDatePickerOnChangeDetail): void {
  this.effectiveDate = event.value as Date;
}
<goab-button (onClick)="toggleModal()">Save and continue</goab-button>

<goab-modal
  [open]="open"
  (onClose)="toggleModal()"
  heading="Address has changed"
  [actions]="actions"
>
  <goab-container type="non-interactive" accent="filled" padding="compact" width="full">
    <goab-text tag="h4" mt="none" mb="s">Before</goab-text>
    <goab-text mt="none">123456 78 Ave NW, Edmonton, Alberta</goab-text>
    <goab-text tag="h4" mt="none" mb="s">After</goab-text>
    <goab-text mt="none" mb="none">881 12 Ave NW, Edmonton, Alberta</goab-text>
  </goab-container>
  <goab-form-item label="Effective date" mt="l">
    <goab-date-picker
      (onChange)="onChangeEffectiveDate($event)"
      name="effectiveDate"
      [value]="effectiveDate"
    ></goab-date-picker>
  </goab-form-item>
  <ng-template #actions>
    <goab-button-group alignment="end">
      <goab-button type="secondary" size="compact" (onClick)="toggleModal()">
        Undo address change
      </goab-button>
      <goab-button type="primary" size="compact" (onClick)="toggleModal()">
        Confirm
      </goab-button>
    </goab-button-group>
  </ng-template>
</goab-modal>
const modal = document.getElementById("change-modal");
const openBtn = document.getElementById("open-modal-btn");
const undoBtn = document.getElementById("undo-btn");
const confirmBtn = document.getElementById("confirm-btn");
const datePicker = document.getElementById("effective-date");

let effectiveDate = new Date();
datePicker.setAttribute("value", effectiveDate.toISOString());

openBtn.addEventListener("_click", () => {
  modal.setAttribute("open", "true");
});

undoBtn.addEventListener("_click", () => {
  modal.removeAttribute("open");
});

confirmBtn.addEventListener("_click", () => {
  modal.removeAttribute("open");
});

modal.addEventListener("_close", () => {
  modal.removeAttribute("open");
});

datePicker.addEventListener("_change", (e) => {
  effectiveDate = e.detail.value;
});
<goa-button version="2" id="open-modal-btn">Save and continue</goa-button>

<goa-modal version="2" id="change-modal" heading="Address has changed">
  <goa-container type="non-interactive" accent="filled" padding="compact" width="full">
    <goa-text as="h4" mt="none" mb="s">Before</goa-text>
    <goa-text mt="none">123456 78 Ave NW, Edmonton, Alberta</goa-text>
    <goa-text as="h4" mt="none" mb="s">After</goa-text>
    <goa-text mt="none" mb="none">881 12 Ave NW, Edmonton, Alberta</goa-text>
  </goa-container>
  <goa-form-item version="2" label="Effective date" mt="l">
    <goa-date-picker
      version="2"
      id="effective-date"
      name="effectiveDate"
    ></goa-date-picker>
  </goa-form-item>
  <div slot="actions">
    <goa-button-group alignment="end">
      <goa-button version="2" type="secondary" size="compact" id="undo-btn">
        Undo address change
      </goa-button>
      <goa-button version="2" type="primary" size="compact" id="confirm-btn">
        Confirm
      </goa-button>
    </goa-button-group>
  </div>
</goa-modal>

Confirm a destructive action

const [open, setOpen] = useState(false);
<GoabButton type="tertiary" leadingIcon="trash" onClick={() => setOpen(true)}>
  Delete record
</GoabButton>
<GoabModal
  heading="Are you sure you want to delete this record?"
  open={open}
  onClose={() => setOpen(false)}
  actions={
    <GoabButtonGroup alignment="end">
      <GoabButton type="tertiary" size="compact" onClick={() => setOpen(false)}>
        Cancel
      </GoabButton>
      <GoabButton
        type="primary"
        variant="destructive"
        size="compact"
        onClick={() => setOpen(false)}
      >
        Delete record
      </GoabButton>
    </GoabButtonGroup>
  }
>
  <p>This action cannot be undone.</p>
</GoabModal>
open = false;

toggleModal(): void {
  this.open = !this.open;
}
<goab-button type="tertiary" leadingIcon="trash" (onClick)="toggleModal()"
  >Delete record</goab-button
>
<goab-modal
  [open]="open"
  (onClose)="toggleModal()"
  heading="Are you sure you want to delete this record?"
  [actions]="actions"
>
  <p>This action cannot be undone.</p>
  <ng-template #actions>
    <goab-button-group alignment="end">
      <goab-button type="tertiary" size="compact" (onClick)="toggleModal()"
        >Cancel</goab-button
      >
      <goab-button
        type="primary"
        variant="destructive"
        size="compact"
        (onClick)="toggleModal()"
        >Delete record</goab-button
      >
    </goab-button-group>
  </ng-template>
</goab-modal>
const modal = document.getElementById("delete-modal");
const deleteBtn = document.getElementById("delete-btn");
const cancelBtn = document.getElementById("cancel-btn");
const confirmDeleteBtn = document.getElementById("confirm-delete-btn");

deleteBtn.addEventListener("_click", () => {
  modal.setAttribute("open", "true");
});

cancelBtn.addEventListener("_click", () => {
  modal.removeAttribute("open");
});

confirmDeleteBtn.addEventListener("_click", () => {
  modal.removeAttribute("open");
});

modal.addEventListener("_close", () => {
  modal.removeAttribute("open");
});
<goa-button version="2" type="tertiary" leadingicon="trash" id="delete-btn"
  >Delete record</goa-button
>
<goa-modal
  version="2"
  id="delete-modal"
  heading="Are you sure you want to delete this record?"
>
  <p>This action cannot be undone.</p>
  <div slot="actions">
    <goa-button-group alignment="end">
      <goa-button version="2" type="tertiary" size="compact" id="cancel-btn"
        >Cancel</goa-button
      >
      <goa-button
        version="2"
        type="primary"
        variant="destructive"
        size="compact"
        id="confirm-delete-btn"
        >Delete record</goa-button
      >
    </goa-button-group>
  </div>
</goa-modal>

Confirm before navigating away

const [open, setOpen] = useState(false);

const handleChangeRoute = () => {
  setOpen(false);
  // In a real app, you would use your router's navigate function
  // setTimeout(() => navigate("/some-path"), 300);
  console.log("Navigating to new route...");
};
<GoabButton onClick={() => setOpen(true)}>Open</GoabButton>
<GoabModal
  heading="Are you sure you want to change route?"
  open={open}
  onClose={() => setOpen(false)}
  actions={
    <GoabButtonGroup alignment="end">
      <GoabButton type="secondary" size="compact" onClick={() => setOpen(false)}>
        Cancel
      </GoabButton>
      <GoabButton type="primary" size="compact" onClick={handleChangeRoute}>
        Change route
      </GoabButton>
    </GoabButtonGroup>
  }
/>
open = false;

constructor(private router: Router) {}

onOpen(): void {
  this.open = true;
}

onClose(): void {
  this.open = false;
}

onChangeRoute(): void {
  this.open = false;
  // setTimeout will allow any modal transitions to be run
  setTimeout(() => this.router.navigate(["/components"]), 0);
}
<goab-button (onClick)="onOpen()">Open</goab-button>
<goab-modal
  [open]="open"
  heading="Are you sure you want to change route?"
  [actions]="actions"
>
  <ng-template #actions>
    <goab-button-group alignment="end">
      <goab-button type="secondary" size="compact" (onClick)="onClose()"
        >Cancel</goab-button
      >
      <goab-button type="primary" size="compact" (onClick)="onChangeRoute()"
        >Change route</goab-button
      >
    </goab-button-group>
  </ng-template>
</goab-modal>
const modal = document.getElementById("route-modal");
const openBtn = document.getElementById("open-btn");
const cancelBtn = document.getElementById("cancel-btn");
const changeRouteBtn = document.getElementById("change-route-btn");

openBtn.addEventListener("_click", () => {
  modal.setAttribute("open", "true");
});

cancelBtn.addEventListener("_click", () => {
  modal.removeAttribute("open");
});

changeRouteBtn.addEventListener("_click", () => {
  modal.removeAttribute("open");
  // setTimeout will allow any modal transitions to be run
  setTimeout(() => {
    window.location.href = "/components";
  }, 300);
});

modal.addEventListener("_close", () => {
  modal.removeAttribute("open");
});
<goa-button version="2" id="open-btn">Open</goa-button>
<goa-modal version="2" id="route-modal" heading="Are you sure you want to change route?">
  <div slot="actions">
    <goa-button-group alignment="end">
      <goa-button version="2" type="secondary" size="compact" id="cancel-btn"
        >Cancel</goa-button
      >
      <goa-button version="2" type="primary" size="compact" id="change-route-btn"
        >Change route</goa-button
      >
    </goa-button-group>
  </div>
</goa-modal>

Confirm that an application was submitted

<GoabText tag="h1" mt="none">
  You have completed the application
</GoabText>

<GoabCallout type="success" heading="Your application was successful">
  <GoabText mt="none" mb="m">
    You will receive a copy of the confirmation to the email person@email.com
  </GoabText>
  <GoabText mt="none" mb="none">
    Confirmation number: <strong>1234ABC</strong>
  </GoabText>
</GoabCallout>

<GoabText tag="h2" mt="xl" mb="m">
  Go back to the dashboard, or direct your user somewhere else useful.
</GoabText>
<GoabText>
  Other information about what was just completed, other tertiary information,
  and/or contact information.
  <br />
  Phone: <a href="tel:7801234567">780 123 4567</a>
  <br />
  Email: <a href="mailto:information@gov.ab.ca">information@gov.ab.ca</a>
</GoabText>

<GoabButtonGroup alignment="start" mt="2xl">
  <GoabButton type="primary">Go to application</GoabButton>
  <GoabButton type="secondary">Back to dashboard</GoabButton>
</GoabButtonGroup>
<goab-text tag="h1" mt="none">You have completed the application</goab-text>

<goab-callout type="success" heading="Your application was successful">
  <goab-text mt="none" mb="m"
    >You will receive a copy of the confirmation to the email
    person&#64;email.com</goab-text
  >
  <goab-text mt="none" mb="none">Confirmation number: <strong>1234ABC</strong></goab-text>
</goab-callout>

<goab-text tag="h2" mt="xl" mb="m"
  >Go back to the dashboard, or direct your user somewhere else useful.</goab-text
>
<goab-text
  >Other information about what was just completed, other tertiary information, and/or
  contact information.
  <br />
  Phone: <a href="tel:7801234567">780 123 4567</a>
  <br />
  Email: <a href="mailto:information@gov.ab.ca">information&#64;gov.ab.ca</a>
</goab-text>

<goab-button-group alignment="start" mt="2xl">
  <goab-button type="primary">Go to application</goab-button>
  <goab-button type="secondary">Back to dashboard</goab-button>
</goab-button-group>
<goa-text as="h1" mt="none">You have completed the application</goa-text>

<goa-callout version="2" type="success" heading="Your application was successful">
  <goa-text mt="none" mb="m"
    >You will receive a copy of the confirmation to the email person@email.com</goa-text
  >
  <goa-text mt="none" mb="none">Confirmation number: <strong>1234ABC</strong></goa-text>
</goa-callout>

<goa-text as="h2" mt="xl" mb="m"
  >Go back to the dashboard, or direct your user somewhere else useful.</goa-text
>
<goa-text
  >Other information about what was just completed, other tertiary information, and/or
  contact information.
  <br />
  Phone: <a href="tel:7801234567">780 123 4567</a>
  <br />
  Email: <a href="mailto:information@gov.ab.ca">information@gov.ab.ca</a>
</goa-text>

<goa-button-group alignment="start" mt="2xl">
  <goa-button version="2" type="primary">Go to application</goa-button>
  <goa-button version="2" type="secondary">Back to dashboard</goa-button>
</goa-button-group>

Display user information

const handleAddToCalendar = () => {
  console.log("Add to calendar clicked");
};
<GoabContainer>
  <GoabText tag="span" size="body-m" color="secondary" mt="none" mb="none">
    Housing Advisor
  </GoabText>
  <GoabText size="heading-m" mt="none" mb="s">
    Tracy Hero
  </GoabText>
  <GoabBlock direction="row" gap="s">
    <GoabBlock direction="column" gap="m">
      <GoabText tag="span" size="heading-xs" mt="none" mb="none">
        Email
      </GoabText>
      <GoabText tag="span" size="heading-xs" mt="none" mb="none">
        Phone
      </GoabText>
    </GoabBlock>
    <GoabBlock direction="column" gap="m">
      <GoabText tag="span" size="body-m" mt="none" mb="none">
        tracyhero@email.com
      </GoabText>
      <GoabText tag="span" size="body-m" mt="none" mb="none">
        283-203-4921
      </GoabText>
    </GoabBlock>
  </GoabBlock>
</GoabContainer>

<GoabContainer
  type="non-interactive"
  accent="thick"
  heading="Upcoming important due dates"
  actions={
    <GoabButton
      type="tertiary"
      size="compact"
      leadingIcon="calendar"
      onClick={handleAddToCalendar}
    >
      Add to calendar
    </GoabButton>
  }
>
  <GoabTable width="100%" striped>
    <tbody>
      <tr>
        <td>Business plan submission</td>
        <td style={{ textAlign: "right" }}>June 30, 2024</td>
      </tr>
      <tr>
        <td>Annual review</td>
        <td style={{ textAlign: "right" }}>October 3, 2024</td>
      </tr>
      <tr>
        <td>Application submission</td>
        <td style={{ textAlign: "right" }}>December 20, 2024</td>
      </tr>
      <tr>
        <td>Application review</td>
        <td style={{ textAlign: "right" }}>January 3, 2025</td>
      </tr>
    </tbody>
  </GoabTable>
</GoabContainer>
onAddToCalendar(): void {
  console.log("Add to calendar clicked");
}
<goab-container>
  <goab-text tag="span" size="body-m" color="secondary" mt="none" mb="none"
    >Housing Advisor</goab-text
  >
  <goab-text size="heading-m" mt="none" mb="s">Tracy Hero</goab-text>
  <goab-block direction="row" gap="s">
    <goab-block direction="column" gap="m">
      <goab-text tag="span" size="heading-xs" mt="none" mb="none">Email</goab-text>
      <goab-text tag="span" size="heading-xs" mt="none" mb="none">Phone</goab-text>
    </goab-block>
    <goab-block direction="column" gap="m">
      <goab-text tag="span" size="body-m" mt="none" mb="none"
        >tracyhero&#64;email.com</goab-text
      >
      <goab-text tag="span" size="body-m" mt="none" mb="none">283-203-4921</goab-text>
    </goab-block>
  </goab-block>
</goab-container>

<goab-container type="non-interactive" accent="thick">
  <div slot="title">Upcoming important due dates</div>
  <div slot="actions">
    <goab-button
      type="tertiary"
      size="compact"
      leadingIcon="calendar"
      (onClick)="onAddToCalendar()"
    >
      Add to calendar
    </goab-button>
  </div>
  <goab-table width="100%" [striped]="true">
    <tbody>
      <tr>
        <td>Business plan submission</td>
        <td style="text-align: right">June 30, 2024</td>
      </tr>
      <tr>
        <td>Annual review</td>
        <td style="text-align: right">October 3, 2024</td>
      </tr>
      <tr>
        <td>Application submission</td>
        <td style="text-align: right">December 20, 2024</td>
      </tr>
      <tr>
        <td>Application review</td>
        <td style="text-align: right">January 3, 2025</td>
      </tr>
    </tbody>
  </goab-table>
</goab-container>
const calendarBtn = document.getElementById("calendar-btn");
calendarBtn.addEventListener("_click", () => {
  console.log("Add to calendar clicked");
});
<goa-container>
  <goa-text as="span" size="body-m" color="secondary" mt="none" mb="none"
    >Housing Advisor</goa-text
  >
  <goa-text size="heading-m" mt="none" mb="s">Tracy Hero</goa-text>
  <goa-block direction="row" gap="s">
    <goa-block direction="column" gap="m">
      <goa-text as="span" size="heading-xs" mt="none" mb="none">Email</goa-text>
      <goa-text as="span" size="heading-xs" mt="none" mb="none">Phone</goa-text>
    </goa-block>
    <goa-block direction="column" gap="m">
      <goa-text as="span" size="body-m" mt="none" mb="none">tracyhero@email.com</goa-text>
      <goa-text as="span" size="body-m" mt="none" mb="none">283-203-4921</goa-text>
    </goa-block>
  </goa-block>
</goa-container>

<goa-container type="non-interactive" accent="thick">
  <div slot="title">Upcoming important due dates</div>
  <div slot="actions">
    <goa-button
      version="2"
      id="calendar-btn"
      type="tertiary"
      size="compact"
      leadingicon="calendar"
    >
      Add to calendar
    </goa-button>
  </div>
  <goa-table version="2" width="100%" striped="true">
    <table style="width: 100%">
      <tbody>
        <tr>
          <td>Business plan submission</td>
          <td style="text-align: right">June 30, 2024</td>
        </tr>
        <tr>
          <td>Annual review</td>
          <td style="text-align: right">October 3, 2024</td>
        </tr>
        <tr>
          <td>Application submission</td>
          <td style="text-align: right">December 20, 2024</td>
        </tr>
        <tr>
          <td>Application review</td>
          <td style="text-align: right">January 3, 2025</td>
        </tr>
      </tbody>
    </table>
  </goa-table>
</goa-container>

Dynamically add an item to a dropdown list

type Task = {
  value: string;
  label: string;
  mount: GoabDropdownItemMountType;
};

const DEFAULT_TASKS: Task[] = [
  { label: "Finish Report", value: "finish-report", mount: "append" },
  { label: "Attend Meeting", value: "attend-meeting", mount: "append" },
  { label: "Reply Emails", value: "reply-emails", mount: "append" },
];

const [tasks, setTasks] = useState<Task[]>(DEFAULT_TASKS);
const [newTask, setNewTask] = useState<string>("");
const [mountType, setMountType] = useState<string>("append");
const [selectedTask, setSelectedTask] = useState<string>("");
const [taskError, setTaskError] = useState<boolean>(false);
const [isReset, setIsReset] = useState<boolean>(false);

function onMountTypeChange(value: string | undefined) {
  setMountType(value as string);
}

function addTask() {
  if (newTask === "") {
    setTaskError(true);
    return;
  }
  setTaskError(false);

  const task: Task = {
    label: newTask,
    value: newTask.toLowerCase().replace(" ", "-"),
    mount: mountType as GoabDropdownItemMountType,
  };
  setTasks([...tasks, task]);
  setNewTask("");
  setIsReset(false);
}

function reset() {
  setTasks(DEFAULT_TASKS);
  setMountType("append");
  setNewTask("");
  setSelectedTask("");
  setTaskError(false);
  setIsReset(true);
}
<GoabFormItem
  requirement="required"
  label="Name of item"
  error={taskError ? "Please enter item name" : undefined}
  helpText="Add an item to the dropdown list below"
>
  <GoabInput
    onChange={(event: GoabInputOnChangeDetail) => setNewTask(event.value)}
    name="item"
    value={newTask}
  />
</GoabFormItem>

<GoabFormItem mt="l" label="Add to">
  <GoabRadioGroup
    name="mountType"
    onChange={(event: GoabRadioGroupOnChangeDetail) =>
      onMountTypeChange(event.value)
    }
    value={mountType}
    orientation="horizontal"
  >
    <GoabRadioItem value="prepend" label="Start" />
    <GoabRadioItem value="append" label="End" />
  </GoabRadioGroup>
</GoabFormItem>

<GoabButtonGroup alignment="start" gap="relaxed" mt="l">
  <GoabButton type="primary" onClick={addTask}>
    Add new item
  </GoabButton>
  <GoabButton type="tertiary" onClick={reset}>
    Reset list
  </GoabButton>
</GoabButtonGroup>

<GoabDivider mt="l" />

<GoabFormItem mt="l" label="All items">
  <div style={{ width: isReset ? "320px" : "auto" }}>
    <GoabDropdown
      key={tasks.length}
      onChange={(event: GoabDropdownOnChangeDetail) =>
        setSelectedTask(event.value as string)
      }
      value={selectedTask}
      name="selectedTask"
    >
      {tasks.map((task) => (
        <GoabDropdownItem
          key={task.value}
          value={task.value}
          mountType={task.mount}
          label={task.label}
        />
      ))}
    </GoabDropdown>
  </div>
</GoabFormItem>
defaultTasks: Task[] = [
  { label: "Finish Report", value: "finish-report", mount: "append" },
  { label: "Attend Meeting", value: "attend-meeting", mount: "append" },
  { label: "Reply Emails", value: "reply-emails", mount: "append" },
];

tasks: Task[] = [...this.defaultTasks];
newTask = "";
mountType: GoabDropdownItemMountType = "append";
selectedTask = "";
taskError = false;
renderTrigger = true;

onMountTypeChange(event: GoabRadioGroupOnChangeDetail): void {
  this.mountType = event.value as GoabDropdownItemMountType;
}

onNewTaskChange(event: GoabInputOnChangeDetail): void {
  this.newTask = event.value;
  this.taskError = false;
}

onSelectedTaskChange(event: GoabDropdownOnChangeDetail): void {
  this.selectedTask = event.value as string;
}

addTask(): void {
  if (this.newTask === "") {
    this.taskError = true;
    return;
  }
  this.taskError = false;

  const task: Task = {
    label: this.newTask,
    value: this.newTask.toLowerCase().replace(" ", "-"),
    mount: this.mountType,
  };
  this.tasks =
    this.mountType === "prepend" ? [task, ...this.tasks] : [...this.tasks, task];
  this.newTask = "";
}

reset(): void {
  this.newTask = "";
  this.selectedTask = "";
  this.taskError = false;
  this.tasks = [...this.defaultTasks];
  this.forceRerender();
}

forceRerender(): void {
  this.renderTrigger = false;
  setTimeout(() => {
    this.renderTrigger = true;
  }, 0);
}

trackByFn(index: number, item: Task): string {
  return item.value;
}
<goab-form-item
  requirement="required"
  label="Name of item"
  [error]="taskError ? 'Please enter item name' : undefined"
  helpText="Add an item to the dropdown list below"
>
  <goab-input name="item" [value]="newTask" (onChange)="onNewTaskChange($event)">
  </goab-input>
</goab-form-item>

<goab-form-item mt="l" label="Add to">
  <goab-radio-group
    name="mountType"
    [value]="mountType"
    orientation="horizontal"
    (onChange)="onMountTypeChange($event)"
  >
    <goab-radio-item value="prepend" label="Start"></goab-radio-item>
    <goab-radio-item value="append" label="End"></goab-radio-item>
  </goab-radio-group>
</goab-form-item>

<goab-button-group alignment="start" gap="relaxed" mt="l">
  <goab-button type="primary" (onClick)="addTask()"> Add new item </goab-button>
  <goab-button type="tertiary" (onClick)="reset()"> Reset list </goab-button>
</goab-button-group>

<goab-divider mt="l"></goab-divider>

<goab-form-item mt="l" label="All items">
  <ng-container *ngIf="renderTrigger">
    <goab-dropdown
      [value]="selectedTask"
      name="selectedTask"
      (onChange)="onSelectedTaskChange($event)"
    >
      @for (task of tasks; track task.value) {
      <goab-dropdown-item
        [value]="task.value"
        [mountType]="task.mount"
        [label]="task.label"
      >
      </goab-dropdown-item>
      }
    </goab-dropdown>
  </ng-container>
</goab-form-item>
const itemInput = document.getElementById("item-input");
const itemFormItem = document.getElementById("item-form-item");
const mountTypeGroup = document.getElementById("mount-type");
const addBtn = document.getElementById("add-btn");
const resetBtn = document.getElementById("reset-btn");
const dropdown = document.getElementById("task-dropdown");

let mountType = "append";
let newTask = "";

const defaultItems = [
  { value: "finish-report", label: "Finish Report" },
  { value: "attend-meeting", label: "Attend Meeting" },
  { value: "reply-emails", label: "Reply Emails" },
];

mountTypeGroup.addEventListener("_change", (e) => {
  mountType = e.detail.value;
});

itemInput.addEventListener("_change", (e) => {
  newTask = e.detail.value;
  itemFormItem.removeAttribute("error");
});

addBtn.addEventListener("_click", () => {
  if (newTask === "") {
    itemFormItem.setAttribute("error", "Please enter item name");
    return;
  }

  const newItem = document.createElement("goa-dropdown-item");
  newItem.setAttribute("value", newTask.toLowerCase().replace(" ", "-"));
  newItem.setAttribute("label", newTask);
  newItem.setAttribute("mount", mountType);
  dropdown.appendChild(newItem);

  itemInput.value = "";
  newTask = "";
});

resetBtn.addEventListener("_click", () => {
  dropdown.innerHTML = "";
  defaultItems.forEach((item) => {
    const dropdownItem = document.createElement("goa-dropdown-item");
    dropdownItem.setAttribute("value", item.value);
    dropdownItem.setAttribute("label", item.label);
    dropdown.appendChild(dropdownItem);
  });
  itemInput.value = "";
  newTask = "";
  itemFormItem.removeAttribute("error");
});
<goa-form-item
  version="2"
  id="item-form-item"
  requirement="required"
  label="Name of item"
  helptext="Add an item to the dropdown list below"
>
  <goa-input version="2" id="item-input" name="item"></goa-input>
</goa-form-item>

<goa-form-item version="2" mt="l" label="Add to">
  <goa-radio-group
    version="2"
    id="mount-type"
    name="mountType"
    value="append"
    orientation="horizontal"
  >
    <goa-radio-item value="prepend" label="Start"></goa-radio-item>
    <goa-radio-item value="append" label="End"></goa-radio-item>
  </goa-radio-group>
</goa-form-item>

<goa-button-group alignment="start" gap="relaxed" mt="l">
  <goa-button version="2" id="add-btn" type="primary">Add new item</goa-button>
  <goa-button version="2" id="reset-btn" type="tertiary">Reset list</goa-button>
</goa-button-group>

<goa-divider mt="l"></goa-divider>

<goa-form-item version="2" mt="l" label="All items">
  <goa-dropdown version="2" id="task-dropdown" name="selectedTask">
    <goa-dropdown-item value="finish-report" label="Finish Report"></goa-dropdown-item>
    <goa-dropdown-item value="attend-meeting" label="Attend Meeting"></goa-dropdown-item>
    <goa-dropdown-item value="reply-emails" label="Reply Emails"></goa-dropdown-item>
  </goa-dropdown>
</goa-form-item>

Filter a list using a push drawer

const [open, setOpen] = useState(false);
<div style={{ display: "flex", minHeight: "480px" }}>
  <div style={{ flex: 1, minWidth: 0 }}>
    <div
      style={{
        display: "flex",
        alignItems: "center",
        gap: "1rem",
        marginBottom: "1rem",
      }}
    >
      <h3 style={{ flex: 1, margin: 0 }}>All cases</h3>
      {!open && (
        <GoabButton
          type="secondary"
          size="compact"
          leadingIcon="filter"
          onClick={() => setOpen(true)}
        >
          Filters
        </GoabButton>
      )}
    </div>

    <GoabTable width="100%">
      <table width="100%">
        <thead>
          <tr>
            <th>Status</th>
            <th>Name</th>
            <th>File number</th>
            <th>Act</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>
              <GoabBadge type="success" content="Completed" />
            </td>
            <td>Gilbert Barton</td>
            <td>24567-9876</td>
            <td>Traffic safety act</td>
          </tr>
          <tr>
            <td>
              <GoabBadge type="information" content="New" />
            </td>
            <td>Brynn Hurley</td>
            <td>98765-3456</td>
            <td>Trespass to premises act</td>
          </tr>
          <tr>
            <td>
              <GoabBadge type="default" content="In review" />
            </td>
            <td>Marco Silva</td>
            <td>34521-7890</td>
            <td>Gaming, liquor, and cannabis act</td>
          </tr>
          <tr>
            <td>
              <GoabBadge type="success" content="Completed" />
            </td>
            <td>Dana Chen</td>
            <td>55123-4567</td>
            <td>Traffic safety act</td>
          </tr>
          <tr>
            <td>
              <GoabBadge type="information" content="New" />
            </td>
            <td>Amira Hassan</td>
            <td>67890-1234</td>
            <td>Trespass to premises act</td>
          </tr>
        </tbody>
      </table>
    </GoabTable>
  </div>

  <GoabPushDrawer
    heading="Filters"
    width="260px"
    open={open}
    onClose={() => setOpen(false)}
  >
    <GoabFormItem label="Act">
      <GoabCheckboxList name="act" onChange={() => {}}>
        <GoabCheckbox name="traffic" text="Traffic safety act" size="compact" />
        <GoabCheckbox
          name="gaming"
          text="Gaming, liquor, and cannabis act"
          size="compact"
        />
        <GoabCheckbox
          name="trespass"
          text="Trespass to premises act"
          size="compact"
        />
      </GoabCheckboxList>
    </GoabFormItem>
    <GoabFormItem label="Status" mt="l">
      <GoabDropdown name="status" onChange={() => {}} value="" size="compact">
        <GoabDropdownItem value="" label="All statuses" />
        <GoabDropdownItem value="new" label="New" />
        <GoabDropdownItem value="in-review" label="In review" />
        <GoabDropdownItem value="completed" label="Completed" />
      </GoabDropdown>
    </GoabFormItem>
  </GoabPushDrawer>
</div>
open = false;

openFilters(): void {
  this.open = true;
}

closeFilters(): void {
  this.open = false;
}

onCheckboxChange(event: GoabCheckboxOnChangeDetail): void {
  console.log(event);
}

onDropdownChange(event: GoabDropdownOnChangeDetail): void {
  console.log(event);
}
<div style="display: flex; min-height: 480px">
  <div style="flex: 1; min-width: 0">
    <div style="display: flex; align-items: center; gap: 1rem; margin-bottom: 1rem">
      <h3 style="flex: 1; margin: 0">All cases</h3>
      @if (!open) {
      <goab-button
        type="secondary"
        size="compact"
        leadingIcon="filter"
        (onClick)="openFilters()"
        >Filters</goab-button
      >
      }
    </div>

    <goab-table width="100%">
      <table width="100%">
        <thead>
          <tr>
            <th>Status</th>
            <th>Name</th>
            <th>File number</th>
            <th>Act</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td><goab-badge type="success" content="Completed"></goab-badge></td>
            <td>Gilbert Barton</td>
            <td>24567-9876</td>
            <td>Traffic safety act</td>
          </tr>
          <tr>
            <td><goab-badge type="information" content="New"></goab-badge></td>
            <td>Brynn Hurley</td>
            <td>98765-3456</td>
            <td>Trespass to premises act</td>
          </tr>
          <tr>
            <td><goab-badge type="default" content="In review"></goab-badge></td>
            <td>Marco Silva</td>
            <td>34521-7890</td>
            <td>Gaming, liquor, and cannabis act</td>
          </tr>
          <tr>
            <td><goab-badge type="success" content="Completed"></goab-badge></td>
            <td>Dana Chen</td>
            <td>55123-4567</td>
            <td>Traffic safety act</td>
          </tr>
          <tr>
            <td><goab-badge type="information" content="New"></goab-badge></td>
            <td>Amira Hassan</td>
            <td>67890-1234</td>
            <td>Trespass to premises act</td>
          </tr>
        </tbody>
      </table>
    </goab-table>
  </div>

  <goab-push-drawer
    heading="Filters"
    width="260px"
    [open]="open"
    (onClose)="closeFilters()"
  >
    <goab-form-item label="Act">
      <goab-checkbox-list name="act" (onChange)="onCheckboxChange($event)">
        <goab-checkbox
          name="traffic"
          text="Traffic safety act"
          size="compact"
        ></goab-checkbox>
        <goab-checkbox
          name="gaming"
          text="Gaming, liquor, and cannabis act"
          size="compact"
        ></goab-checkbox>
        <goab-checkbox
          name="trespass"
          text="Trespass to premises act"
          size="compact"
        ></goab-checkbox>
      </goab-checkbox-list>
    </goab-form-item>
    <goab-form-item label="Status" mt="l">
      <goab-dropdown
        name="status"
        (onChange)="onDropdownChange($event)"
        value=""
        size="compact"
      >
        <goab-dropdown-item value="" label="All statuses"></goab-dropdown-item>
        <goab-dropdown-item value="new" label="New"></goab-dropdown-item>
        <goab-dropdown-item value="in-review" label="In review"></goab-dropdown-item>
        <goab-dropdown-item value="completed" label="Completed"></goab-dropdown-item>
      </goab-dropdown>
    </goab-form-item>
  </goab-push-drawer>
</div>
const filtersDrawer = document.getElementById("filters-drawer");
const openFiltersBtn = document.getElementById("open-filters-btn");

openFiltersBtn.addEventListener("_click", () => {
  filtersDrawer.setAttribute("open", "true");
  openFiltersBtn.style.display = "none";
});

filtersDrawer.addEventListener("_close", () => {
  filtersDrawer.removeAttribute("open");
  openFiltersBtn.style.display = "";
});
<div style="display: flex; min-height: 480px">
  <div style="flex: 1; min-width: 0">
    <div style="display: flex; align-items: center; gap: 1rem; margin-bottom: 1rem">
      <h3 style="flex: 1; margin: 0">All cases</h3>
      <goa-button
        version="2"
        id="open-filters-btn"
        type="secondary"
        size="compact"
        leadingicon="filter"
        >Filters</goa-button
      >
    </div>

    <goa-table version="2" width="100%">
      <table width="100%">
        <thead>
          <tr>
            <th>Status</th>
            <th>Name</th>
            <th>File number</th>
            <th>Act</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>
              <goa-badge version="2" type="success" content="Completed"></goa-badge>
            </td>
            <td>Gilbert Barton</td>
            <td>24567-9876</td>
            <td>Traffic safety act</td>
          </tr>
          <tr>
            <td><goa-badge version="2" type="information" content="New"></goa-badge></td>
            <td>Brynn Hurley</td>
            <td>98765-3456</td>
            <td>Trespass to premises act</td>
          </tr>
          <tr>
            <td>
              <goa-badge version="2" type="default" content="In review"></goa-badge>
            </td>
            <td>Marco Silva</td>
            <td>34521-7890</td>
            <td>Gaming, liquor, and cannabis act</td>
          </tr>
          <tr>
            <td>
              <goa-badge version="2" type="success" content="Completed"></goa-badge>
            </td>
            <td>Dana Chen</td>
            <td>55123-4567</td>
            <td>Traffic safety act</td>
          </tr>
          <tr>
            <td><goa-badge version="2" type="information" content="New"></goa-badge></td>
            <td>Amira Hassan</td>
            <td>67890-1234</td>
            <td>Trespass to premises act</td>
          </tr>
        </tbody>
      </table>
    </goa-table>
  </div>

  <goa-push-drawer version="2" id="filters-drawer" heading="Filters" width="260px">
    <goa-form-item version="2" label="Act">
      <goa-checkbox-list name="act">
        <goa-checkbox
          version="2"
          name="traffic"
          text="Traffic safety act"
          size="compact"
        ></goa-checkbox>
        <goa-checkbox
          version="2"
          name="gaming"
          text="Gaming, liquor, and cannabis act"
          size="compact"
        ></goa-checkbox>
        <goa-checkbox
          version="2"
          name="trespass"
          text="Trespass to premises act"
          size="compact"
        ></goa-checkbox>
      </goa-checkbox-list>
    </goa-form-item>
    <goa-form-item version="2" label="Status" mt="l">
      <goa-dropdown version="2" name="status" size="compact">
        <goa-dropdown-item value="" label="All statuses"></goa-dropdown-item>
        <goa-dropdown-item value="new" label="New"></goa-dropdown-item>
        <goa-dropdown-item value="in-review" label="In review"></goa-dropdown-item>
        <goa-dropdown-item value="completed" label="Completed"></goa-dropdown-item>
      </goa-dropdown>
    </goa-form-item>
  </goa-push-drawer>
</div>

Disabled button with a required field

const [inputValue, setInputValue] = useState("");

const handleInputChange = (detail: GoabInputOnChangeDetail) => {
  setInputValue(detail.value);
};

const handleConfirm = () => {
  // Handle form submission
  console.log("Form submitted with:", inputValue);
};

const handleCancel = () => {
  // Handle cancellation
  setInputValue("");
};
<form>
  <GoabFormItem label="Name" requirement="required">
    <GoabInput
      name="input"
      type="text"
      onChange={handleInputChange}
      value={inputValue}
      width="100%"
    />
  </GoabFormItem>

  <GoabButtonGroup alignment="start" mt="xl">
    <GoabButton disabled={inputValue.trim() === ""} onClick={handleConfirm}>
      Confirm
    </GoabButton>
    <GoabButton type="secondary" onClick={handleCancel}>
      Cancel
    </GoabButton>
  </GoabButtonGroup>
</form>
inputValue = "";

onInputChange(detail: GoabInputOnChangeDetail): void {
  this.inputValue = detail.value;
}

onConfirm(): void {
  // Handle form submission
  console.log("Form submitted with:", this.inputValue);
}

onCancel(): void {
  // Handle cancellation
  this.inputValue = "";
}

get isDisabled(): boolean {
  return this.inputValue.trim() === "";
}
<form>
  <goab-form-item label="Name" requirement="required">
    <goab-input
      name="input"
      type="text"
      (onChange)="onInputChange($event)"
      [value]="inputValue"
      width="100%"
    >
    </goab-input>
  </goab-form-item>

  <goab-button-group alignment="start" mt="xl">
    <goab-button [disabled]="isDisabled" (onClick)="onConfirm()"> Confirm </goab-button>
    <goab-button type="secondary" (onClick)="onCancel()"> Cancel </goab-button>
  </goab-button-group>
</form>
const nameInput = document.getElementById("name-input");
const confirmBtn = document.getElementById("confirm-btn");
const cancelBtn = document.getElementById("cancel-btn");

nameInput.addEventListener("_change", (e) => {
  const value = e.detail.value.trim();
  if (value === "") {
    confirmBtn.setAttribute("disabled", "true");
  } else {
    confirmBtn.removeAttribute("disabled");
  }
});

confirmBtn.addEventListener("_click", () => {
  console.log("Form submitted with:", nameInput.value);
});

cancelBtn.addEventListener("_click", () => {
  nameInput.value = "";
  confirmBtn.setAttribute("disabled", "true");
});
<form id="required-field-form">
  <goa-form-item version="2" label="Name" requirement="required">
    <goa-input
      version="2"
      id="name-input"
      name="input"
      type="text"
      width="100%"
    ></goa-input>
  </goa-form-item>

  <goa-button-group alignment="start" mt="xl">
    <goa-button version="2" id="confirm-btn" disabled="true">Confirm</goa-button>
    <goa-button version="2" id="cancel-btn" type="secondary">Cancel</goa-button>
  </goa-button-group>
</form>

Filter data in a table

const [typedChips, setTypedChips] = useState<string[]>([]);
const [inputValue, setInputValue] = useState("");
const [inputError, setInputError] = useState("");
const errorEmpty = "Empty filter";
const errorDuplicate = "Enter a unique filter";

const data = useMemo(
  () => [
    {
      status: { type: "information" as GoabBadgeType, text: "In progress" },
      name: "Ivan Schmidt",
      id: "7838576954",
    },
    {
      status: { type: "success" as GoabBadgeType, text: "Completed" },
      name: "Luz Lakin",
      id: "8576953364",
    },
    {
      status: { type: "information" as GoabBadgeType, text: "In progress" },
      name: "Keith McGlynn",
      id: "9846041345",
    },
    {
      status: { type: "success" as GoabBadgeType, text: "Completed" },
      name: "Melody Frami",
      id: "7385256175",
    },
    {
      status: { type: "important" as GoabBadgeType, text: "Updated" },
      name: "Frederick Skiles",
      id: "5807570418",
    },
    {
      status: { type: "success" as GoabBadgeType, text: "Completed" },
      name: "Dana Pfannerstill",
      id: "5736306857",
    },
  ],
  [],
);

const [dataFiltered, setDataFiltered] = useState(data);

const handleInputChange = (detail: GoabInputOnChangeDetail) => {
  const newValue = detail.value.trim();
  setInputValue(newValue);
};

const handleInputKeyPress = (detail: GoabInputOnKeyPressDetail) => {
  if (detail.key === "Enter") {
    applyFilter();
  }
};

const applyFilter = () => {
  if (inputValue === "") {
    setInputError(errorEmpty);
    return;
  }
  if (typedChips.length > 0 && typedChips.includes(inputValue)) {
    setInputError(errorDuplicate);
    return;
  }
  setTypedChips([...typedChips, inputValue]);
  setTimeout(() => {
    setInputValue("");
  }, 0);
  setInputError("");
};

const removeTypedChip = (chip: string) => {
  setTypedChips(typedChips.filter((c) => c !== chip));
  setInputError("");
};

const checkNested = useCallback((obj: object, chip: string): boolean => {
  return Object.values(obj).some((value) =>
    typeof value === "object" && value !== null
      ? checkNested(value, chip)
      : typeof value === "string" && value.toLowerCase().includes(chip.toLowerCase()),
  );
}, []);

const getFilteredData = useCallback(
  (typedChips: string[]) => {
    if (typedChips.length === 0) {
      return data;
    }
    return data.filter((item: object) =>
      typedChips.every((chip) => checkNested(item, chip)),
    );
  },
  [checkNested, data],
);

useEffect(() => {
  setDataFiltered(getFilteredData(typedChips));
}, [getFilteredData, typedChips]);
<GoabFormItem id="filterChipInput" error={inputError} mb="m">
  <GoabBlock gap="xs" direction="row" alignment="start" width="100%">
    <div style={{ flex: 1 }}>
      <GoabInput
        name="filterChipInput"
        aria-labelledby="filterChipInput"
        value={inputValue}
        leadingIcon="search"
        width="100%"
        onChange={handleInputChange}
        onKeyPress={handleInputKeyPress}
      />
    </div>
    <GoabButton type="secondary" onClick={applyFilter} leadingIcon="filter">
      Filter
    </GoabButton>
  </GoabBlock>
</GoabFormItem>

{typedChips.length > 0 && (
  <div>
    <GoabText tag="span" color="secondary" mb="xs" mr="xs">
      Filter:
    </GoabText>
    {typedChips.map((typedChip, index) => (
      <GoabFilterChip
        key={index}
        content={typedChip}
        mb="xs"
        mr="xs"
        onClick={() => removeTypedChip(typedChip)}
      />
    ))}
    <GoabButton
      type="tertiary"
      size="compact"
      mb="xs"
      onClick={() => setTypedChips([])}
    >
      Clear all
    </GoabButton>
  </div>
)}

<GoabTable width="100%">
  <thead>
    <tr>
      <th>Status</th>
      <th>Name</th>
      <th className="goa-table-number-header">ID Number</th>
    </tr>
  </thead>
  <tbody>
    {dataFiltered.map((item) => (
      <tr key={item.id}>
        <td>
          <GoabBadge
            type={item.status.type}
            content={item.status.text}
            icon={false}
          />
        </td>
        <td>{item.name}</td>
        <td className="goa-table-number-column">{item.id}</td>
      </tr>
    ))}
  </tbody>
</GoabTable>

{dataFiltered.length === 0 && data.length > 0 && (
  <GoabBlock mt="l" mb="l">
    No results found
  </GoabBlock>
)}
typedChips: string[] = [];
inputValue = "";
inputError = "";
readonly errorEmpty = "Empty filter";
readonly errorDuplicate = "Enter a unique filter";

readonly data: DataItem[] = [
  {
    status: { type: "information", text: "In progress" },
    name: "Ivan Schmidt",
    id: "7838576954",
  },
  {
    status: { type: "success", text: "Completed" },
    name: "Luz Lakin",
    id: "8576953364",
  },
  {
    status: { type: "information", text: "In progress" },
    name: "Keith McGlynn",
    id: "9846041345",
  },
  {
    status: { type: "success", text: "Completed" },
    name: "Melody Frami",
    id: "7385256175",
  },
  {
    status: { type: "important", text: "Updated" },
    name: "Frederick Skiles",
    id: "5807570418",
  },
  {
    status: { type: "success", text: "Completed" },
    name: "Dana Pfannerstill",
    id: "5736306857",
  },
];

dataFiltered = this.getFilteredData(this.typedChips);

handleInputChange(detail: GoabInputOnChangeDetail): void {
  const newValue = detail.value.trim();
  this.inputValue = newValue;
}

handleInputKeyPress(detail: GoabInputOnKeyPressDetail): void {
  if (detail.key === "Enter") {
    this.applyFilter();
  }
}

applyFilter(): void {
  if (this.inputValue === "") {
    this.inputError = this.errorEmpty;
    return;
  }
  if (this.typedChips.includes(this.inputValue)) {
    this.inputError = this.errorDuplicate;
    return;
  }
  this.typedChips = [...this.typedChips, this.inputValue];
  this.inputValue = "";
  this.inputError = "";
  this.dataFiltered = this.getFilteredData(this.typedChips);
}

removeTypedChip(chip: string): void {
  this.typedChips = this.typedChips.filter((c) => c !== chip);
  this.dataFiltered = this.getFilteredData(this.typedChips);
  this.inputError = "";
}

removeAllTypedChips(): void {
  this.typedChips = [];
  this.dataFiltered = this.getFilteredData(this.typedChips);
  this.inputError = "";
}

getFilteredData(typedChips: string[]): DataItem[] {
  if (typedChips.length === 0) {
    return this.data;
  }
  return this.data.filter((item) =>
    typedChips.every((chip) => this.checkNested(item, chip)),
  );
}

checkNested(obj: object, chip: string): boolean {
  return Object.values(obj).some((value) =>
    typeof value === "object" && value !== null
      ? this.checkNested(value, chip)
      : typeof value === "string" && value.toLowerCase().includes(chip.toLowerCase()),
  );
}
<goab-form-item id="filterChipInput" [error]="inputError" mb="m">
  <goab-block gap="xs" direction="row" alignment="start" width="100%">
    <div style="flex: 1">
      <goab-input
        name="filterChipInput"
        aria-labelledby="filterChipInput"
        [value]="inputValue"
        leadingIcon="search"
        width="100%"
        (onChange)="handleInputChange($event)"
        (onKeyPress)="handleInputKeyPress($event)"
      >
      </goab-input>
    </div>
    <goab-button type="secondary" (onClick)="applyFilter()" leadingIcon="filter">
      Filter
    </goab-button>
  </goab-block>
</goab-form-item>

@if (typedChips.length > 0) {
<ng-container>
  <goab-text tag="span" color="secondary" mb="xs" mr="xs"> Filter: </goab-text>
  @for (typedChip of typedChips; track typedChip; let index = $index) {
  <goab-filter-chip
    [content]="typedChip"
    mb="xs"
    mr="xs"
    (onClick)="removeTypedChip(typedChip)"
  >
  </goab-filter-chip>
  }
  <goab-button type="tertiary" size="compact" mb="xs" (onClick)="removeAllTypedChips()">
    Clear all
  </goab-button>
</ng-container>
}

<goab-table width="100%">
  <thead>
    <tr>
      <th>Status</th>
      <th>Name</th>
      <th class="goa-table-number-header">ID Number</th>
    </tr>
  </thead>
  <tbody>
    @for (item of dataFiltered; track $index) {
    <tr>
      <td>
        <goab-badge
          [type]="item.status.type"
          [content]="item.status.text"
          [icon]="false"
        ></goab-badge>
      </td>
      <td>{{ item.name }}</td>
      <td class="goa-table-number-column">{{ item.id }}</td>
    </tr>
    }
  </tbody>
</goab-table>

@if (dataFiltered.length === 0 && data.length > 0) {
<goab-block mt="l" mb="l"> No results found </goab-block>
}
const filterInput = document.getElementById("filter-input");
const filterBtn = document.getElementById("filter-btn");
const filterFormItem = document.getElementById("filter-form-item");
const chipsContainer = document.getElementById("chips-container");
const chipsList = document.getElementById("chips-list");
const clearAllBtn = document.getElementById("clear-all-btn");
const tableRows = document.querySelectorAll("tbody tr");

let typedChips = [];

function filterTable() {
  tableRows.forEach((row) => {
    const badge = row.querySelector("goa-badge");
    const badgeText = badge ? badge.getAttribute("content") || "" : "";
    const text = (row.textContent + " " + badgeText).toLowerCase();
    const matches =
      typedChips.length === 0 ||
      typedChips.every((chip) => text.includes(chip.toLowerCase()));
    row.style.display = matches ? "" : "none";
  });
}

function renderChips() {
  chipsList.innerHTML = "";
  typedChips.forEach((chip) => {
    const filterChip = document.createElement("goa-filter-chip");
    filterChip.setAttribute("version", "2");
    filterChip.setAttribute("content", chip);
    filterChip.setAttribute("mb", "xs");
    filterChip.setAttribute("mr", "xs");
    filterChip.addEventListener("_click", () => removeChip(chip));
    chipsList.appendChild(filterChip);
  });
  chipsContainer.style.display = typedChips.length > 0 ? "block" : "none";
  filterTable();
}

function applyFilter() {
  const value = filterInput.value.trim();
  if (value === "") {
    filterFormItem.setAttribute("error", "Empty filter");
    return;
  }
  if (typedChips.includes(value)) {
    filterFormItem.setAttribute("error", "Enter a unique filter");
    return;
  }
  typedChips.push(value);
  filterInput.value = "";
  filterFormItem.removeAttribute("error");
  renderChips();
}

function removeChip(chip) {
  typedChips = typedChips.filter((c) => c !== chip);
  renderChips();
}

filterBtn.addEventListener("_click", applyFilter);
clearAllBtn.addEventListener("_click", () => {
  typedChips = [];
  renderChips();
});
<goa-form-item version="2" id="filter-form-item" mb="m">
  <goa-block gap="xs" direction="row" alignment="center" width="100%">
    <div style="flex: 1">
      <goa-input
        version="2"
        id="filter-input"
        name="filterChipInput"
        leadingicon="search"
        width="100%"
      >
      </goa-input>
    </div>
    <goa-button version="2" id="filter-btn" type="secondary" leadingicon="filter">
      Filter
    </goa-button>
  </goa-block>
</goa-form-item>

<div id="chips-container" style="display: none">
  <goa-text as="span" color="secondary" mb="xs" mr="xs">Filter:</goa-text>
  <span id="chips-list"></span>
  <goa-button version="2" id="clear-all-btn" type="tertiary" size="compact" mb="xs">
    Clear all
  </goa-button>
</div>

<goa-table version="2" width="100%" mt="s">
  <table style="width: 100%">
    <thead>
      <tr>
        <th>Status</th>
        <th>Name</th>
        <th class="goa-table-number-header">ID Number</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>
          <goa-badge
            version="2"
            type="information"
            content="In progress"
            icon="false"
          ></goa-badge>
        </td>
        <td>Ivan Schmidt</td>
        <td class="goa-table-number-column">7838576954</td>
      </tr>
      <tr>
        <td>
          <goa-badge
            version="2"
            type="success"
            content="Completed"
            icon="false"
          ></goa-badge>
        </td>
        <td>Luz Lakin</td>
        <td class="goa-table-number-column">8576953364</td>
      </tr>
      <tr>
        <td>
          <goa-badge
            version="2"
            type="information"
            content="In progress"
            icon="false"
          ></goa-badge>
        </td>
        <td>Keith McGlynn</td>
        <td class="goa-table-number-column">9846041345</td>
      </tr>
      <tr>
        <td>
          <goa-badge
            version="2"
            type="success"
            content="Completed"
            icon="false"
          ></goa-badge>
        </td>
        <td>Melody Frami</td>
        <td class="goa-table-number-column">7385256175</td>
      </tr>
      <tr>
        <td>
          <goa-badge
            version="2"
            type="important"
            content="Updated"
            icon="false"
          ></goa-badge>
        </td>
        <td>Frederick Skiles</td>
        <td class="goa-table-number-column">5807570418</td>
      </tr>
      <tr>
        <td>
          <goa-badge
            version="2"
            type="success"
            content="Completed"
            icon="false"
          ></goa-badge>
        </td>
        <td>Dana Pfannerstill</td>
        <td class="goa-table-number-column">5736306857</td>
      </tr>
    </tbody>
  </table>
</goa-table>

Give more information before asking a question (a)

const [selectedValue, setSelectedValue] = useState<string>("");

const handleChange = (event: GoabRadioGroupOnChangeDetail) => {
  setSelectedValue(event.value as string);
};

const handleSubmit = () => {
  console.log("Selected:", selectedValue);
};
      <GoabLink leadingIcon="arrow-back" size="small" mb="none">
        Back
      </GoabLink>

      <GoabText tag="h2" mt="xl" mb="m">
        Current school status
      </GoabText>
      <GoabText mt="none" mb="s">
        School can encompass foundational programs that help individuals gain basic skills
        for further learning and living, such as literacy and numeracy courses. It also
        includes skills and employment training programs, designed to equip you with
        specific skills for the job market.
      </GoabText>
      <GoabText mt="none" mb="s">
        Post-secondary education, such as Bachelor's, Master's, or Doctoral degrees, and
        continuing education courses for professional or personal development, are also
        categorized under 'school'.
      </GoabText>
      <GoabText mt="none" mb="xl">
        Contact your provider if you're concerned about your school status.
      </GoabText>

      <GoabFormItem label="Are you currently in school?">
        <GoabRadioGroup
          name="school"
          ariaLabel="are you currently in school?"
          onChange={handleChange}
        >
          <GoabRadioItem value="yes" label="Yes" />
          <GoabRadioItem value="no" label="No" />
        </GoabRadioGroup>
      </GoabFormItem>

      <GoabButton type="submit" mt="2xl" onClick={handleSubmit}>
        Save and continue
      </GoabButton>
  );
}
selectedValue = "";

onChange(event: GoabRadioGroupOnChangeDetail): void {
  this.selectedValue = event.value as string;
}

onSubmit(): void {
  console.log("Selected:", this.selectedValue);
}
<goab-link leadingIcon="arrow-back" size="small" mb="none"> Back </goab-link>

<goab-text tag="h2" mt="xl" mb="m">Current school status</goab-text>
<goab-text mt="none" mb="s">
  School can encompass foundational programs that help individuals gain basic skills for
  further learning and living, such as literacy and numeracy courses. It also includes
  skills and employment training programs, designed to equip you with specific skills for
  the job market.
</goab-text>
<goab-text mt="none" mb="s">
  Post-secondary education, such as Bachelor's, Master's, or Doctoral degrees, and
  continuing education courses for professional or personal development, are also
  categorized under 'school'.
</goab-text>
<goab-text mt="none" mb="xl">
  Contact your provider if you're concerned about your school status.
</goab-text>

<goab-form-item label="Are you currently in school?">
  <goab-radio-group
    name="school"
    ariaLabel="are you currently in school?"
    (onChange)="onChange($event)"
  >
    <goab-radio-item value="yes" label="Yes"></goab-radio-item>
    <goab-radio-item value="no" label="No"></goab-radio-item>
  </goab-radio-group>
</goab-form-item>

<goab-button type="submit" mt="2xl" (onClick)="onSubmit()">
  Save and continue
</goab-button>
const radioGroup = document.getElementById("school-radio");
const submitBtn = document.getElementById("submit-btn");
let selectedValue = "";

radioGroup.addEventListener("_change", (e) => {
  selectedValue = e.detail.value;
});

submitBtn.addEventListener("_click", () => {
  console.log("Selected:", selectedValue);
});
<goa-link leadingicon="arrow-back" size="small" mb="none"> Back </goa-link>

<goa-text as="h2" mt="xl" mb="m">Current school status</goa-text>
<goa-text mt="none" mb="s">
  School can encompass foundational programs that help individuals gain basic skills for
  further learning and living, such as literacy and numeracy courses. It also includes
  skills and employment training programs, designed to equip you with specific skills for
  the job market.
</goa-text>
<goa-text mt="none" mb="s">
  Post-secondary education, such as Bachelor's, Master's, or Doctoral degrees, and
  continuing education courses for professional or personal development, are also
  categorized under 'school'.
</goa-text>
<goa-text mt="none" mb="xl">
  Contact your provider if you're concerned about your school status.
</goa-text>

<goa-form-item version="2" label="Are you currently in school?">
  <goa-radio-group
    version="2"
    id="school-radio"
    name="school"
    arialabel="are you currently in school?"
  >
    <goa-radio-item value="yes" label="Yes"></goa-radio-item>
    <goa-radio-item value="no" label="No"></goa-radio-item>
  </goa-radio-group>
</goa-form-item>

<goa-button version="2" id="submit-btn" type="submit" mt="2xl">
  Save and continue
</goa-button>

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>

Give more information before asking a question (b)

const [textValue, setTextValue] = useState("");

const handleChange = (event: GoabTextAreaOnChangeDetail) => {
  setTextValue(event.value);
};

const handleContinue = () => {
  console.log("Submitted:", textValue);
};
<GoabLink leadingIcon="arrow-back" size="small" mb="none">
  Back
</GoabLink>

<GoabText tag="h2" mt="xl" mb="m">
  Submit a question about your benefits
</GoabText>
<GoabText mt="none" mb="xl">
  If you need clarification about your benefit eligibility, payment schedule, or
  application status, submit your question here.
</GoabText>

<form>
  <GoabFormItem
    label="Provide details about your situation"
    helpText="Include specific details to help us answer your question quickly."
  >
    <GoabTextArea
      name="program"
      onChange={handleChange}
      value={textValue}
      maxCount={400}
      countBy="character"
    />
  </GoabFormItem>
</form>

<GoabDetails mt="m" heading="What kind of information is useful?">
  <p>
    Include your benefit program name, mention any recent correspondence you
    received and/or provide any relevant case or reference numbers.
  </p>
</GoabDetails>

<GoabButtonGroup alignment="start" mt="2xl">
  <GoabButton type="primary" onClick={handleContinue}>
    Continue
  </GoabButton>
</GoabButtonGroup>
form: FormGroup;

constructor(private fb: FormBuilder) {
  this.form = this.fb.group({
    program: [""],
  });
}

onContinue(): void {
  console.log("Submitted:", this.form.get("program")?.value);
}
<goab-link leadingIcon="arrow-back" size="small" mb="none"> Back </goab-link>

<goab-text tag="h2" mt="xl" mb="m">Submit a question about your benefits</goab-text>
<goab-text mt="none" mb="xl">
  If you need clarification about your benefit eligibility, payment schedule, or
  application status, submit your question here.
</goab-text>

<form [formGroup]="form">
  <goab-form-item
    label="Provide details about your situation"
    helpText="Include specific details to help us answer your question quickly."
  >
    <goab-textarea
      formControlName="program"
      name="program"
      [maxCount]="400"
      countBy="character"
    >
    </goab-textarea>
  </goab-form-item>
</form>

<goab-details mt="m" heading="What kind of information is useful?">
  <p>
    Include your benefit program name, mention any recent correspondence you received
    and/or provide any relevant case or reference numbers.
  </p>
</goab-details>

<goab-button-group alignment="start" mt="2xl">
  <goab-button type="primary" (onClick)="onContinue()"> Continue </goab-button>
</goab-button-group>
const textarea = document.getElementById("program-textarea");
const continueBtn = document.getElementById("continue-btn");

continueBtn.addEventListener("_click", () => {
  console.log("Submitted:", textarea.value);
});
<goa-link leadingicon="arrow-back" size="small" mb="none"> Back </goa-link>

<goa-text as="h2" mt="xl" mb="m">Submit a question about your benefits</goa-text>
<goa-text mt="none" mb="xl">
  If you need clarification about your benefit eligibility, payment schedule, or
  application status, submit your question here.
</goa-text>

<form>
  <goa-form-item
    version="2"
    label="Provide details about your situation"
    helptext="Include specific details to help us answer your question quickly."
  >
    <goa-textarea
      version="2"
      id="program-textarea"
      name="program"
      maxcount="400"
      countby="character"
    >
    </goa-textarea>
  </goa-form-item>
</form>

<goa-details mt="m" heading="What kind of information is useful?">
  <p>
    Include your benefit program name, mention any recent correspondence you received
    and/or provide any relevant case or reference numbers.
  </p>
</goa-details>

<goa-button-group alignment="start" mt="2xl">
  <goa-button version="2" id="continue-btn" type="primary"> Continue </goa-button>
</goa-button-group>
const [addressLine1, setAddressLine1] = useState("");
const [addressLine2, setAddressLine2] = useState("");
const [townCity, setTownCity] = useState("");
const [province, setProvince] = useState("");
const [postalCode, setPostalCode] = useState("");
<GoabLink leadingIcon="arrow-back" size="small" mb="none">
  Back
</GoabLink>

<GoabText tag="h2" mt="xl" mb="m">
  Your address
</GoabText>
<GoabText mt="none" mb="xl">
  This is the home address of the person applying
</GoabText>

<GoabFormItem label="Address line 1">
  <GoabInput
    onChange={(event) => setAddressLine1(event.value)}
    value={addressLine1}
    name="address-line-1"
    ariaLabel="Address line 1"
    width="100%"
  />
</GoabFormItem>

<GoabFormItem label="Address line 2" mt="l">
  <GoabInput
    onChange={(event) => setAddressLine2(event.value)}
    value={addressLine2}
    name="address-line-2"
    ariaLabel="Address line 2"
    width="100%"
  />
</GoabFormItem>

<GoabFormItem label="Town or city" mt="l">
  <GoabInput
    onChange={(event) => setTownCity(event.value)}
    value={townCity}
    name="town-city"
    ariaLabel="Town or city name"
    width="460px"
  />
</GoabFormItem>

<GoabFormItem label="Province or territory" mt="l" id="provinceLabel">
  <GoabDropdown
    onChange={(event) => setProvince(event.value ?? "")}
    value={province}
    name="province-territory"
    ariaLabelledBy="provinceLabel"
  >
    <GoabDropdownItem value="AB" label="Alberta" />
    <GoabDropdownItem value="BC" label="British Columbia" />
    <GoabDropdownItem value="MB" label="Manitoba" />
    <GoabDropdownItem value="NB" label="New Brunswick" />
    <GoabDropdownItem value="NL" label="Newfoundland and Labrador" />
    <GoabDropdownItem value="NS" label="Nova Scotia" />
    <GoabDropdownItem value="ON" label="Ontario" />
    <GoabDropdownItem value="PE" label="Prince Edward Island" />
    <GoabDropdownItem value="QC" label="Quebec" />
    <GoabDropdownItem value="SK" label="Saskatchewan" />
    <GoabDropdownItem value="NT" label="Northwest Territories" />
    <GoabDropdownItem value="NU" label="Nunavut" />
    <GoabDropdownItem value="YT" label="Yukon" />
  </GoabDropdown>
</GoabFormItem>

<GoabFormItem label="Postal code" mt="l">
  <GoabInput
    onChange={(event) => setPostalCode(event.value)}
    value={postalCode}
    name="postal-code"
    width="105px"
  />
</GoabFormItem>

<GoabButton type="submit" mt="2xl">
  Save and continue
</GoabButton>
addressLine1 = "";
addressLine2 = "";
townCity = "";
province = "";
postalCode = "";

onAddressLine1Change(value: string): void {
  this.addressLine1 = value;
}

onAddressLine2Change(value: string): void {
  this.addressLine2 = value;
}

onTownCityChange(value: string): void {
  this.townCity = value;
}

onProvinceChange(value: string): void {
  this.province = value;
}

onPostalCodeChange(value: string): void {
  this.postalCode = value;
}

onSubmit(): void {
  console.log("Form submitted");
}
<goab-link leadingIcon="arrow-back" size="small" mb="none"> Back </goab-link>

<goab-text tag="h2" mt="xl" mb="m">Your address</goab-text>
<goab-text mt="none" mb="xl">This is the home address of the person applying</goab-text>

<goab-form-item label="Address line 1">
  <goab-input
    (onChange)="onAddressLine1Change($event)"
    [value]="addressLine1"
    name="address-line-1"
    ariaLabel="Address line 1"
    width="100%"
  >
  </goab-input>
</goab-form-item>

<goab-form-item label="Address line 2" mt="l">
  <goab-input
    (onChange)="onAddressLine2Change($event)"
    [value]="addressLine2"
    name="address-line-2"
    ariaLabel="Address line 2"
    width="100%"
  >
  </goab-input>
</goab-form-item>

<goab-form-item label="Town or city" mt="l">
  <goab-input
    (onChange)="onTownCityChange($event)"
    [value]="townCity"
    name="town-city"
    ariaLabel="Town or city name"
    width="460px"
  >
  </goab-input>
</goab-form-item>

<goab-form-item label="Province or territory" mt="l" id="provinceLabel">
  <goab-dropdown
    (onChange)="onProvinceChange($event)"
    [value]="province"
    name="province-territory"
    ariaLabelledBy="provinceLabel"
  >
    <goab-dropdown-item value="AB" label="Alberta"></goab-dropdown-item>
    <goab-dropdown-item value="BC" label="British Columbia"></goab-dropdown-item>
    <goab-dropdown-item value="MB" label="Manitoba"></goab-dropdown-item>
    <goab-dropdown-item value="NB" label="New Brunswick"></goab-dropdown-item>
    <goab-dropdown-item value="NL" label="Newfoundland and Labrador"></goab-dropdown-item>
    <goab-dropdown-item value="NS" label="Nova Scotia"></goab-dropdown-item>
    <goab-dropdown-item value="ON" label="Ontario"></goab-dropdown-item>
    <goab-dropdown-item value="PE" label="Prince Edward Island"></goab-dropdown-item>
    <goab-dropdown-item value="QC" label="Quebec"></goab-dropdown-item>
    <goab-dropdown-item value="SK" label="Saskatchewan"></goab-dropdown-item>
    <goab-dropdown-item value="NT" label="Northwest Territories"></goab-dropdown-item>
    <goab-dropdown-item value="NU" label="Nunavut"></goab-dropdown-item>
    <goab-dropdown-item value="YT" label="Yukon"></goab-dropdown-item>
  </goab-dropdown>
</goab-form-item>

<goab-form-item label="Postal code" mt="l">
  <goab-input
    (onChange)="onPostalCodeChange($event)"
    [value]="postalCode"
    name="postal-code"
    width="105px"
  >
  </goab-input>
</goab-form-item>

<goab-button type="submit" mt="2xl" (onClick)="onSubmit()">
  Save and continue
</goab-button>
document.getElementById("address-line-1").addEventListener("_change", (e) => {
  console.log("Address line 1:", e.detail.value);
});

document.getElementById("province-territory").addEventListener("_change", (e) => {
  console.log("Province:", e.detail.value);
});

document.getElementById("submit-btn").addEventListener("_click", () => {
  console.log("Form submitted");
});
<goa-link leadingicon="arrow-back" size="small" mb="none"> Back </goa-link>

<goa-text as="h2" mt="xl" mb="m">Your address</goa-text>
<goa-text mt="none" mb="xl">This is the home address of the person applying</goa-text>

<goa-form-item version="2" label="Address line 1">
  <goa-input
    version="2"
    id="address-line-1"
    name="address-line-1"
    aria-label="Address line 1"
    width="100%"
  >
  </goa-input>
</goa-form-item>

<goa-form-item version="2" label="Address line 2" mt="l">
  <goa-input
    version="2"
    id="address-line-2"
    name="address-line-2"
    aria-label="Address line 2"
    width="100%"
  >
  </goa-input>
</goa-form-item>

<goa-form-item version="2" label="Town or city" mt="l">
  <goa-input
    version="2"
    id="town-city"
    name="town-city"
    aria-label="Town or city name"
    width="460px"
  >
  </goa-input>
</goa-form-item>

<goa-form-item version="2" label="Province or territory" mt="l" id="provinceLabel">
  <goa-dropdown
    version="2"
    id="province-territory"
    name="province-territory"
    aria-labelledby="provinceLabel"
  >
    <goa-dropdown-item value="AB" label="Alberta"></goa-dropdown-item>
    <goa-dropdown-item value="BC" label="British Columbia"></goa-dropdown-item>
    <goa-dropdown-item value="MB" label="Manitoba"></goa-dropdown-item>
    <goa-dropdown-item value="NB" label="New Brunswick"></goa-dropdown-item>
    <goa-dropdown-item value="NL" label="Newfoundland and Labrador"></goa-dropdown-item>
    <goa-dropdown-item value="NS" label="Nova Scotia"></goa-dropdown-item>
    <goa-dropdown-item value="ON" label="Ontario"></goa-dropdown-item>
    <goa-dropdown-item value="PE" label="Prince Edward Island"></goa-dropdown-item>
    <goa-dropdown-item value="QC" label="Quebec"></goa-dropdown-item>
    <goa-dropdown-item value="SK" label="Saskatchewan"></goa-dropdown-item>
    <goa-dropdown-item value="NT" label="Northwest Territories"></goa-dropdown-item>
    <goa-dropdown-item value="NU" label="Nunavut"></goa-dropdown-item>
    <goa-dropdown-item value="YT" label="Yukon"></goa-dropdown-item>
  </goa-dropdown>
</goa-form-item>

<goa-form-item version="2" label="Postal code" mt="l">
  <goa-input version="2" id="postal-code" name="postal-code" width="105px"> </goa-input>
</goa-form-item>

<goa-button version="2" type="submit" mt="2xl" id="submit-btn">
  Save and continue
</goa-button>

Hero banner with actions

function handleClick() {
  console.log("Call to action clicked");
}
<GoabHeroBanner heading="Supporting Businesses">
  Resources are available to help Alberta entrepreneurs and small businesses start,
  grow and succeed.
  <GoabHeroBannerActions>
    <GoabButton type="start" onClick={handleClick}>
      Call to action
    </GoabButton>
  </GoabHeroBannerActions>
</GoabHeroBanner>
onClick(): void {
  console.log("Call to action clicked");
}
<goab-hero-banner heading="Supporting Businesses" [actions]="heroBannerActionTemplate">
  Resources are available to help Alberta entrepreneurs and small businesses start, grow
  and succeed.
  <ng-template #heroBannerActionTemplate>
    <goab-button type="start" (onClick)="onClick()">Call to action</goab-button>
  </ng-template>
</goab-hero-banner>
document.getElementById("cta-btn").addEventListener("_click", () => {
  console.log("Call to action clicked");
});
<goa-hero-banner heading="Supporting Businesses">
  Resources are available to help Alberta entrepreneurs and small businesses start, grow
  and succeed.
  <div slot="actions">
    <goa-button version="2" type="start" id="cta-btn">Call to action</goa-button>
  </div>
</goa-hero-banner>

Hide and show many sections of information

const [expandedAll, setExpandedAll] = useState<boolean>(false);
const [expandedList, setExpandedList] = useState<number[]>([]);

useEffect(() => {
  setExpandedAll(expandedList.length === 4);
}, [expandedList.length]);

const expandOrCollapseAll = () => {
  setExpandedAll((prev) => {
    const newState = !prev;
    setExpandedList(newState ? [1, 2, 3, 4] : []);
    return newState;
  });
};

const updateAccordion = (order: number, isOpen: boolean) => {
  setExpandedList((prev) => {
    if (isOpen) {
      return prev.includes(order) ? prev : [...prev, order];
    }
    return prev.filter((item) => item !== order);
  });
};
<GoabButton
  type="tertiary"
  size="compact"
  mb="m"
  onClick={() => expandOrCollapseAll()}
>
  {expandedAll ? "Hide all sections" : "Show all sections"}
</GoabButton>

<GoabAccordion
  open={expandedList.includes(1)}
  heading="How do I create an account?"
  headingSize="medium"
  onChange={(open) => updateAccordion(1, open)}
>
  To create an account you will need to contact your office admin.
</GoabAccordion>

<GoabAccordion
  open={expandedList.includes(2)}
  heading="What verification is needed to sign documents digitally?"
  headingSize="medium"
  onChange={(open) => updateAccordion(2, open)}
>
  You will need to verify your identity through our two factor authentication in
  addition to the digital signature.
</GoabAccordion>

<GoabAccordion
  open={expandedList.includes(3)}
  heading="Can I track the status of my service requests online?"
  headingSize="medium"
  onChange={(open) => updateAccordion(3, open)}
>
  Yes, you can see the status of your application on the main service dashboard when
  you login. You will receive updates and notifications in your email as your
  request progresses.
</GoabAccordion>

<GoabAccordion
  open={expandedList.includes(4)}
  heading="Are there accessibility features for people with disabilities?"
  headingSize="medium"
  onChange={(open) => updateAccordion(4, open)}
>
  Yes, our digital service is designed with accessibility in mind.{" "}
  <a href="#">More information on accessibility.</a>
</GoabAccordion>
expandedList: boolean[] = [false, false, false, false];
expandedAll = false;
accordionStatus = "Show all sections";

toggleAccordion(index: number, open: boolean): void {
  this.expandedList[index] = open;
  this.updateAccordionStatus();
}

onClick(): void {
  const isExpanding = this.expandedList.some((isOpen) => !isOpen);
  this.expandedList = this.expandedList.map(() => isExpanding);
  this.updateAccordionStatus();
}

private updateAccordionStatus(): void {
  this.expandedAll = this.expandedList.every((isOpen) => isOpen);
  this.accordionStatus = this.expandedList.every((isOpen) => isOpen)
    ? "Hide all sections"
    : "Show all sections";
}
<goab-button type="tertiary" size="compact" mb="m" (onClick)="onClick()">
  {{ accordionStatus }}
</goab-button>

<goab-accordion
  heading="How do I create an account?"
  headingSize="medium"
  [open]="expandedList[0]"
  (onChange)="toggleAccordion(0, $event)"
>
  To create an account you will need to contact your office admin.
</goab-accordion>

<goab-accordion
  heading="What verification is needed to sign documents digitally?"
  headingSize="medium"
  [open]="expandedList[1]"
  (onChange)="toggleAccordion(1, $event)"
>
  You will need to verify your identity through our two factor authentication in addition
  to the digital signature.
</goab-accordion>

<goab-accordion
  heading="Can I track the status of my service requests online?"
  headingSize="medium"
  [open]="expandedList[2]"
  (onChange)="toggleAccordion(2, $event)"
>
  Yes, you can see the status of your application on the main service dashboard when you
  login. You will receive updates and notifications in your email as your request
  progresses.
</goab-accordion>

<goab-accordion
  heading="Are there accessibility features for people with disabilities?"
  headingSize="medium"
  [open]="expandedList[3]"
  (onChange)="toggleAccordion(3, $event)"
>
  Yes, our digital service is designed with accessibility in mind.
  <a href="#">More information on accessibility.</a>
</goab-accordion>
const expandedList = [false, false, false, false];
const toggleBtn = document.getElementById("toggle-all-btn");
const accordions = [
  document.getElementById("accordion-1"),
  document.getElementById("accordion-2"),
  document.getElementById("accordion-3"),
  document.getElementById("accordion-4"),
];

function updateButtonText() {
  const allExpanded = expandedList.every((isOpen) => isOpen);
  toggleBtn.textContent = allExpanded ? "Hide all sections" : "Show all sections";
}

accordions.forEach((accordion, index) => {
  accordion.addEventListener("_change", (e) => {
    expandedList[index] = e.detail.open;
    updateButtonText();
  });
});

toggleBtn.addEventListener("_click", () => {
  const isExpanding = expandedList.some((isOpen) => !isOpen);
  expandedList.fill(isExpanding);
  accordions.forEach((accordion) => {
    accordion.setAttribute("open", isExpanding);
  });
  updateButtonText();
});
<goa-button version="2" type="tertiary" size="compact" mb="m" id="toggle-all-btn">
  Show all sections
</goa-button>

<goa-accordion
  id="accordion-1"
  heading="How do I create an account?"
  heading-size="medium"
>
  To create an account you will need to contact your office admin.
</goa-accordion>

<goa-accordion
  id="accordion-2"
  heading="What verification is needed to sign documents digitally?"
  heading-size="medium"
>
  You will need to verify your identity through our two factor authentication in addition
  to the digital signature.
</goa-accordion>

<goa-accordion
  id="accordion-3"
  heading="Can I track the status of my service requests online?"
  heading-size="medium"
>
  Yes, you can see the status of your application on the main service dashboard when you
  login. You will receive updates and notifications in your email as your request
  progresses.
</goa-accordion>

<goa-accordion
  id="accordion-4"
  heading="Are there accessibility features for people with disabilities?"
  heading-size="medium"
>
  Yes, our digital service is designed with accessibility in mind.
  <a href="#">More information on accessibility.</a>
</goa-accordion>

Require user action before continuing

const [open, setOpen] = useState(false);
<GoabButton onClick={() => setOpen(true)}>Open Basic Modal</GoabButton>
<GoabModal
  heading="Are you sure you want to continue?"
  open={open}
  onClose={() => setOpen(false)}
  actions={
    <GoabButtonGroup alignment="end">
      <GoabButton type="secondary" size="compact" onClick={() => setOpen(false)}>
        Back
      </GoabButton>
      <GoabButton type="primary" size="compact" onClick={() => setOpen(false)}>
        Continue
      </GoabButton>
    </GoabButtonGroup>
  }
>
  <p>You cannot return to this page.</p>
</GoabModal>
open = false;

toggleModal(): void {
  this.open = !this.open;
}
<goab-button (onClick)="toggleModal()">Open Basic Modal</goab-button>
<goab-modal
  [open]="open"
  (onClose)="toggleModal()"
  heading="Are you sure you want to continue?"
  [actions]="actions"
>
  <p>You cannot return to this page.</p>
  <ng-template #actions>
    <goab-button-group alignment="end">
      <goab-button type="secondary" size="compact" (onClick)="toggleModal()"
        >Back</goab-button
      >
      <goab-button type="primary" size="compact" (onClick)="toggleModal()"
        >Continue</goab-button
      >
    </goab-button-group>
  </ng-template>
</goab-modal>
const modal = document.getElementById("confirmation-modal");
const openBtn = document.getElementById("open-modal-btn");
const backBtn = document.getElementById("back-btn");
const continueBtn = document.getElementById("continue-btn");

function openModal() {
  modal.setAttribute("open", "true");
}

function closeModal() {
  modal.removeAttribute("open");
}

openBtn.addEventListener("_click", openModal);
backBtn.addEventListener("_click", closeModal);
continueBtn.addEventListener("_click", closeModal);
modal.addEventListener("_close", closeModal);
<goa-button version="2" id="open-modal-btn">Open Basic Modal</goa-button>
<goa-modal
  version="2"
  id="confirmation-modal"
  heading="Are you sure you want to continue?"
>
  <p>You cannot return to this page.</p>
  <div slot="actions">
    <goa-button-group alignment="end">
      <goa-button version="2" id="back-btn" type="secondary" size="compact"
        >Back</goa-button
      >
      <goa-button version="2" id="continue-btn" type="primary" size="compact"
        >Continue</goa-button
      >
    </goa-button-group>
  </div>
</goa-modal>

Reset date picker field

const [date, setDate] = useState<Date | undefined>();

const setNewDate = (value: Date | undefined) => {
  setDate(value);
};

function setValue() {
  const d = new Date();
  d.setDate(d.getDate() - 7);
  setDate(d);
}

function clearValue() {
  setDate(undefined);
}
<GoabFormItem label="Date Picker">
  <GoabDatePicker
    name="item"
    value={date}
    onChange={(e) => setNewDate(e.value as Date)}
    mb="xl"
  />
</GoabFormItem>

<GoabButtonGroup mt="xs" alignment="start">
  <GoabButton onClick={setValue}>Set Value</GoabButton>
  <GoabButton onClick={clearValue}>Clear Value</GoabButton>
</GoabButtonGroup>
item: Date | undefined = undefined;

onChange(event: GoabDatePickerOnChangeDetail): void {
  this.item = event.valueStr ? new Date(event.valueStr) : undefined;
}

setValue(): void {
  const d = new Date();
  d.setDate(d.getDate() - 7);
  this.item = d;
}

clearValue(): void {
  this.item = undefined;
}
<goab-form-item label="Date Picker">
  <goab-date-picker (onChange)="onChange($event)" name="item" [value]="item">
  </goab-date-picker>
</goab-form-item>

<goab-button-group alignment="start" mt="xs">
  <goab-button (onClick)="setValue()">Set Value</goab-button>
  <goab-button (onClick)="clearValue()">Clear Value</goab-button>
</goab-button-group>
const datePicker = document.getElementById("date-picker");
const setValueBtn = document.getElementById("set-value-btn");
const clearValueBtn = document.getElementById("clear-value-btn");

datePicker.addEventListener("_change", (e) => {
  console.log("Date changed:", e.detail.value);
});

setValueBtn.addEventListener("_click", () => {
  const d = new Date();
  d.setDate(d.getDate() - 7);
  datePicker.setAttribute("value", d.toISOString());
});

clearValueBtn.addEventListener("_click", () => {
  datePicker.removeAttribute("value");
});
<goa-form-item version="2" label="Date Picker">
  <goa-date-picker version="2" id="date-picker" name="item"></goa-date-picker>
</goa-form-item>

<goa-button-group alignment="start" mt="xs">
  <goa-button version="2" id="set-value-btn">Set Value</goa-button>
  <goa-button version="2" id="clear-value-btn">Clear Value</goa-button>
</goa-button-group>

Question page

const [answer, setAnswer] = useState("");

const handleContinue = () => {
  console.log("Answer submitted:", answer);
};
      <GoabLink leadingIcon="arrow-back" size="small" mb="none">
        Back
      </GoabLink>

      <GoabText tag="h1" mt="xl" mb="m">
        What is your email address?
      </GoabText>
      <GoabText mt="none" mb="xl">
        We'll use this to send you confirmation of your application.
      </GoabText>

      <GoabFormItem label="Email address">
        <GoabInput
          name="email"
          type="email"
          value={answer}
          onChange={(e) => setAnswer(e.value)}
          width="100%"
        />
      </GoabFormItem>

      <GoabButtonGroup alignment="start" mt="2xl">
        <GoabButton type="primary" onClick={handleContinue}>
          Continue
        </GoabButton>
      </GoabButtonGroup>
  );
}
answer = "";

onAnswerChange(event: { value: string }): void {
  this.answer = event.value;
}

handleContinue(): void {
  console.log("Answer submitted:", this.answer);
}
<goab-link leadingIcon="arrow-back" size="small" mb="none"> Back </goab-link>

<goab-text tag="h1" mt="xl" mb="m">What is your email address?</goab-text>
<goab-text mt="none" mb="xl"
  >We'll use this to send you confirmation of your application.</goab-text
>

<goab-form-item label="Email address">
  <goab-input
    name="email"
    type="email"
    [value]="answer"
    (onChange)="onAnswerChange($event)"
    width="100%"
  >
  </goab-input>
</goab-form-item>

<goab-button-group alignment="start" mt="2xl">
  <goab-button type="primary" (onClick)="handleContinue()"> Continue </goab-button>
</goab-button-group>
const emailInput = document.getElementById("email-input");
const continueBtn = document.getElementById("continue-btn");
let answer = "";

emailInput.addEventListener("_change", (e) => {
  answer = e.detail.value;
});

continueBtn.addEventListener("_click", () => {
  console.log("Answer submitted:", answer);
});
<goa-link leadingicon="arrow-back" size="small" mb="none"> Back </goa-link>

<goa-text as="h1" mt="xl" mb="m">What is your email address?</goa-text>
<goa-text mt="none" mb="xl"
  >We'll use this to send you confirmation of your application.</goa-text
>

<goa-form-item version="2" label="Email address">
  <goa-input version="2" id="email-input" name="email" type="email" width="100%">
  </goa-input>
</goa-form-item>

<goa-button-group alignment="start" mt="2xl">
  <goa-button version="2" id="continue-btn" type="primary"> Continue </goa-button>
</goa-button-group>

Review and action

<GoabGrid minChildWidth="315px">
  <GoabContainer accent="thin" type="non-interactive">
    <GoabText size="heading-m" mt="none" mb="m">
      Appearance details
    </GoabText>
    <GoabGrid minChildWidth="200px" gap="m">
      <GoabBlock direction="column" gap="xs">
        <GoabText size="body-s" color="secondary" mt="none" mb="none">
          Accused name
        </GoabText>
        <GoabText size="body-m" mt="none" mb="none">
          Doe, John Scott
        </GoabText>
      </GoabBlock>

      <GoabBlock direction="column" gap="xs">
        <GoabText size="body-s" color="secondary" mt="none" mb="none">
          Date of birth
        </GoabText>
        <GoabText size="body-m" mt="none" mb="none">
          Mar 14, 2021
        </GoabText>
      </GoabBlock>

      <GoabBlock direction="column" gap="xs">
        <GoabText size="body-s" color="secondary" mt="none" mb="none">
          Court location
        </GoabText>
        <GoabText size="body-m" mt="none" mb="none">
          Calgary
        </GoabText>
      </GoabBlock>

      <GoabBlock direction="column" gap="xs">
        <GoabText size="body-s" color="secondary" mt="none" mb="none">
          Upcoming appearance date{"(s)"}
        </GoabText>
        <GoabText size="body-m" mt="none" mb="none">
          Sep 20, 2021
        </GoabText>
      </GoabBlock>
    </GoabGrid>

    <GoabText size="heading-xs" mt="l" mb="s">
      Docket number{"(s)"} &amp; charges
    </GoabText>
    <GoabContainer type="non-interactive" padding="compact">
      <GoabText size="heading-xs" mt="none" mb="xs">
        {"1) 12345678"}
      </GoabText>
      <GoabText size="body-m" mt="none" mb="none">
        {"CC 334(1) - Theft under $5000"}
      </GoabText>
      <GoabText size="body-m" mt="none" mb="none">
        {"CC 268(1) - Aggravated assault"}
      </GoabText>
    </GoabContainer>

    <GoabContainer type="non-interactive" padding="compact">
      <GoabText size="heading-xs" mt="none" mb="xs">
        {"2) 12345678"}
      </GoabText>
      <GoabText size="body-m" mt="none" mb="none">
        {"CC 334(1) - Theft under $5000"}
      </GoabText>
      <GoabText size="body-m" mt="none" mb="none">
        {"CC 268(1) - Aggravated assault"}
      </GoabText>
    </GoabContainer>
  </GoabContainer>

  <GoabContainer accent="thin" width="content">
    <form>
      <GoabText size="heading-m" mt="none" mb="m">
        Adjournment request
      </GoabText>
      <GoabText size="body-m" mt="none" mb="none">
        Keep track of the individuals who are placed in lodges and may qualify for the
        Lodge Assistance Program subsidy.
      </GoabText>

      <GoabFormItem label="Case history and new request" mt="l">
        <GoabRadioGroup name="case" orientation="horizontal" onChange={() => {}}>
          <GoabRadioItem value="grant" label="Grant" />
          <GoabRadioItem value="deny" label="Deny" />
        </GoabRadioGroup>
      </GoabFormItem>

      <GoabFormItem label="Reason to deny" mt="l">
        <GoabDropdown name="reason" width="100%" onChange={() => {}}>
          <GoabDropdownItem value="1" label="Incomplete Application" />
          <GoabDropdownItem value="2" label="Eligibility Criteria Not Met" />
          <GoabDropdownItem value="3" label="Documentation Verification Failure" />
        </GoabDropdown>
      </GoabFormItem>

      <GoabFormItem label="Message" mt="l">
        <GoabTextArea
          name="message"
          rows={5}
          width="100%"
          value=""
          onChange={() => {}}
        />
      </GoabFormItem>

      <GoabButton mt="xl" onClick={() => {}}>
        Confirm adjournment
      </GoabButton>
    </form>
  </GoabContainer>
</GoabGrid>
form: FormGroup;

constructor(private fb: FormBuilder) {
  this.form = this.fb.group({
    case: [""],
    reason: [""],
    message: [""],
  });
}

onClick(): void {
  console.log("Confirm clicked!");
}
<goab-grid minChildWidth="315px">
  <goab-container accent="thin" type="non-interactive">
    <goab-text size="heading-m" mt="none" mb="m">Appearance details</goab-text>
    <goab-grid minChildWidth="200px" gap="m">
      <goab-block direction="column" gap="xs">
        <goab-text size="body-s" color="secondary" mt="none" mb="none"
          >Accused name</goab-text
        >
        <goab-text size="body-m" mt="none" mb="none">Doe, John Scott</goab-text>
      </goab-block>

      <goab-block direction="column" gap="xs">
        <goab-text size="body-s" color="secondary" mt="none" mb="none"
          >Date of birth</goab-text
        >
        <goab-text size="body-m" mt="none" mb="none">Mar 14, 2021</goab-text>
      </goab-block>

      <goab-block direction="column" gap="xs">
        <goab-text size="body-s" color="secondary" mt="none" mb="none"
          >Court location</goab-text
        >
        <goab-text size="body-m" mt="none" mb="none">Calgary</goab-text>
      </goab-block>

      <goab-block direction="column" gap="xs">
        <goab-text size="body-s" color="secondary" mt="none" mb="none"
          >Upcoming appearance date(s)</goab-text
        >
        <goab-text size="body-m" mt="none" mb="none">Sep 20, 2021</goab-text>
      </goab-block>
    </goab-grid>

    <goab-text size="heading-xs" mt="l" mb="s">Docket number(s) &amp; charges</goab-text>
    <goab-container type="non-interactive" padding="compact">
      <goab-text size="heading-xs" mt="none" mb="xs">1) 12345678</goab-text>
      <goab-text size="body-m" mt="none" mb="none"
        >CC 334(1) - Theft under $5000</goab-text
      >
      <goab-text size="body-m" mt="none" mb="none"
        >CC 268(1) - Aggravated assault</goab-text
      >
    </goab-container>

    <goab-container type="non-interactive" padding="compact">
      <goab-text size="heading-xs" mt="none" mb="xs">2) 12345678</goab-text>
      <goab-text size="body-m" mt="none" mb="none"
        >CC 334(1) - Theft under $5000</goab-text
      >
      <goab-text size="body-m" mt="none" mb="none"
        >CC 268(1) - Aggravated assault</goab-text
      >
    </goab-container>
  </goab-container>

  <goab-container accent="thin" width="content">
    <form [formGroup]="form">
      <goab-text size="heading-m" mt="none" mb="m">Adjournment request</goab-text>
      <goab-text size="body-m" mt="none" mb="none">
        Keep track of the individuals who are placed in lodges and may qualify for the
        Lodge Assistance Program subsidy.
      </goab-text>

      <goab-form-item label="Case history and new request" mt="l">
        <goab-radio-group name="case" orientation="horizontal" formControlName="case">
          <goab-radio-item value="grant" label="Grant"></goab-radio-item>
          <goab-radio-item value="deny" label="Deny"></goab-radio-item>
        </goab-radio-group>
      </goab-form-item>

      <goab-form-item label="Reason to deny" mt="l">
        <goab-dropdown name="reason" width="100%" formControlName="reason">
          <goab-dropdown-item
            value="1"
            label="Incomplete Application"
          ></goab-dropdown-item>
          <goab-dropdown-item
            value="2"
            label="Eligibility Criteria Not Met"
          ></goab-dropdown-item>
          <goab-dropdown-item
            value="3"
            label="Documentation Verification Failure"
          ></goab-dropdown-item>
        </goab-dropdown>
      </goab-form-item>

      <goab-form-item label="Message" mt="l">
        <goab-textarea
          name="message"
          [rows]="5"
          width="100%"
          formControlName="message"
        ></goab-textarea>
      </goab-form-item>

      <goab-button mt="xl" (onClick)="onClick()">Confirm adjournment</goab-button>
    </form>
  </goab-container>
</goab-grid>
document.getElementById("confirm-btn").addEventListener("_click", () => {
  console.log("Confirm clicked!");
});
<goa-grid minchildwidth="315px">
  <goa-container accent="thin" type="non-interactive">
    <goa-text size="heading-m" mt="none" mb="m">Appearance details</goa-text>
    <goa-grid minchildwidth="200px" gap="m">
      <goa-block direction="column" gap="xs">
        <goa-text size="body-s" color="secondary" mt="none" mb="none"
          >Accused name</goa-text
        >
        <goa-text size="body-m" mt="none" mb="none">Doe, John Scott</goa-text>
      </goa-block>

      <goa-block direction="column" gap="xs">
        <goa-text size="body-s" color="secondary" mt="none" mb="none"
          >Date of birth</goa-text
        >
        <goa-text size="body-m" mt="none" mb="none">Mar 14, 2021</goa-text>
      </goa-block>

      <goa-block direction="column" gap="xs">
        <goa-text size="body-s" color="secondary" mt="none" mb="none"
          >Court location</goa-text
        >
        <goa-text size="body-m" mt="none" mb="none">Calgary</goa-text>
      </goa-block>

      <goa-block direction="column" gap="xs">
        <goa-text size="body-s" color="secondary" mt="none" mb="none"
          >Upcoming appearance date(s)</goa-text
        >
        <goa-text size="body-m" mt="none" mb="none">Sep 20, 2021</goa-text>
      </goa-block>
    </goa-grid>

    <goa-text size="heading-xs" mt="l" mb="s">Docket number(s) &amp; charges</goa-text>
    <goa-container type="non-interactive" padding="compact">
      <goa-text size="heading-xs" mt="none" mb="xs">1) 12345678</goa-text>
      <goa-text size="body-m" mt="none" mb="none">CC 334(1) - Theft under $5000</goa-text>
      <goa-text size="body-m" mt="none" mb="none"
        >CC 268(1) - Aggravated assault</goa-text
      >
    </goa-container>

    <goa-container type="non-interactive" padding="compact">
      <goa-text size="heading-xs" mt="none" mb="xs">2) 12345678</goa-text>
      <goa-text size="body-m" mt="none" mb="none">CC 334(1) - Theft under $5000</goa-text>
      <goa-text size="body-m" mt="none" mb="none"
        >CC 268(1) - Aggravated assault</goa-text
      >
    </goa-container>
  </goa-container>

  <goa-container accent="thin" width="content">
    <form>
      <goa-text size="heading-m" mt="none" mb="m">Adjournment request</goa-text>
      <goa-text size="body-m" mt="none" mb="none">
        Keep track of the individuals who are placed in lodges and may qualify for the
        Lodge Assistance Program subsidy.
      </goa-text>

      <goa-form-item version="2" label="Case history and new request" mt="l">
        <goa-radio-group version="2" name="case" orientation="horizontal">
          <goa-radio-item value="grant" label="Grant"></goa-radio-item>
          <goa-radio-item value="deny" label="Deny"></goa-radio-item>
        </goa-radio-group>
      </goa-form-item>

      <goa-form-item version="2" label="Reason to deny" mt="l">
        <goa-dropdown version="2" name="reason" width="100%">
          <goa-dropdown-item value="1" label="Incomplete Application"></goa-dropdown-item>
          <goa-dropdown-item
            value="2"
            label="Eligibility Criteria Not Met"
          ></goa-dropdown-item>
          <goa-dropdown-item
            value="3"
            label="Documentation Verification Failure"
          ></goa-dropdown-item>
        </goa-dropdown>
      </goa-form-item>

      <goa-form-item version="2" label="Message" mt="l">
        <goa-textarea version="2" name="message" rows="5" width="100%"></goa-textarea>
      </goa-form-item>

      <goa-button version="2" id="confirm-btn" mt="xl">Confirm adjournment</goa-button>
    </form>
  </goa-container>
</goa-grid>

Review page

      <GoabText size="heading-l" mt="none" mb="none">
        Review your answers
      </GoabText>
      <GoabText size="heading-s" color="secondary" mt="l" mb="none">
        Your situation
      </GoabText>
      <GoabTable mt="l">
        <tbody>
          <tr>
            <td>
              <strong>
                What was your (the applicant's) relationship to the deceased?
              </strong>
            </td>
            <td>Other</td>
            <td>
              <GoabLink>Change</GoabLink>
            </td>
          </tr>
          <tr>
            <td>
              <strong>My relationship to the deceased was</strong>
            </td>
            <td>Manager</td>
            <td>
              <GoabLink>Change</GoabLink>
            </td>
          </tr>
          <tr>
            <td>
              <strong>
                Was the deceased part of a household that was receiving Assured Income for
                the Severely Handicapped (AISH) or Income Support?
              </strong>
            </td>
            <td>No</td>
            <td>
              <GoabLink>Change</GoabLink>
            </td>
          </tr>
          <tr>
            <td>
              <strong>Was the deceased a minor?</strong>
            </td>
            <td>No</td>
            <td>
              <GoabLink>Change</GoabLink>
            </td>
          </tr>
          <tr>
            <td>
              <strong>What was the deceased's marital status at time of death?</strong>
            </td>
            <td>Married</td>
            <td>
              <GoabLink>Change</GoabLink>
            </td>
          </tr>
          <tr>
            <td>
              <strong>Did the deceased have any dependents?</strong>
            </td>
            <td>No</td>
            <td>
              <GoabLink>Change</GoabLink>
            </td>
          </tr>
          <tr>
            <td>
              <strong>Was the deceased a sponsored immigrant?</strong>
            </td>
            <td>Yes</td>
            <td>
              <GoabLink>Change</GoabLink>
            </td>
          </tr>
        </tbody>
      </GoabTable>
      <GoabButtonGroup alignment="start" mt="2xl">
        <GoabButton type="primary">Confirm and continue</GoabButton>
        <GoabButton type="tertiary">Back to application overview</GoabButton>
      </GoabButtonGroup>
  );
}
onChangeClick(): void {
  console.log("Change clicked");
}

onConfirmClick(): void {
  console.log("Confirm clicked");
}

onBackClick(): void {
  console.log("Back clicked");
}
<goab-text size="heading-l" mt="none" mb="none">Review your answers</goab-text>
<goab-text size="heading-s" color="secondary" mt="l" mb="none">Your situation</goab-text>
<goab-table mt="l">
  <tbody>
    <tr>
      <td>
        <strong>What was your (the applicant's) relationship to the deceased?</strong>
      </td>
      <td>Other</td>
      <td><goab-link>Change</goab-link></td>
    </tr>
    <tr>
      <td><strong>My relationship to the deceased was</strong></td>
      <td>Manager</td>
      <td><goab-link>Change</goab-link></td>
    </tr>
    <tr>
      <td>
        <strong
          >Was the deceased part of a household that was receiving Assured Income for the
          Severely Handicapped (AISH) or Income Support?</strong
        >
      </td>
      <td>No</td>
      <td><goab-link>Change</goab-link></td>
    </tr>
    <tr>
      <td><strong>Was the deceased a minor?</strong></td>
      <td>No</td>
      <td><goab-link>Change</goab-link></td>
    </tr>
    <tr>
      <td><strong>What was the deceased's marital status at time of death?</strong></td>
      <td>Married</td>
      <td><goab-link>Change</goab-link></td>
    </tr>
    <tr>
      <td><strong>Did the deceased have any dependents?</strong></td>
      <td>No</td>
      <td><goab-link>Change</goab-link></td>
    </tr>
    <tr>
      <td><strong>Was the deceased a sponsored immigrant?</strong></td>
      <td>Yes</td>
      <td><goab-link>Change</goab-link></td>
    </tr>
  </tbody>
</goab-table>
<goab-button-group alignment="start" mt="2xl">
  <goab-button type="primary" (onClick)="onConfirmClick()"
    >Confirm and continue</goab-button
  >
  <goab-button type="tertiary" (onClick)="onBackClick()"
    >Back to application overview</goab-button
  >
</goab-button-group>
document.getElementById("confirm-btn").addEventListener("_click", () => {
  console.log("Confirm clicked");
});
<goa-text size="heading-l" mt="none" mb="none">Review your answers</goa-text>
<goa-text size="heading-s" color="secondary" mt="l" mb="none">Your situation</goa-text>
<goa-table version="2" mt="l">
  <table>
    <tbody>
      <tr>
        <td>
          <strong>What was your (the applicant's) relationship to the deceased?</strong>
        </td>
        <td>Other</td>
        <td><goa-link>Change</goa-link></td>
      </tr>
      <tr>
        <td><strong>My relationship to the deceased was</strong></td>
        <td>Manager</td>
        <td><goa-link>Change</goa-link></td>
      </tr>
      <tr>
        <td>
          <strong
            >Was the deceased part of a household that was receiving Assured Income for
            the Severely Handicapped (AISH) or Income Support?</strong
          >
        </td>
        <td>No</td>
        <td><goa-link>Change</goa-link></td>
      </tr>
      <tr>
        <td><strong>Was the deceased a minor?</strong></td>
        <td>No</td>
        <td><goa-link>Change</goa-link></td>
      </tr>
      <tr>
        <td><strong>What was the deceased's marital status at time of death?</strong></td>
        <td>Married</td>
        <td><goa-link>Change</goa-link></td>
      </tr>
      <tr>
        <td><strong>Did the deceased have any dependents?</strong></td>
        <td>No</td>
        <td><goa-link>Change</goa-link></td>
      </tr>
      <tr>
        <td><strong>Was the deceased a sponsored immigrant?</strong></td>
        <td>Yes</td>
        <td><goa-link>Change</goa-link></td>
      </tr>
    </tbody>
  </table>
</goa-table>
<goa-button-group alignment="start" mt="2xl">
  <goa-button version="2" type="primary" id="confirm-btn"
    >Confirm and continue</goa-button
  >
  <goa-button version="2" type="tertiary" id="back-btn"
    >Back to application overview</goa-button
  >
</goa-button-group>
const [search, setSearch] = useState("");

const onClick = () => {
  console.log("search:", search);
};
<form>
  <GoabFormItem>
    <GoabBlock gap="xs" direction="row">
      <GoabInput
        type="search"
        name="search"
        value={search}
        onChange={(e) => setSearch(e.value)}
        leadingIcon="search"
      />
      <GoabButton type="primary" onClick={onClick}>
        Search
      </GoabButton>
    </GoabBlock>
  </GoabFormItem>
</form>
form: FormGroup;

constructor(private fb: FormBuilder) {
  this.form = this.fb.group({
    search: [""],
  });
}

onClick(): void {
  console.log("search:", this.form.controls["search"].value);
}
<form [formGroup]="form">
  <goab-form-item>
    <goab-block gap="xs" direction="row">
      <goab-input
        type="search"
        name="search"
        formControlName="search"
        leadingIcon="search"
      >
      </goab-input>
      <goab-button type="primary" (onClick)="onClick()">Search</goab-button>
    </goab-block>
  </goab-form-item>
</form>
const searchInput = document.getElementById("search-input");
const searchBtn = document.getElementById("search-btn");
let searchValue = "";

searchInput.addEventListener("_change", (e) => {
  searchValue = e.detail.value;
});

searchBtn.addEventListener("_click", () => {
  console.log("search:", searchValue);
});
<form>
  <goa-form-item version="2">
    <goa-block gap="xs" direction="row">
      <goa-input
        version="2"
        id="search-input"
        type="search"
        name="search"
        leadingicon="search"
      >
      </goa-input>
      <goa-button version="2" id="search-btn" type="primary">Search</goa-button>
    </goa-block>
  </goa-form-item>
</form>

Set a specific tab to be active

const review = [0, 1, 2, 3];
const complete = [0, 1];
<GoabTabs initialTab={2}>
  <GoabTab heading="All">
    <GoabTable width="100%">
      <thead>
        <tr>
          <th>Status</th>
          <th>Text</th>
          <th className="goa-table-number-header">Number</th>
          <th style={{ width: "1%", whiteSpace: "nowrap" }}>Action</th>
        </tr>
      </thead>
      <tbody>
        {review.map((i) => (
          <tr key={`review-${i}`}>
            <td>
              <GoabBadge type="important" content="Review pending" />
            </td>
            <td>Lorem Ipsum</td>
            <td className="goa-table-number-column">1234567890</td>
            <td>
              <GoabButton type="tertiary" size="compact">
                Action
              </GoabButton>
            </td>
          </tr>
        ))}
        {complete.map((i) => (
          <tr key={`complete-${i}`}>
            <td>
              <GoabBadge type="information" content="Complete" />
            </td>
            <td>Lorem Ipsum</td>
            <td className="goa-table-number-column">1234567890</td>
            <td>
              <GoabButton type="tertiary" size="compact">
                Action
              </GoabButton>
            </td>
          </tr>
        ))}
      </tbody>
    </GoabTable>
  </GoabTab>
  <GoabTab
    heading={
        Review pending
        <GoabBadge type="important" content="4" icon={false} />
    }
  >
    <GoabTable width="100%">
      <thead>
        <tr>
          <th>Status</th>
          <th>Text</th>
          <th className="goa-table-number-header">Number</th>
          <th style={{ width: "1%", whiteSpace: "nowrap" }}>Action</th>
        </tr>
      </thead>
      <tbody>
        {review.map((i) => (
          <tr key={i}>
            <td>
              <GoabBadge type="important" content="Review pending" />
            </td>
            <td>Lorem Ipsum</td>
            <td className="goa-table-number-column">1234567890</td>
            <td>
              <GoabButton type="tertiary" size="compact">
                Action
              </GoabButton>
            </td>
          </tr>
        ))}
      </tbody>
    </GoabTable>
  </GoabTab>
  <GoabTab
    heading={
      <>
        Complete
        <GoabBadge type="information" content="338" icon={false} />
      </>
    }
  >
    <GoabTable width="100%">
      <thead>
        <tr>
          <th>Status</th>
          <th>Text</th>
          <th className="goa-table-number-header">Number</th>
          <th style={{ width: "1%", whiteSpace: "nowrap" }}>Action</th>
        </tr>
      </thead>
      <tbody>
        {complete.map((i) => (
          <tr key={i}>
            <td>
              <GoabBadge type="information" content="Complete" />
            </td>
            <td>Lorem Ipsum</td>
            <td className="goa-table-number-column">1234567890</td>
            <td>
              <GoabButton type="tertiary" size="compact">
                Action
              </GoabButton>
            </td>
          </tr>
        ))}
      </tbody>
    </GoabTable>
  </GoabTab>
</GoabTabs>
review = [0, 1, 2, 3];
complete = [0, 1];
<goab-tabs [initialTab]="2">
  <goab-tab heading="All">
    <goab-table width="100%">
      <thead>
        <tr>
          <th>Status</th>
          <th>Text</th>
          <th class="goa-table-number-header">Number</th>
          <th style="width: 1%; white-space: nowrap">Action</th>
        </tr>
      </thead>
      <tbody>
        @for (i of review; track $index) {
        <tr>
          <td>
            <goab-badge type="important" content="Review pending"></goab-badge>
          </td>
          <td>Lorem Ipsum</td>
          <td class="goa-table-number-column">1234567890</td>
          <td>
            <goab-button type="tertiary" size="compact">Action</goab-button>
          </td>
        </tr>
        } @for (i of complete; track $index) {
        <tr>
          <td>
            <goab-badge type="information" content="Complete"></goab-badge>
          </td>
          <td>Lorem Ipsum</td>
          <td class="goa-table-number-column">1234567890</td>
          <td>
            <goab-button type="tertiary" size="compact">Action</goab-button>
          </td>
        </tr>
        }
      </tbody>
    </goab-table>
  </goab-tab>
  <goab-tab [heading]="reviewPending">
    <ng-template #reviewPending
      >Review pending<goab-badge type="important" content="4" [icon]="false"></goab-badge
    ></ng-template>
    <goab-table width="100%">
      <thead>
        <tr>
          <th>Status</th>
          <th>Text</th>
          <th class="goa-table-number-header">Number</th>
          <th style="width: 1%; white-space: nowrap">Action</th>
        </tr>
      </thead>
      <tbody>
        @for (i of review; track $index) {
        <tr>
          <td>
            <goab-badge type="important" content="Review pending"></goab-badge>
          </td>
          <td>Lorem Ipsum</td>
          <td class="goa-table-number-column">1234567890</td>
          <td>
            <goab-button type="tertiary" size="compact">Action</goab-button>
          </td>
        </tr>
        }
      </tbody>
    </goab-table>
  </goab-tab>
  <goab-tab [heading]="completeTemplate">
    <ng-template #completeTemplate
      >Complete<goab-badge type="information" content="338" [icon]="false"></goab-badge
    ></ng-template>
    <goab-table width="100%">
      <thead>
        <tr>
          <th>Status</th>
          <th>Text</th>
          <th class="goa-table-number-header">Number</th>
          <th style="width: 1%; white-space: nowrap">Action</th>
        </tr>
      </thead>
      <tbody>
        @for (i of complete; track $index) {
        <tr>
          <td>
            <goab-badge type="information" content="Complete"></goab-badge>
          </td>
          <td>Lorem Ipsum</td>
          <td class="goa-table-number-column">1234567890</td>
          <td>
            <goab-button type="tertiary" size="compact">Action</goab-button>
          </td>
        </tr>
        }
      </tbody>
    </goab-table>
  </goab-tab>
</goab-tabs>
<goa-tabs version="2" initialtab="2">
  <goa-tab>
    <div slot="heading">All</div>
    <goa-table version="2" width="100%">
      <table width="100%">
        <thead>
          <tr>
            <th>Status</th>
            <th>Text</th>
            <th class="goa-table-number-header">Number</th>
            <th style="width: 1%; white-space: nowrap">Action</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>
              <goa-badge
                version="2"
                type="important"
                content="Review pending"
              ></goa-badge>
            </td>
            <td>Lorem Ipsum</td>
            <td class="goa-table-number-column">1234567890</td>
            <td>
              <goa-button version="2" type="tertiary" size="compact">Action</goa-button>
            </td>
          </tr>
          <tr>
            <td>
              <goa-badge
                version="2"
                type="important"
                content="Review pending"
              ></goa-badge>
            </td>
            <td>Lorem Ipsum</td>
            <td class="goa-table-number-column">1234567890</td>
            <td>
              <goa-button version="2" type="tertiary" size="compact">Action</goa-button>
            </td>
          </tr>
          <tr>
            <td>
              <goa-badge version="2" type="information" content="Complete"></goa-badge>
            </td>
            <td>Lorem Ipsum</td>
            <td class="goa-table-number-column">1234567890</td>
            <td>
              <goa-button version="2" type="tertiary" size="compact">Action</goa-button>
            </td>
          </tr>
        </tbody>
      </table>
    </goa-table>
  </goa-tab>
  <goa-tab>
    <div slot="heading">
      Review pending<goa-badge
        version="2"
        type="important"
        content="4"
        icon="false"
      ></goa-badge>
    </div>
    <goa-table version="2" width="100%">
      <table width="100%">
        <thead>
          <tr>
            <th>Status</th>
            <th>Text</th>
            <th class="goa-table-number-header">Number</th>
            <th style="width: 1%; white-space: nowrap">Action</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>
              <goa-badge
                version="2"
                type="important"
                content="Review pending"
              ></goa-badge>
            </td>
            <td>Lorem Ipsum</td>
            <td class="goa-table-number-column">1234567890</td>
            <td>
              <goa-button version="2" type="tertiary" size="compact">Action</goa-button>
            </td>
          </tr>
          <tr>
            <td>
              <goa-badge
                version="2"
                type="important"
                content="Review pending"
              ></goa-badge>
            </td>
            <td>Lorem Ipsum</td>
            <td class="goa-table-number-column">1234567890</td>
            <td>
              <goa-button version="2" type="tertiary" size="compact">Action</goa-button>
            </td>
          </tr>
        </tbody>
      </table>
    </goa-table>
  </goa-tab>
  <goa-tab>
    <div slot="heading">
      Complete<goa-badge
        version="2"
        type="information"
        content="338"
        icon="false"
      ></goa-badge>
    </div>
    <goa-table version="2" width="100%">
      <table width="100%">
        <thead>
          <tr>
            <th>Status</th>
            <th>Text</th>
            <th class="goa-table-number-header">Number</th>
            <th style="width: 1%; white-space: nowrap">Action</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>
              <goa-badge version="2" type="information" content="Complete"></goa-badge>
            </td>
            <td>Lorem Ipsum</td>
            <td class="goa-table-number-column">1234567890</td>
            <td>
              <goa-button version="2" type="tertiary" size="compact">Action</goa-button>
            </td>
          </tr>
          <tr>
            <td>
              <goa-badge version="2" type="information" content="Complete"></goa-badge>
            </td>
            <td>Lorem Ipsum</td>
            <td class="goa-table-number-column">1234567890</td>
            <td>
              <goa-button version="2" type="tertiary" size="compact">Action</goa-button>
            </td>
          </tr>
        </tbody>
      </table>
    </goa-table>
  </goa-tab>
</goa-tabs>

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>

Show a notification

const save = async () => {
  // await api.save();

  TemporaryNotification.show("Your application has been saved.", {
    type: "success",
  });
};
<GoabTemporaryNotificationCtrl />
<GoabButton type="secondary" onClick={save}>
  Save
</GoabButton>
async save(): Promise<void> {
  // await this.api.save();

  TemporaryNotification.show("Your application has been saved.", {
    type: "success",
  });
}
<goab-temporary-notification-ctrl></goab-temporary-notification-ctrl>

<goab-button type="secondary" (onClick)="save()">Save</goab-button>
document.getElementById("save-btn").addEventListener("_click", () => {
  // await api.save();

  document.body.dispatchEvent(
    new CustomEvent("msg", {
      composed: true,
      bubbles: true,
      detail: {
        action: "goa:temp-notification",
        data: {
          message: "Your application has been saved.",
          type: "success",
          uuid: crypto.randomUUID(),
          duration: "short",
        },
      },
    }),
  );
});
<goa-temp-notification-ctrl></goa-temp-notification-ctrl>

<goa-button version="2" id="save-btn" type="secondary">Save</goa-button>

Show a section title on a question page

<GoabLink leadingIcon="arrow-back" size="small" mb="none">
  Back
</GoabLink>

<GoabText tag="h3" size="body-m" mt="xl" mb="m" color="secondary">
  Personal information
</GoabText>

<GoabFormItem label="Do you currently live in Canada?" labelSize="large">
  <GoabRadioGroup
    name="canada"
    ariaLabel="Do you currently live in Canada?"
    onChange={() => {}}
  >
    <GoabRadioItem value="yes" label="Yes" />
    <GoabRadioItem value="no" label="No" />
  </GoabRadioGroup>
</GoabFormItem>

<GoabButton type="submit" mt="2xl">
  Save and continue
</GoabButton>
onRadioChange(event: GoabRadioGroupOnChangeDetail): void {
  console.log("Selected:", event.value);
}
<goab-link leadingIcon="arrow-back" size="small" mb="none"> Back </goab-link>

<goab-text tag="h3" size="body-m" mt="xl" mb="m" color="secondary"
  >Personal information</goab-text
>

<goab-form-item label="Do you currently live in Canada?" labelSize="large">
  <goab-radio-group
    name="canada"
    ariaLabel="Do you currently live in Canada?"
    (onChange)="onRadioChange($event)"
  >
    <goab-radio-item value="yes" label="Yes"></goab-radio-item>
    <goab-radio-item value="no" label="No"></goab-radio-item>
  </goab-radio-group>
</goab-form-item>

<goab-button type="submit" mt="2xl"> Save and continue </goab-button>
document.querySelector("goa-radio-group").addEventListener("_change", (e) => {
  console.log("Selected:", e.detail.value);
});
<goa-link leadingicon="arrow-back" size="small" mb="none"> Back </goa-link>

<goa-text as="h3" size="body-m" mt="xl" mb="m" color="secondary"
  >Personal information</goa-text
>

<goa-form-item version="2" label="Do you currently live in Canada?" labelsize="large">
  <goa-radio-group
    version="2"
    name="canada"
    aria-label="Do you currently live in Canada?"
  >
    <goa-radio-item value="yes" label="Yes"></goa-radio-item>
    <goa-radio-item value="no" label="No"></goa-radio-item>
  </goa-radio-group>
</goa-form-item>

<goa-button version="2" type="submit" mt="2xl"> Save and continue </goa-button>

Show a notification with an action

const comment = () => {
  const uuid = TemporaryNotification.show(
    "Edna Mode commented on your assigned case.",
    {
      actionText: "View",
      action: () => {
        TemporaryNotification.dismiss(uuid);
      },
    },
  );
};
<GoabTemporaryNotificationCtrl />
<GoabButton onClick={comment}>Comment</GoabButton>
comment(): void {
  const uuid = TemporaryNotification.show(
    "Edna Mode commented on your assigned case.",
    {
      actionText: "View",
      action: () => {
        TemporaryNotification.dismiss(uuid);
      },
    },
  );
}
<goab-temporary-notification-ctrl></goab-temporary-notification-ctrl>

<goab-button (onClick)="comment()">Comment</goab-button>
const commentBtn = document.getElementById("comment-btn");
let currentUuid = null;

function showNotification(message, opts = {}) {
  const uuid = crypto.randomUUID();
  document.body.dispatchEvent(
    new CustomEvent("msg", {
      composed: true,
      bubbles: true,
      detail: {
        action: "goa:temp-notification",
        data: { message, uuid, type: "basic", duration: "short", ...opts },
      },
    }),
  );
  return uuid;
}

function dismissNotification(uuid) {
  document.body.dispatchEvent(
    new CustomEvent("msg", {
      composed: true,
      bubbles: true,
      detail: {
        action: "goa:temp-notification:dismiss",
        data: uuid,
      },
    }),
  );
}

commentBtn.addEventListener("_click", () => {
  currentUuid = showNotification("Edna Mode commented on your assigned case.", {
    actionText: "View",
    action: () => {
      dismissNotification(currentUuid);
    },
  });
});
<goa-temp-notification-ctrl></goa-temp-notification-ctrl>

<goa-button version="2" id="comment-btn">Comment</goa-button>

Show a simple progress indicator on a question page

<GoabLink leadingIcon="arrow-back" size="small" mb="none">
  Back
</GoabLink>

<GoabText tag="h3" size="body-m" mt="xl" mb="m" color="secondary">
  Question 3 of 9
</GoabText>
<GoabFormItem label="Do you currently live in Canada?" labelSize="large">
  <GoabRadioGroup
    name="canada"
    ariaLabel="Do you currently live in Canada?"
    onChange={() => {}}
  >
    <GoabRadioItem value="yes" label="Yes" />
    <GoabRadioItem value="no" label="No" />
  </GoabRadioGroup>
</GoabFormItem>

<GoabButton type="submit" mt="2xl">
  Save and continue
</GoabButton>
onRadioChange(event: GoabRadioGroupOnChangeDetail): void {
  console.log("Selected:", event.value);
}
<goab-link leadingIcon="arrow-back" size="small" mb="none"> Back </goab-link>

<goab-text tag="h3" size="body-m" mt="xl" mb="m" color="secondary"
  >Question 3 of 9</goab-text
>

<goab-form-item label="Do you currently live in Canada?" labelSize="large">
  <goab-radio-group
    name="canada"
    ariaLabel="Do you currently live in Canada?"
    (onChange)="onRadioChange($event)"
  >
    <goab-radio-item value="yes" label="Yes"></goab-radio-item>
    <goab-radio-item value="no" label="No"></goab-radio-item>
  </goab-radio-group>
</goab-form-item>

<goab-button type="submit" mt="2xl"> Save and continue </goab-button>
document.querySelector("goa-radio-group").addEventListener("_change", (e) => {
  console.log("Selected:", e.detail.value);
});
<goa-link leadingicon="arrow-back" size="small" mb="none"> Back </goa-link>

<goa-text as="h3" size="body-m" mt="xl" mb="m" color="secondary"
  >Question 3 of 9</goa-text
>

<goa-form-item version="2" label="Do you currently live in Canada?" labelsize="large">
  <goa-radio-group
    version="2"
    name="canada"
    aria-label="Do you currently live in Canada?"
  >
    <goa-radio-item value="yes" label="Yes"></goa-radio-item>
    <goa-radio-item value="no" label="No"></goa-radio-item>
  </goa-radio-group>
</goa-form-item>

<goa-button version="2" type="submit" mt="2xl"> Save and continue </goa-button>

Show a user progress

const sendApi = (
  progressCallback: (progress: number) => void,
  isCancelledRef: { current: boolean },
) => {
  return new Promise((resolve, reject) => {
    let progress = 0;
    const interval = setInterval(() => {
      if (isCancelledRef.current) {
        clearInterval(interval);
        reject("cancelled");
        return;
      }

      progress += 5;
      progressCallback(progress);

      if (progress >= 100) {
        clearInterval(interval);
        resolve("success");
      }
    }, 200);
  });
};

const downloadReport = () => {
  const isCancelledRef = { current: false };

  const uuid = TemporaryNotification.show("Downloading report D-23459", {
    type: "progress",
    actionText: "Cancel",
    action: () => {
      isCancelledRef.current = true;
      TemporaryNotification.dismiss(uuid);
      console.log("Download cancelled");
    },
  });

  TemporaryNotification.setProgress(uuid, 0);

  const updateProgress = (progress: number) => {
    TemporaryNotification.setProgress(uuid, progress);

    if (progress >= 100) {
      setTimeout(() => {
        TemporaryNotification.show("Report downloaded", {
          type: "success",
          duration: "medium",
          actionText: "View",
          action: () => {
            console.log("View report clicked!");
          },
          cancelUUID: uuid,
        });
      }, 300);
    }
  };

  sendApi(updateProgress, isCancelledRef).catch((error) => {
    if (error !== "cancelled") {
      TemporaryNotification.dismiss(uuid);
    }
  });
};
<GoabTemporaryNotificationCtrl />
<GoabButton type="tertiary" leadingIcon="download" onClick={downloadReport}>
  Download report
</GoabButton>
async downloadReportAPI(notificationUuid: string): Promise<Error | undefined> {
  // Perform your API call here with progress tracking
  // Update progress as download progresses (0-100)
  TemporaryNotification.setProgress(notificationUuid, 25);
  // ... continue API work ...
  TemporaryNotification.setProgress(notificationUuid, 50);
  // ... continue API work ...
  TemporaryNotification.setProgress(notificationUuid, 75);
  // ... complete API work ...
  TemporaryNotification.setProgress(notificationUuid, 100);
  return undefined;
}

async downloadReport(): Promise<void> {
  const uuid = TemporaryNotification.show("Downloading report D-23459", {
    type: "progress",
    actionText: "Cancel",
    action: () => {
      TemporaryNotification.dismiss(uuid);
    },
  });

  const err = await this.downloadReportAPI(uuid);

  if (err) {
    TemporaryNotification.show("Download failed", {
      type: "error",
      duration: "medium",
      cancelUUID: uuid,
    });
  } else {
    TemporaryNotification.show("Report downloaded", {
      type: "success",
      duration: "medium",
      actionText: "View",
      action: () => {
        console.log("View report clicked!");
      },
      cancelUUID: uuid,
    });
  }
}
<goab-temporary-notification-ctrl></goab-temporary-notification-ctrl>

<goab-button type="tertiary" leadingIcon="download" (onClick)="downloadReport()">
  Download report
</goab-button>
const downloadBtn = document.getElementById("download-btn");
let currentUuid = null;

function showNotification(message, opts = {}) {
  const uuid = crypto.randomUUID();
  document.body.dispatchEvent(
    new CustomEvent("msg", {
      composed: true,
      bubbles: true,
      detail: {
        action: "goa:temp-notification",
        data: { message, uuid, type: "basic", ...opts },
      },
    }),
  );
  return uuid;
}

function dismissNotification(uuid) {
  document.body.dispatchEvent(
    new CustomEvent("msg", {
      composed: true,
      bubbles: true,
      detail: {
        action: "goa:temp-notification:dismiss",
        data: uuid,
      },
    }),
  );
}

function setProgress(uuid, progress) {
  document.body.dispatchEvent(
    new CustomEvent("msg", {
      composed: true,
      bubbles: true,
      detail: {
        action: "goa:temp-notification:progress",
        data: { uuid, progress },
      },
    }),
  );
}

async function downloadReportAPI(notificationUuid) {
  setProgress(notificationUuid, 25);
  await new Promise((resolve) => setTimeout(resolve, 500));
  setProgress(notificationUuid, 50);
  await new Promise((resolve) => setTimeout(resolve, 500));
  setProgress(notificationUuid, 75);
  await new Promise((resolve) => setTimeout(resolve, 500));
  setProgress(notificationUuid, 100);
}

async function downloadReport() {
  currentUuid = showNotification("Downloading report D-23459", {
    type: "progress",
    actionText: "Cancel",
    action: () => {
      dismissNotification(currentUuid);
    },
  });

  try {
    await downloadReportAPI(currentUuid);
    showNotification("Report downloaded", {
      type: "success",
      duration: "medium",
      actionText: "View",
      action: () => {
        console.log("View report clicked!");
      },
      cancelUUID: currentUuid,
    });
  } catch (err) {
    showNotification("Download failed", {
      type: "failure",
      duration: "medium",
      cancelUUID: currentUuid,
    });
  }
}

downloadBtn.addEventListener("_click", downloadReport);
<goa-temp-notification-ctrl></goa-temp-notification-ctrl>

<goa-button version="2" id="download-btn" type="tertiary" leadingicon="download">
  Download report
</goa-button>

Show a simple progress indicator on a question page with multiple questions

<GoabLink leadingIcon="arrow-back" size="small" mb="none">
  Back
</GoabLink>

<GoabText tag="h3" size="body-m" mt="xl" mb="none" color="secondary">
  Step 1 of 5
</GoabText>
<GoabText tag="h2" mt="xs" mb="xl">
  Personal information
</GoabText>

<GoabFormItem label="What is your name?">
  <GoabInput
    onChange={() => {}}
    name="name"
    ariaLabel="what is your name?"
    width="50ch"
  />
</GoabFormItem>

<GoabFormItem label="What is your phone number?" mt="l">
  <GoabInput
    onChange={() => {}}
    name="phone-number"
    ariaLabel="what is your phone number?"
    leadingContent="+1"
  />
</GoabFormItem>

<GoabFormItem label="What is your home postal code?" mt="l">
  <GoabInput
    onChange={() => {}}
    name="postal-code"
    width="14ch"
    ariaLabel="what is your home postal code"
  />
</GoabFormItem>

<GoabButton type="submit" mt="2xl">
  Save and continue
</GoabButton>
onChange(event: GoabInputOnChangeDetail): void {
  console.log("Value:", event.value);
}
<goab-link leadingIcon="arrow-back" size="small" mb="none"> Back </goab-link>

<goab-text tag="h3" size="body-m" mt="xl" mb="none" color="secondary"
  >Step 1 of 5</goab-text
>
<goab-text tag="h2" mt="xs" mb="xl">Personal information</goab-text>

<goab-form-item label="What is your name?">
  <goab-input
    (onChange)="onChange($event)"
    name="name"
    ariaLabel="what is your name?"
    width="50ch"
  ></goab-input>
</goab-form-item>

<goab-form-item label="What is your phone number?" mt="l">
  <goab-input
    (onChange)="onChange($event)"
    name="phone-number"
    ariaLabel="what is your phone number?"
    leadingContent="+1"
  ></goab-input>
</goab-form-item>

<goab-form-item label="What is your home postal code?" mt="l">
  <goab-input
    (onChange)="onChange($event)"
    name="postal-code"
    width="14ch"
    ariaLabel="what is your home postal code"
  ></goab-input>
</goab-form-item>

<goab-button type="submit" mt="2xl"> Save and continue </goab-button>
document.querySelectorAll("goa-input").forEach((input) => {
  input.addEventListener("_change", (e) => {
    console.log(`${e.target.name}:`, e.detail.value);
  });
});
<goa-link leadingicon="arrow-back" size="small" mb="none"> Back </goa-link>

<goa-text as="h3" size="body-m" mt="xl" mb="none" color="secondary">Step 1 of 5</goa-text>
<goa-text as="h2" mt="xs" mb="xl">Personal information</goa-text>

<goa-form-item version="2" label="What is your name?">
  <goa-input
    version="2"
    name="name"
    aria-label="what is your name?"
    width="50ch"
  ></goa-input>
</goa-form-item>

<goa-form-item version="2" label="What is your phone number?" mt="l">
  <goa-input version="2" name="phone-number" aria-label="what is your phone number?">
    <div slot="leadingContent">+1</div>
  </goa-input>
</goa-form-item>

<goa-form-item version="2" label="What is your home postal code?" mt="l">
  <goa-input
    version="2"
    name="postal-code"
    width="14ch"
    aria-label="what is your home postal code"
  ></goa-input>
</goa-form-item>

<goa-button version="2" type="submit" mt="2xl"> Save and continue </goa-button>

Show a user progress when the time is unknown

const searchCMS = async (): Promise<Error | undefined> => {
  // Perform your API call here
  await new Promise((resolve) => setTimeout(resolve, 3000));
  return undefined;
};

const search = async () => {
  const uuid = TemporaryNotification.show("Searching case management system...", {
    type: "indeterminate",
    actionText: "Cancel",
    action: () => {
      TemporaryNotification.dismiss(uuid);
    },
  });

  const err = await searchCMS();
  if (err) {
    TemporaryNotification.show("Could not connect to case history", {
      type: "failure",
      duration: "medium",
      cancelUUID: uuid,
    });
  } else {
    TemporaryNotification.show("Search complete - 47 records found", {
      type: "success",
      duration: "medium",
      actionText: "View",
      action: () => {
        console.log("View search results clicked!");
      },
      cancelUUID: uuid,
    });
  }
};
<GoabTemporaryNotificationCtrl />
<GoabButton type="secondary" leadingIcon="search" onClick={search}>
  Search case history
</GoabButton>
async searchCMS(): Promise<Error | undefined> {
  // Perform your API call here
  await new Promise((resolve) => setTimeout(resolve, 3000));
  return undefined;
}

async search(): Promise<void> {
  const uuid = TemporaryNotification.show("Searching case management system...", {
    type: "indeterminate",
    actionText: "Cancel",
    action: () => {
      TemporaryNotification.dismiss(uuid);
    },
  });

  const err = await this.searchCMS();
  if (err) {
    TemporaryNotification.show("Could not connect to case history", {
      type: "failure",
      duration: "medium",
      cancelUUID: uuid,
    });
  } else {
    TemporaryNotification.show("Search complete - 47 records found", {
      type: "success",
      duration: "medium",
      actionText: "View",
      action: () => {
        console.log("View search results clicked!");
      },
      cancelUUID: uuid,
    });
  }
}
<goab-temporary-notification-ctrl></goab-temporary-notification-ctrl>

<goab-button type="secondary" leadingIcon="search" (onClick)="search()">
  Search case history
</goab-button>
const searchBtn = document.getElementById("search-btn");
let currentUuid = null;

function showNotification(message, opts = {}) {
  const uuid = crypto.randomUUID();
  document.body.dispatchEvent(
    new CustomEvent("msg", {
      composed: true,
      bubbles: true,
      detail: {
        action: "goa:temp-notification",
        data: { message, uuid, type: "basic", ...opts },
      },
    }),
  );
  return uuid;
}

function dismissNotification(uuid) {
  document.body.dispatchEvent(
    new CustomEvent("msg", {
      composed: true,
      bubbles: true,
      detail: {
        action: "goa:temp-notification:dismiss",
        data: uuid,
      },
    }),
  );
}

async function searchCMS() {
  await new Promise((resolve) => setTimeout(resolve, 3000));
}

async function search() {
  currentUuid = showNotification("Searching case management system...", {
    type: "indeterminate",
    actionText: "Cancel",
    action: () => {
      dismissNotification(currentUuid);
    },
  });

  try {
    await searchCMS();
    showNotification("Search complete - 47 records found", {
      type: "success",
      duration: "medium",
      actionText: "View",
      action: () => {
        console.log("View search results clicked!");
      },
      cancelUUID: currentUuid,
    });
  } catch (err) {
    showNotification("Could not connect to case history", {
      type: "failure",
      duration: "medium",
      cancelUUID: currentUuid,
    });
  }
}

searchBtn.addEventListener("_click", search);
<goa-temp-notification-ctrl></goa-temp-notification-ctrl>

<goa-button version="2" id="search-btn" type="secondary" leadingicon="search">
  Search case history
</goa-button>

Show different views of data in a table

const review = [0, 1, 2, 3];
const complete = [0, 1];
<GoabTabs initialTab={1}>
  <GoabTab heading="All">
    <GoabTable width="100%">
      <thead>
        <tr>
          <th>Status</th>
          <th>Text</th>
          <th className="goa-table-number-header">Number</th>
          <th style={{ width: "1%", whiteSpace: "nowrap" }}>Action</th>
        </tr>
      </thead>
      <tbody>
        {review.map((i) => (
          <tr key={`review-${i}`}>
            <td>
              <GoabBadge type="important" content="Review pending" />
            </td>
            <td>Lorem Ipsum</td>
            <td className="goa-table-number-column">1234567890</td>
            <td>
              <GoabButton type="tertiary" size="compact">
                Action
              </GoabButton>
            </td>
          </tr>
        ))}
        {complete.map((i) => (
          <tr key={`complete-${i}`}>
            <td>
              <GoabBadge type="information" content="Complete" />
            </td>
            <td>Lorem Ipsum</td>
            <td className="goa-table-number-column">1234567890</td>
            <td>
              <GoabButton type="tertiary" size="compact">
                Action
              </GoabButton>
            </td>
          </tr>
        ))}
      </tbody>
    </GoabTable>
  </GoabTab>
  <GoabTab
    heading={
        Review pending
        <GoabBadge type="important" content="4" icon={false} />
    }
  >
    <GoabTable width="100%">
      <thead>
        <tr>
          <th>Status</th>
          <th>Text</th>
          <th className="goa-table-number-header">Number</th>
          <th style={{ width: "1%", whiteSpace: "nowrap" }}>Action</th>
        </tr>
      </thead>
      <tbody>
        {review.map((i) => (
          <tr key={i}>
            <td>
              <GoabBadge type="important" content="Review pending" />
            </td>
            <td>Lorem Ipsum</td>
            <td className="goa-table-number-column">1234567890</td>
            <td>
              <GoabButton type="tertiary" size="compact">
                Action
              </GoabButton>
            </td>
          </tr>
        ))}
      </tbody>
    </GoabTable>
  </GoabTab>
  <GoabTab
    heading={
      <>
        Complete
        <GoabBadge type="information" content="338" icon={false} />
      </>
    }
  >
    <GoabTable width="100%">
      <thead>
        <tr>
          <th>Status</th>
          <th>Text</th>
          <th className="goa-table-number-header">Number</th>
          <th style={{ width: "1%", whiteSpace: "nowrap" }}>Action</th>
        </tr>
      </thead>
      <tbody>
        {complete.map((i) => (
          <tr key={i}>
            <td>
              <GoabBadge type="information" content="Complete" />
            </td>
            <td>Lorem Ipsum</td>
            <td className="goa-table-number-column">1234567890</td>
            <td>
              <GoabButton type="tertiary" size="compact">
                Action
              </GoabButton>
            </td>
          </tr>
        ))}
      </tbody>
    </GoabTable>
  </GoabTab>
</GoabTabs>
reviewItems = [0, 1, 2, 3];
completeItems = [0, 1];
<goab-tabs>
  <goab-tab heading="All">
    <goab-table width="100%">
      <thead>
        <tr>
          <th>Status</th>
          <th>Text</th>
          <th class="goa-table-number-header">Number</th>
          <th style="width: 1%; white-space: nowrap">Action</th>
        </tr>
      </thead>
      <tbody>
        @for (i of reviewItems; track $index) {
        <tr>
          <td><goab-badge type="important" content="Review pending"></goab-badge></td>
          <td>Lorem ipsum</td>
          <td class="goa-table-number-column">1234567890</td>
          <td><goab-button type="tertiary" size="compact">Action</goab-button></td>
        </tr>
        } @for (i of completeItems; track $index) {
        <tr>
          <td><goab-badge type="information" content="Complete"></goab-badge></td>
          <td>Lorem Ipsum</td>
          <td class="goa-table-number-column">1234567890</td>
          <td><goab-button type="tertiary" size="compact">Action</goab-button></td>
        </tr>
        }
      </tbody>
    </goab-table>
  </goab-tab>
  <goab-tab [heading]="reviewPending">
    <ng-template #reviewPending
      >Review pending<goab-badge type="important" content="4" [icon]="false"></goab-badge
    ></ng-template>
    <goab-table width="100%">
      <thead>
        <tr>
          <th>Status</th>
          <th>Text</th>
          <th class="goa-table-number-header">Number</th>
          <th style="width: 1%; white-space: nowrap">Action</th>
        </tr>
      </thead>
      <tbody>
        @for (i of reviewItems; track $index) {
        <tr>
          <td><goab-badge type="important" content="Review pending"></goab-badge></td>
          <td>Lorem ipsum</td>
          <td class="goa-table-number-column">1234567890</td>
          <td><goab-button type="tertiary" size="compact">Action</goab-button></td>
        </tr>
        }
      </tbody>
    </goab-table>
  </goab-tab>
  <goab-tab [heading]="completeTab">
    <ng-template #completeTab
      >Complete<goab-badge type="information" content="338" [icon]="false"></goab-badge
    ></ng-template>
    <goab-table width="100%">
      <thead>
        <tr>
          <th>Status</th>
          <th>Text</th>
          <th class="goa-table-number-header">Number</th>
          <th style="width: 1%; white-space: nowrap">Action</th>
        </tr>
      </thead>
      <tbody>
        @for (i of completeItems; track $index) {
        <tr>
          <td><goab-badge type="information" content="Complete"></goab-badge></td>
          <td>Lorem Ipsum</td>
          <td class="goa-table-number-column">1234567890</td>
          <td><goab-button type="tertiary" size="compact">Action</goab-button></td>
        </tr>
        }
      </tbody>
    </goab-table>
  </goab-tab>
</goab-tabs>
<goa-tabs version="2">
  <goa-tab>
    <div slot="heading">All</div>
    <goa-table version="2" width="100%">
      <table width="100%">
        <thead>
          <tr>
            <th>Status</th>
            <th>Text</th>
            <th class="goa-table-number-header">Number</th>
            <th style="width: 1%; white-space: nowrap">Action</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>
              <goa-badge
                version="2"
                type="important"
                content="Review pending"
              ></goa-badge>
            </td>
            <td>Lorem ipsum</td>
            <td class="goa-table-number-column">1234567890</td>
            <td>
              <goa-button version="2" type="tertiary" size="compact">Action</goa-button>
            </td>
          </tr>
          <tr>
            <td>
              <goa-badge
                version="2"
                type="important"
                content="Review pending"
              ></goa-badge>
            </td>
            <td>Lorem ipsum</td>
            <td class="goa-table-number-column">1234567890</td>
            <td>
              <goa-button version="2" type="tertiary" size="compact">Action</goa-button>
            </td>
          </tr>
          <tr>
            <td>
              <goa-badge version="2" type="information" content="Complete"></goa-badge>
            </td>
            <td>Lorem Ipsum</td>
            <td class="goa-table-number-column">1234567890</td>
            <td>
              <goa-button version="2" type="tertiary" size="compact">Action</goa-button>
            </td>
          </tr>
        </tbody>
      </table>
    </goa-table>
  </goa-tab>
  <goa-tab>
    <div slot="heading">
      Review pending<goa-badge
        version="2"
        type="important"
        content="4"
        icon="false"
      ></goa-badge>
    </div>
    <goa-table version="2" width="100%">
      <table width="100%">
        <thead>
          <tr>
            <th>Status</th>
            <th>Text</th>
            <th class="goa-table-number-header">Number</th>
            <th style="width: 1%; white-space: nowrap">Action</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>
              <goa-badge
                version="2"
                type="important"
                content="Review pending"
              ></goa-badge>
            </td>
            <td>Lorem ipsum</td>
            <td class="goa-table-number-column">1234567890</td>
            <td>
              <goa-button version="2" type="tertiary" size="compact">Action</goa-button>
            </td>
          </tr>
          <tr>
            <td>
              <goa-badge
                version="2"
                type="important"
                content="Review pending"
              ></goa-badge>
            </td>
            <td>Lorem ipsum</td>
            <td class="goa-table-number-column">1234567890</td>
            <td>
              <goa-button version="2" type="tertiary" size="compact">Action</goa-button>
            </td>
          </tr>
        </tbody>
      </table>
    </goa-table>
  </goa-tab>
  <goa-tab>
    <div slot="heading">
      Complete<goa-badge
        version="2"
        type="information"
        content="338"
        icon="false"
      ></goa-badge>
    </div>
    <goa-table version="2" width="100%">
      <table width="100%">
        <thead>
          <tr>
            <th>Status</th>
            <th>Text</th>
            <th class="goa-table-number-header">Number</th>
            <th style="width: 1%; white-space: nowrap">Action</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>
              <goa-badge version="2" type="information" content="Complete"></goa-badge>
            </td>
            <td>Lorem Ipsum</td>
            <td class="goa-table-number-column">1234567890</td>
            <td>
              <goa-button version="2" type="tertiary" size="compact">Action</goa-button>
            </td>
          </tr>
        </tbody>
      </table>
    </goa-table>
  </goa-tab>
</goa-tabs>

Show more information to help answer a question

<GoabLink leadingIcon="arrow-back" size="small" mb="none">
  Back
</GoabLink>

<GoabFormItem
  mt="xl"
  label="Do you pay for child care?"
  labelSize="large"
  helpText="Examples of child care are daycares, day homes and baby-sisters."
>
  <GoabRadioGroup
    name="child-care"
    ariaLabel="Do you pay for child care?"
    onChange={() => {}}
  >
    <GoabRadioItem value="yes" label="Yes" />
    <GoabRadioItem value="no" label="No" />
  </GoabRadioGroup>
</GoabFormItem>

<GoabDetails heading="Why are we asking this question?" mt="l">
  <p>
    We ask this question to determine if you are eligible for child care benefits.
  </p>
</GoabDetails>

<GoabButton type="submit" mt="2xl">
  Save and continue
</GoabButton>
onRadioChange(event: GoabRadioGroupOnChangeDetail): void {
  console.log("Radio changed:", event.value);
}
<goab-link leadingIcon="arrow-back" size="small" mb="none"> Back </goab-link>

<goab-form-item
  mt="xl"
  label="Do you pay for child care?"
  labelSize="large"
  helpText="Examples of child care are daycares, day homes and baby-sisters."
>
  <goab-radio-group
    name="child-care"
    ariaLabel="Do you pay for child care?"
    (onChange)="onRadioChange($event)"
  >
    <goab-radio-item value="yes" label="Yes"></goab-radio-item>
    <goab-radio-item value="no" label="No"></goab-radio-item>
  </goab-radio-group>
</goab-form-item>

<goab-details heading="Why are we asking this question?" mt="l">
  <p>We ask this question to determine if you are eligible for child care benefits.</p>
</goab-details>

<goab-button type="submit" mt="2xl">Save and continue</goab-button>
<goa-link leadingicon="arrow-back" size="small" mb="none"> Back </goa-link>

<goa-form-item
  version="2"
  mt="xl"
  label="Do you pay for child care?"
  labelsize="large"
  helptext="Examples of child care are daycares, day homes and baby-sisters."
>
  <goa-radio-group version="2" name="child-care" arialabel="Do you pay for child care?">
    <goa-radio-item value="yes" label="Yes"></goa-radio-item>
    <goa-radio-item value="no" label="No"></goa-radio-item>
  </goa-radio-group>
</goa-form-item>

<goa-details heading="Why are we asking this question?" mt="l">
  <p>We ask this question to determine if you are eligible for child care benefits.</p>
</goa-details>

<goa-button version="2" type="submit" mt="2xl">Save and continue</goa-button>

Show status in a table

interface BadgeValue {
  key: number;
  type: GoabBadgeType;
  content: string;
}

const badgeValues: BadgeValue[] = [
  { key: 1, type: "important", content: "Pending" },
  { key: 2, type: "emergency", content: "Failed" },
  { key: 3, type: "success", content: "Complete" },
  { key: 4, type: "information", content: "In progress" },
  { key: 5, type: "default", content: "Closed" },
  { key: 6, type: "success", content: "Complete" },
];

const handleClick = () => {
  console.log("clicked");
};
<GoabTable width="100%">
  <thead>
    <tr>
      <th>Status</th>
      <th>Name</th>
      <th className="goa-table-number-header">File number</th>
      <th style={{ width: "1%", whiteSpace: "nowrap" }}></th>
    </tr>
  </thead>
  <tbody>
    {badgeValues.map((badge) => (
      <tr key={badge.key}>
        <td>
          <GoabBadge type={badge.type} content={badge.content} icon={false} />
        </td>
        <td>Lorem ipsum dolor sit amet consectetur</td>
        <td className="goa-table-number-column">1234567890</td>
        <td>
          <GoabButton size="compact" type="tertiary" onClick={handleClick}>
            Assign
          </GoabButton>
        </td>
      </tr>
    ))}
  </tbody>
</GoabTable>
badgeValues: BadgeValue[] = [
  { type: "important", content: "Pending" },
  { type: "emergency", content: "Failed" },
  { type: "success", content: "Complete" },
  { type: "information", content: "In progress" },
  { type: "default", content: "Closed" },
  { type: "success", content: "Complete" },
];

onClick(): void {
  console.log("clicked");
}
<goab-table width="100%">
  <thead>
    <tr>
      <th>Status</th>
      <th>Name</th>
      <th class="goa-table-number-header">File number</th>
      <th style="width: 1%; white-space: nowrap"></th>
    </tr>
  </thead>
  <tbody>
    @for (badge of badgeValues; track $index) {
    <tr>
      <td>
        <goab-badge
          [type]="badge.type"
          [content]="badge.content"
          [icon]="false"
        ></goab-badge>
      </td>
      <td>Lorem ipsum dolor sit amet consectetur.</td>
      <td class="goa-table-number-column">1234567890</td>
      <td>
        <goab-button size="compact" type="tertiary" (onClick)="onClick()"
          >Assign</goab-button
        >
      </td>
    </tr>
    }
  </tbody>
</goab-table>
const badgeValues = [
  { type: "important", content: "Pending" },
  { type: "emergency", content: "Failed" },
  { type: "success", content: "Complete" },
  { type: "information", content: "In progress" },
  { type: "default", content: "Closed" },
  { type: "success", content: "Complete" },
];

const tbody = document.getElementById("table-body");

badgeValues.forEach((badge) => {
  const row = document.createElement("tr");
  row.innerHTML = `
    <td><goa-badge version="2" type="${badge.type}" content="${badge.content}" icon="false"></goa-badge></td>
    <td>Lorem ipsum dolor sit amet consectetur</td>
    <td class="goa-table-number-column">1234567890</td>
    <td><goa-button version="2" size="compact" type="tertiary">Assign</goa-button></td>
  `;
  const button = row.querySelector("goa-button");
  button.addEventListener("_click", () => console.log("clicked"));
  tbody.appendChild(row);
});
<goa-table version="2" width="100%" id="status-table">
  <table width="100%">
    <thead>
      <tr>
        <th>Status</th>
        <th>Name</th>
        <th class="goa-table-number-header">File number</th>
        <th style="width: 1%; white-space: nowrap"></th>
      </tr>
    </thead>
    <tbody id="table-body"></tbody>
  </table>
</goa-table>

Start page

const handleClick = () => {
  console.log("Get started clicked");
};
<GoabText size="heading-xl" mt="none" mb="l">
  Name of service
</GoabText>
<GoabText size="body-l" mt="none" mb="none">
  A short overview of the service. This is a couple sentences that helps the user
  understand what the service is.
</GoabText>
<GoabText size="body-m" mt="l" mb="s">
  Use this service to apply for [service]. You can use this service to:
</GoabText>
<ul>
  <li>see if you or a family member is eligible for [service]</li>
  <li>create and submit an application for [service]</li>
  <li>continue an application for [service] that you already started</li>
</ul>

<GoabText size="heading-l" mt="xl" mb="none">
  Before you begin
</GoabText>
<GoabText size="body-m" mt="l" mb="none">
  The application form should take about 20 minutes to complete.
</GoabText>
<GoabText size="body-m" mt="l" mb="none">
  <strong>In order to complete the application you will need:</strong>
</GoabText>
<ul>
  <li>government issued ID for the person applying</li>
</ul>
<GoabButton mt="2xl" mb="xl" type="start" onClick={handleClick}>
  Get started
</GoabButton>

<GoabText size="heading-l" mt="xl" mb="none">
  Other information about the service
</GoabText>
<GoabText size="body-m" mt="l" mb="none">
  This section contains supplementary details about the service, including
  descriptions of less common scenarios, exceptions, and additional resources
  available. It provides context and additional insights that may be relevant to
  your specific circumstances or interests, helping you understand the full scope
  and utility of the service offered.
</GoabText>

<GoabText size="heading-l" mt="xl" mb="none">
  Support
</GoabText>
<GoabText size="body-m" mt="l" mb="none">
  For assistance, email us at <a href="mailto:help@gov.ab.ca">help@gov.ab.ca</a>
</GoabText>
onClick(): void {
  console.log("Get started clicked");
}
<goab-text size="heading-xl" mt="none" mb="l">Name of service</goab-text>
<goab-text size="body-l" mt="none" mb="none">
  A short overview of the service. This is a couple sentences that helps the user
  understand what the service is.
</goab-text>
<goab-text size="body-m" mt="l" mb="s"
  >Use this service to apply for [service]. You can use this service to:</goab-text
>
<ul>
  <li>see if you or a family member is eligible for [service]</li>
  <li>create and submit an application for [service]</li>
  <li>continue an application for [service] that you already started</li>
</ul>

<goab-text size="heading-l" mt="xl" mb="none">Before you begin</goab-text>
<goab-text size="body-m" mt="l" mb="none"
  >The application form should take about 20 minutes to complete.</goab-text
>
<goab-text size="body-m" mt="l" mb="none">
  <strong>In order to complete the application you will need:</strong>
</goab-text>
<ul>
  <li>government issued ID for the person applying</li>
</ul>
<goab-button mt="2xl" mb="xl" type="start" (onClick)="onClick()">
  Get started
</goab-button>

<goab-text size="heading-l" mt="xl" mb="none"
  >Other information about the service</goab-text
>
<goab-text size="body-m" mt="l" mb="none">
  This section contains supplementary details about the service, including descriptions of
  less common scenarios, exceptions, and additional resources available. It provides
  context and additional insights that may be relevant to your specific circumstances or
  interests, helping you understand the full scope and utility of the service offered.
</goab-text>

<goab-text size="heading-l" mt="xl" mb="none">Support</goab-text>
<goab-text size="body-m" mt="l" mb="none">
  For assistance, email us at <a href="mailto:help@gov.ab.ca">help&#64;gov.ab.ca</a>
</goab-text>
document.getElementById("start-btn").addEventListener("_click", () => {
  console.log("Get started clicked");
});
<goa-text size="heading-xl" mt="none" mb="l">Name of service</goa-text>
<goa-text size="body-l" mt="none" mb="none">
  A short overview of the service. This is a couple sentences that helps the user
  understand what the service is.
</goa-text>
<goa-text size="body-m" mt="l" mb="s"
  >Use this service to apply for [service]. You can use this service to:</goa-text
>
<ul>
  <li>see if you or a family member is eligible for [service]</li>
  <li>create and submit an application for [service]</li>
  <li>continue an application for [service] that you already started</li>
</ul>

<goa-text size="heading-l" mt="xl" mb="none">Before you begin</goa-text>
<goa-text size="body-m" mt="l" mb="none"
  >The application form should take about 20 minutes to complete.</goa-text
>
<goa-text size="body-m" mt="l" mb="none">
  <strong>In order to complete the application you will need:</strong>
</goa-text>
<ul>
  <li>government issued ID for the person applying</li>
</ul>
<goa-button version="2" mt="2xl" mb="xl" type="start" id="start-btn"
  >Get started</goa-button
>

<goa-text size="heading-l" mt="xl" mb="none"
  >Other information about the service</goa-text
>
<goa-text size="body-m" mt="l" mb="none">
  This section contains supplementary details about the service, including descriptions of
  less common scenarios, exceptions, and additional resources available. It provides
  context and additional insights that may be relevant to your specific circumstances or
  interests, helping you understand the full scope and utility of the service offered.
</goa-text>

<goa-text size="heading-l" mt="xl" mb="none">Support</goa-text>
<goa-text size="body-m" mt="l" mb="none">
  For assistance, email us at <a href="mailto:help@gov.ab.ca">help@gov.ab.ca</a>
</goa-text>

Warn a user of a deadline

const [open, setOpen] = useState(false);
      <GoabButton type="secondary" onClick={() => setOpen(true)}>
        Save for later
      </GoabButton>
      <GoabModal
        heading="Complete submission prior to 1PM"
        calloutVariant="important"
        open={open}
        onClose={() => setOpen(false)}
        actions={
          <GoabButtonGroup alignment="end">
            <GoabButton type="primary" onClick={() => setOpen(false)}>
              I understand
            </GoabButton>
          </GoabButtonGroup>
        }
      >
        <p>
          You've selected to adjourn a matter that is required to appear today. This
          Calgary court location does not accept adjournment requests past 1PM MST. Please
          submit your adjournment request as soon as possible.
        </p>
      </GoabModal>
  );
}
open = false;

toggleModal(): void {
  this.open = !this.open;
}
<goab-button type="secondary" (onClick)="toggleModal()">Save for later</goab-button>
<goab-modal
  [open]="open"
  calloutVariant="important"
  (onClose)="toggleModal()"
  heading="Complete submission prior to 1PM"
  [actions]="actions"
>
  <p>
    You've selected to adjourn a matter that is required to appear today. This Calgary
    court location does not accept adjournment requests past 1PM MST. Please submit your
    adjournment request as soon as possible.
  </p>
  <ng-template #actions>
    <goab-button-group alignment="end">
      <goab-button type="primary" (onClick)="toggleModal()">I understand</goab-button>
    </goab-button-group>
  </ng-template>
</goab-modal>
const modal = document.getElementById("deadline-modal");
const openBtn = document.getElementById("open-modal-btn");
const understandBtn = document.getElementById("understand-btn");

openBtn.addEventListener("_click", () => {
  modal.setAttribute("open", "true");
});

understandBtn.addEventListener("_click", () => {
  modal.removeAttribute("open");
});

modal.addEventListener("_close", () => {
  modal.removeAttribute("open");
});
<goa-button version="2" type="secondary" id="open-modal-btn">Save for later</goa-button>
<goa-modal
  version="2"
  id="deadline-modal"
  calloutvariant="important"
  heading="Complete submission prior to 1PM"
>
  You've selected to adjourn a matter that is required to appear today. This Calgary court
  location does not accept adjournment requests past 1PM MST. Please submit your
  adjournment request as soon as possible.
  <div slot="actions">
    <goa-button-group alignment="end">
      <goa-button version="2" type="primary" size="compact" id="understand-btn"
        >I understand</goa-button
      >
    </goa-button-group>
  </div>
</goa-modal>

Workspace

Preview not available
No React code available

States

Submit

Only use disabled buttons if research shows it makes the user interface easier to understand.

Consider removing options that are unavailable or not applicable. Show actions that are only relevant and useful to the user at a given time.

Avoid using disabled buttons. They have poor contrast and can confuse users.

Instead of disabling a submit button, keep it enabled and provide clear feedback about any missed fields or input errors when the user tries to submit the form.

Keep buttons enabled and use error handling to provide clear feedback when the user submits.
Submit

When you must disable a button or input:

  • Provide nearby text explaining what needs to happen first
  • Consider showing the element enabled with validation on submit instead
  • Use aria-describedby to link the disabled element to explanatory text
Don't disable buttons or inputs without explaining why. Disabled controls can be confusing and users may not understand why they can't interact with an element.

Sizing

Edit
Use compact buttons in dense spaces like tables or container title bars.
CancelSave
Don't stack standard and full width buttons.
SaveCancel
Don't use different button sizes in the same area to emphasize hierarchy.
SaveCancel
Use full width buttons on mobile.

Content

SubmitCancel
Use one word to explain the function whenever possible, such as "Save", "Submit", or "Search".
Cancel application
Use descriptive language in both modal content and button text to inform users of the resulting destructive action.
SUBMITcancel
Don't use all uppercase or all lowercase to label buttons.
Submit applicationSave draftCancel
Button labels should clearly describe what happens when clicked. Use specific verbs like "Submit application" or "Save draft" instead of generic labels like "OK" or "Click here".

Types

Button types
  • Primary - If there is only one button on a page, it should be a primary button. For citizen facing applications, generally there should only be one primary button on a page.
  • Secondary - Use secondary buttons for less important actions on a page. Often paired with a primary action as a secondary action.
  • Tertiary - Use tertiary buttons for links that should function like a button, such as “edit” or “cancel” in applications. It’s okay to use more than one tertiary button on a page.
Delete account
Use the destructive button variant for actions that cannot be easily undone, like permanently deleting data or removing a user from a system.
Delete record
Don't use a destructive button to trigger a confirmation. Reserve destructive styling for the final action inside the modal.
SaveSubmitContinue
Avoid using more than one primary button per page. Multiple primary buttons create visual competition and make it unclear which action is most important.
SaveCancel
Use a primary button for main actions and a secondary button for less important actions.
Submit form

This distinction matters for screen reader users who expect different behaviors, keyboard navigation patterns, and browser history.

Use a button for actions that trigger functionality (submit, save, cancel). Use a link for navigation to different pages or external websites.
Submit application
Use a button when you need users to take a specific action, such as submitting a form, starting a process, or confirming a decision.
Go to homepage
Don't use Button for simple navigation (use Link), toggling state (use Toggle or Checkbox), or minor utility functions (use Icon Button).

Icons

Add item
Use icons with a clear visual association to the action.
Confirm
Don't use icons that don't have a clear visual association to the intended outcome.
Add new
Use a text label with an icon, especially for public-facing applications and novice users.

Positioning

SubmitEditSaveCopyDraft
Don't group more than 3 actions together. Consider using an overflow menu for additional options.
SubmitCancel
Use a button group when putting multiple buttons together.

Other

Use Link for navigation to other pages. Use Button for actions that change state or trigger functionality.
All GoA Design System components are built to meet WCAG 2.2 AA standards. The following guidelines provide additional context for accessible implementation.

Screen Readers

For icon buttons with both a label and icon, hide the icon from the screen reader so it announces “Button, add row” not “Button, cross icon, add row”.

Don't read the icon class or description for icon buttons with labels. Screen readers should read the button label only.
Icon-only buttons must include a descriptive label for screen readers.

Focus

Don't focus on just the icon within a button. Focus the button as a whole.
View old component docs