Block

Group components into a block with consistent space between.

Props

gap
Spacing
Spacing between items. Uses design system spacing tokens.
Defaults to m.
direction
row | column
Stacking direction of child components.
Defaults to row.
alignment
center | start | end | normal
Primary axis alignment of child components.
Defaults to normal.
testId
string
Sets a data-testid attribute for automated testing.
minWidth
string
Sets the minimum width of the block container.
maxWidth
string
Sets the maximum width of the block container.
width
string
Sets the width of the block container. Defaults to max-content.
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.
Examples

Add a record using a drawer

const [open, setOpen] = useState(false);
<GoabxButton leadingIcon="add" onClick={() => setOpen(true)}>
        Add Record
      </GoabxButton>
      <GoabxDrawer
        maxSize="492px"
        open={open}
        heading="Add Record"
        position="right"
        onClose={() => setOpen(false)}
        actions={
          <GoabButtonGroup>
            <GoabxButton type="primary" size="compact" onClick={() => setOpen(false)}>
              Add record
            </GoabxButton>
            <GoabxButton type="tertiary" size="compact" onClick={() => setOpen(false)}>
              Cancel
            </GoabxButton>
          </GoabButtonGroup>
        }
      >
        <GoabxFormItem label="Level of education">
          <GoabxDropdown onChange={() => {}} name="education" value="university">
            <GoabxDropdownItem value="high-school" label="High School Diploma" />
            <GoabxDropdownItem value="college" label="College Diploma" />
            <GoabxDropdownItem value="university" label="University Degree" />
            <GoabxDropdownItem value="masters" label="Master's Degree" />
            <GoabxDropdownItem value="doctorate" label="Doctorate" />
          </GoabxDropdown>
        </GoabxFormItem>
        <GoabxFormItem label="Educational institution" mt="l">
          <GoabxInput name="education" type="text" onChange={() => {}} />
        </GoabxFormItem>
        <GoabxFormItem label="Field of study" requirement="optional" mt="l">
          <GoabxInput name="fieldOfStudy" type="text" onChange={() => {}} />
        </GoabxFormItem>
        <GoabxFormItem label="Is the person currently attending?" mt="l">
          <GoabxRadioGroup name="attendTraining" orientation="horizontal" onChange={() => {}}>
            <GoabxRadioItem value="yes" label="Yes" />
            <GoabxRadioItem value="no" label="No" />
          </GoabxRadioGroup>
        </GoabxFormItem>
        <GoabxFormItem label="Start date" mt="l">
          <GoabxDatePicker onChange={() => {}} value={new Date("2022-09-01")} />
          <GoabxCheckbox name="startDateApproximate" text="Approximate date" value="y" mt="s" />
        </GoabxFormItem>
        <GoabxFormItem label="Credential received?" mt="l">
          <GoabxRadioGroup name="credentialReceived" orientation="horizontal" onChange={() => {}}>
            <GoabxRadioItem value="yes" label="Yes" />
            <GoabxRadioItem value="no" label="No" />
          </GoabxRadioGroup>
        </GoabxFormItem>
      </GoabxDrawer>
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;
  }
<goabx-button leadingIcon="add" (onClick)="onClick()">Add Record</goabx-button>
<goabx-drawer maxSize="492px" [open]="open" heading="Add Record" position="right" (onClose)="onClose()" [actions]="actions">
  <goabx-form-item label="Level of education">
    <goabx-dropdown (onChange)="dropdownOnChange($event)" name="education" value="university">
      <goabx-dropdown-item value="high-school" label="High School Diploma"></goabx-dropdown-item>
      <goabx-dropdown-item value="college" label="College Diploma"></goabx-dropdown-item>
      <goabx-dropdown-item value="university" label="University Degree"></goabx-dropdown-item>
      <goabx-dropdown-item value="masters" label="Master's Degree"></goabx-dropdown-item>
      <goabx-dropdown-item value="doctorate" label="Doctorate"></goabx-dropdown-item>
    </goabx-dropdown>
  </goabx-form-item>
  <goabx-form-item label="Educational institution" mt="l">
    <goabx-input name="education" type="text" (onChange)="inputOnChange($event)"></goabx-input>
  </goabx-form-item>
  <goabx-form-item label="Field of study" requirement="optional" mt="l">
    <goabx-input name="fieldOfStudy" type="text" (onChange)="inputOnChange($event)"></goabx-input>
  </goabx-form-item>
  <goabx-form-item label="Is the person currently attending?" mt="l">
    <goabx-radio-group name="attendTraining" orientation="horizontal" (onChange)="radioOnChange($event)">
      <goabx-radio-item value="yes" label="Yes"></goabx-radio-item>
      <goabx-radio-item value="no" label="No"></goabx-radio-item>
    </goabx-radio-group>
  </goabx-form-item>
  <goabx-form-item label="Start date" mt="l">
    <goabx-date-picker (onChange)="dateOnChange($event)"></goabx-date-picker>
    <goabx-checkbox name="startDateApproximate" text="Approximate date" value="y" mt="s"></goabx-checkbox>
  </goabx-form-item>
  <goabx-form-item label="Credential received?" mt="l">
    <goabx-radio-group name="credentialReceived" orientation="horizontal" (onChange)="radioOnChange($event)">
      <goabx-radio-item value="yes" label="Yes"></goabx-radio-item>
      <goabx-radio-item value="no" label="No"></goabx-radio-item>
    </goabx-radio-group>
  </goabx-form-item>
  <ng-template #actions>
    <goab-button-group>
      <goabx-button type="primary" size="compact" (onClick)="closeDrawer()">Add record</goabx-button>
      <goabx-button type="tertiary" size="compact" (onClick)="closeDrawer()">Cancel</goabx-button>
    </goab-button-group>
  </ng-template>
</goabx-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>
      <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>

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>
      <GoabxFormItem label="Street Address">
        <GoabxInput
          name="address"
          type="text"
          value={address}
          onChange={(e) => setAddress(e.value)}
          width="100%"
        />
      </GoabxFormItem>
      <GoabxFormItem label="Suite or unit #" mt="l">
        <GoabxInput
          name="suite"
          type="text"
          value={suite}
          onChange={(e) => setSuite(e.value)}
          width="100%"
        />
      </GoabxFormItem>
      <GoabxFormItem label="City or town" mt="l">
        <GoabxInput
          name="city"
          type="text"
          value={city}
          onChange={(e) => setCity(e.value)}
          width="100%"
        />
      </GoabxFormItem>
      <GoabBlock direction="row" gap="l" mt="l">
        <GoabxFormItem label="Province or territory">
          <GoabxDropdown
            onChange={(e) => setProvince(e.value ?? "")}
            name="province"
            value={province}
          >
            <GoabxDropdownItem label="Alberta" value="AB" />
            <GoabxDropdownItem label="British Columbia" value="BC" />
            <GoabxDropdownItem label="Manitoba" value="MB" />
            <GoabxDropdownItem label="New Brunswick" value="NB" />
            <GoabxDropdownItem label="Newfoundland and Labrador" value="NL" />
            <GoabxDropdownItem label="Northwest Territories" value="NT" />
            <GoabxDropdownItem label="Nova Scotia" value="NS" />
            <GoabxDropdownItem label="Nunavut" value="NU" />
            <GoabxDropdownItem label="Ontario" value="ON" />
            <GoabxDropdownItem label="Prince Edward Island" value="PE" />
            <GoabxDropdownItem label="Quebec" value="QC" />
            <GoabxDropdownItem label="Saskatchewan" value="SK" />
            <GoabxDropdownItem label="Yukon" value="YT" />
          </GoabxDropdown>
        </GoabxFormItem>
        <GoabxFormItem label="Postal Code">
          <GoabxInput
            name="postalCode"
            type="text"
            value={postalCode}
            onChange={(e) => setPostalCode(e.value)}
            width="7ch"
          />
        </GoabxFormItem>
      </GoabBlock>
      <GoabButtonGroup alignment="start" mt="2xl">
        <GoabxButton type="primary" onClick={() => {}}>
          Save and continue
        </GoabxButton>
        <GoabxButton type="secondary" onClick={() => {}}>
          Cancel
        </GoabxButton>
      </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>
<goabx-form-item label="Street Address">
  <goabx-input name="address" type="text" [formControl]="form.controls.address" width="100%"></goabx-input>
</goabx-form-item>
<goabx-form-item label="Suite or unit #" mt="l">
  <goabx-input name="suite" type="text" [formControl]="form.controls.suite" width="100%"></goabx-input>
</goabx-form-item>
<goabx-form-item label="City or town" mt="l">
  <goabx-input name="city" type="text" [formControl]="form.controls.city" width="100%"></goabx-input>
</goabx-form-item>
<goab-block direction="row" gap="l" mt="l">
  <goabx-form-item label="Province or territory">
    <goabx-dropdown name="province" [formControl]="form.controls.province">
      <goabx-dropdown-item label="Alberta" value="AB"></goabx-dropdown-item>
      <goabx-dropdown-item label="British Columbia" value="BC"></goabx-dropdown-item>
      <goabx-dropdown-item label="Manitoba" value="MB"></goabx-dropdown-item>
      <goabx-dropdown-item label="New Brunswick" value="NB"></goabx-dropdown-item>
      <goabx-dropdown-item label="Newfoundland and Labrador" value="NL"></goabx-dropdown-item>
      <goabx-dropdown-item label="Northwest Territories" value="NT"></goabx-dropdown-item>
      <goabx-dropdown-item label="Nova Scotia" value="NS"></goabx-dropdown-item>
      <goabx-dropdown-item label="Nunavut" value="NU"></goabx-dropdown-item>
      <goabx-dropdown-item label="Ontario" value="ON"></goabx-dropdown-item>
      <goabx-dropdown-item label="Prince Edward Island" value="PE"></goabx-dropdown-item>
      <goabx-dropdown-item label="Quebec" value="QC"></goabx-dropdown-item>
      <goabx-dropdown-item label="Saskatchewan" value="SK"></goabx-dropdown-item>
      <goabx-dropdown-item label="Yukon" value="YT"></goabx-dropdown-item>
    </goabx-dropdown>
  </goabx-form-item>
  <goabx-form-item label="Postal Code">
    <goabx-input name="postalCode" type="text" [formControl]="form.controls.postalCode" width="7ch"></goabx-input>
  </goabx-form-item>
</goab-block>
<goab-button-group alignment="start" mt="2xl">
  <goabx-button type="primary" (onClick)="onClick()">Save and continue</goabx-button>
  <goabx-button type="secondary" (onClick)="onClick()">Cancel</goabx-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">
      <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 for an Indian registration number

const [bandNo, setBandNo] = useState("");
  const [family, setFamily] = useState("");
  const [position, setPosition] = useState("");
<GoabxFormItem label="Indian registration number" labelSize="large">
      <GoabBlock gap="m" direction="row">
        <GoabxFormItem label="Band #" helpText="3 digits">
          <GoabxInput
            onChange={(e) => setBandNo(e.value)}
            value={bandNo}
            name="bandNo"
            width="88px"
            maxLength={3}
          />
        </GoabxFormItem>
        <GoabxFormItem label="Family" helpText="Up to 5 digits">
          <GoabxInput
            onChange={(e) => setFamily(e.value)}
            value={family}
            name="family"
            width="105px"
            maxLength={5}
          />
        </GoabxFormItem>
        <GoabxFormItem label="Position" helpText="2 digits">
          <GoabxInput
            onChange={(e) => setPosition(e.value)}
            value={position}
            name="position"
            width="71px"
            maxLength={2}
          />
        </GoabxFormItem>
      </GoabBlock>
    </GoabxFormItem>
form!: FormGroup;

  constructor(private fb: FormBuilder) {
    this.form = this.fb.group({
      bandNo: [""],
      family: [""],
      position: [""],
    });
  }
<goabx-form-item label="Indian registration number" labelSize="large">
  <goab-block gap="m" direction="row">
    <goabx-form-item label="Band #" helpText="3 digits">
      <goabx-input
        [formControl]="form.controls.bandNo"
        name="bandNo"
        width="88px"
        [maxLength]="3">
      </goabx-input>
    </goabx-form-item>
    <goabx-form-item label="Family" helpText="Up to 5 digits">
      <goabx-input
        [formControl]="form.controls.family"
        name="family"
        width="105px"
        [maxLength]="5">
      </goabx-input>
    </goabx-form-item>
    <goabx-form-item label="Position" helpText="2 digits">
      <goabx-input
        [formControl]="form.controls.position"
        name="position"
        width="71px"
        [maxLength]="2">
      </goabx-input>
    </goabx-form-item>
  </goab-block>
</goabx-form-item>
["band-input", "family-input", "position-input"].forEach((id) => {
  document.getElementById(id)?.addEventListener("_change", (e) => {
    console.log(`${id}:`, e.detail.value);
  });
});
<goa-form-item version="2" label="Indian registration number" labelsize="large">
  <goa-block gap="m" direction="row">
    <goa-form-item version="2" label="Band #" helptext="3 digits">
      <goa-input version="2"
        name="bandNo"
        id="band-input"
        width="88px"
        maxlength="3">
      </goa-input>
    </goa-form-item>
    <goa-form-item version="2" label="Family" helptext="Up to 5 digits">
      <goa-input version="2"
        name="family"
        id="family-input"
        width="105px"
        maxlength="5">
      </goa-input>
    </goa-form-item>
    <goa-form-item version="2" label="Position" helptext="2 digits">
      <goa-input version="2"
        name="position"
        id="position-input"
        width="71px"
        maxlength="2">
      </goa-input>
    </goa-form-item>
  </goa-block>
</goa-form-item>

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">
            <GoabxBadge type="midtone" content="Not started" />
            <GoabxButton type="tertiary" size="compact">Start</GoabxButton>
          </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">
            <GoabxBadge type="important" content="Information needed" />
            <GoabxButton type="tertiary" size="compact">Edit</GoabxButton>
          </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">
            <GoabxBadge type="success" content="Approved" />
            <GoabxButton type="tertiary" size="compact">View</GoabxButton>
          </GoabBlock>
        </div>
      </GoabContainer>
.case-file-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: var(--goa-space-m);
}
<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">
      <goabx-badge type="midtone" content="Not started"></goabx-badge>
      <goabx-button type="tertiary" size="compact">Start</goabx-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">
      <goabx-badge type="important" content="Information needed"></goabx-badge>
      <goabx-button type="tertiary" size="compact">Edit</goabx-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">
      <goabx-badge type="success" content="Approved"></goabx-badge>
      <goabx-button type="tertiary" size="compact">View</goabx-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="midtone" 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>

Copy to clipboard

.token-block {
  background-color: var(--goa-color-interactive-default);
  height: 22px;
  width: 24px;
  border-radius: var(--goa-border-radius-s);
}
const [isCopied, setIsCopied] = useState(false);

  function copyCode() {
    const codeToCopy = "$goa-color-interactive-default";
    navigator.clipboard.writeText(codeToCopy).then(() => {
      setIsCopied(true);
      setTimeout(() => setIsCopied(false), 1000);
    });
  }
<GoabBlock alignment="center">
        <div className="token-block" />
        <span>$goa-color-interactive-default</span>
        <GoabTooltip content={isCopied ? "Copied" : "Copy?"} position="top">
          <GoabIconButton icon="copy" onClick={copyCode} mt="2xs" />
        </GoabTooltip>
      </GoabBlock>
.token-block {
  background-color: var(--goa-color-interactive-default);
  height: 22px;
  width: 24px;
  border-radius: var(--goa-border-radius-s);
}
isCopied = false;

  copyCode(): void {
    const codeToCopy = "$goa-color-interactive-default";
    navigator.clipboard.writeText(codeToCopy).then(() => {
      this.isCopied = true;
      setTimeout(() => this.isCopied = false, 1000);
    });
  }
<goab-block alignment="center" gap="s">
  <div class="token-block"></div>
  <span>$goa-color-interactive-default</span>
  <goab-tooltip [content]="isCopied ? 'Copied' : 'Copy?'" position="top">
    <goab-icon-button icon="copy" (onClick)="copyCode()" mt="2xs"></goab-icon-button>
  </goab-tooltip>
</goab-block>
.token-block {
  background-color: var(--goa-color-interactive-default);
  height: 22px;
  width: 24px;
  border-radius: var(--goa-border-radius-s);
}
const copyBtn = document.getElementById('copy-btn');
const tooltip = document.getElementById('copy-tooltip');

function copyCode() {
  const codeToCopy = "$goa-color-interactive-default";
  navigator.clipboard.writeText(codeToCopy).then(() => {
    tooltip.setAttribute('content', 'Copied');
    setTimeout(() => {
      tooltip.setAttribute('content', 'Copy?');
    }, 1000);
  });
}

copyBtn.addEventListener('_click', copyCode);
<goa-block alignment="center">
  <div class="token-block"></div>
  <span>$goa-color-interactive-default</span>
  <goa-tooltip id="copy-tooltip" content="Copy?" position="top">
    <goa-icon-button id="copy-btn" icon="copy" mt="2xs"></goa-icon-button>
  </goa-tooltip>
</goa-block>

Display user information

const handleAddToCalendar = () => {
    console.log("Add to calendar clicked");
  };
<GoabContainer>
        <GoabText as="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 as="span" size="heading-xs" mt="none" mb="none">Email</GoabText>
            <GoabText as="span" size="heading-xs" mt="none" mb="none">Phone</GoabText>
          </GoabBlock>
          <GoabBlock direction="column" gap="m">
            <GoabText as="span" size="body-m" mt="none" mb="none">tracyhero@email.com</GoabText>
            <GoabText as="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={
          <GoabxButton
            type="tertiary"
            size="compact"
            leadingIcon="calendar"
            onClick={handleAddToCalendar}>
            Add to calendar
          </GoabxButton>
        }>
        <GoabxTable 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>
        </GoabxTable>
      </GoabContainer>
onAddToCalendar(): void {
    console.log("Add to calendar clicked");
  }
<goab-container>
  <goab-text as="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 as="span" size="heading-xs" mt="none" mb="none">Email</goab-text>
      <goab-text as="span" size="heading-xs" mt="none" mb="none">Phone</goab-text>
    </goab-block>
    <goab-block direction="column" gap="m">
      <goab-text as="span" size="body-m" mt="none" mb="none">tracyhero&#64;email.com</goab-text>
      <goab-text as="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">
    <goabx-button type="tertiary" size="compact" leadingIcon="calendar" (onClick)="onAddToCalendar()">
      Add to calendar
    </goabx-button>
  </div>
  <goabx-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>
  </goabx-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>

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]);
<GoabxFormItem id="filterChipInput" error={inputError} mb="m">
        <GoabBlock gap="xs" direction="row" alignment="start" width="100%">
          <div style={{ flex: 1 }}>
            <GoabxInput
              name="filterChipInput"
              aria-labelledby="filterChipInput"
              value={inputValue}
              leadingIcon="search"
              width="100%"
              onChange={handleInputChange}
              onKeyPress={handleInputKeyPress}
            />
          </div>
          <GoabxButton type="secondary" onClick={applyFilter} leadingIcon="filter">
            Filter
          </GoabxButton>
        </GoabBlock>
      </GoabxFormItem>

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

      <GoabxTable width="full">
        <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>
                <GoabxBadge 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>
      </GoabxTable>

      {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())
    );
  }
<goabx-form-item id="filterChipInput" [error]="inputError" mb="m">
  <goab-block gap="xs" direction="row" alignment="start" width="100%">
    <div style="flex: 1">
      <goabx-input
        name="filterChipInput"
        aria-labelledby="filterChipInput"
        [value]="inputValue"
        leadingIcon="search"
        width="100%"
        (onChange)="handleInputChange($event)"
        (onKeyPress)="handleInputKeyPress($event)"
      >
      </goabx-input>
    </div>
    <goabx-button type="secondary" (onClick)="applyFilter()" leadingIcon="filter">
      Filter
    </goabx-button>
  </goab-block>
</goabx-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) {
  <goabx-filter-chip
    [content]="typedChip"
    mb="xs"
    mr="xs"
    (onClick)="removeTypedChip(typedChip)"
  >
  </goabx-filter-chip>
  }
  <goabx-button type="tertiary" size="compact" mb="xs" (onClick)="removeAllTypedChips()">
    Clear all
  </goabx-button>
</ng-container>
}

<goabx-table width="full">
  <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>
        <goabx-badge
          [type]="item.status.type"
          [content]="item.status.text"
          [icon]="false"
        ></goabx-badge>
      </td>
      <td>{{ item.name }}</td>
      <td class="goa-table-number-column">{{ item.id }}</td>
    </tr>
    }
  </tbody>
</goabx-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 tag="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>

Result page

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

      <GoabxCallout type="success" heading="Application submitted">
        <GoabText size="body-m" mt="none" mb="s">You will receive a copy of the confirmation to the email name@email.com</GoabText>
        <GoabText size="body-m" mt="none" mb="none">Your reference number is: <strong>1234ABC</strong></GoabText>
      </GoabxCallout>

      <GoabText as="h2" mt="xl" mb="m">What happens next</GoabText>
      <GoabText size="body-m" mt="none" mb="s">We've sent your application to service name. They will contact you to confirm your registration.</GoabText>
      <GoabText size="body-m" mt="none" mb="s">You can now close this window.</GoabText>
      <GoabText size="body-m" mt="none" mb="s">What did you think of this service? <a href="#">Give feedback</a></GoabText>

      <GoabText as="h2" mt="xl" mb="m">If you have questions about your application</GoabText>
      <GoabText size="body-m" mt="none" mb="s">Contact the [ministry area].</GoabText>
      <GoabText size="body-m" mt="none" mb="s">Email: <a href="mailto:information@gov.ab.ca">information@gov.ab.ca</a></GoabText>
      <GoabText size="body-m" mt="none" mb="s">Phone: <a href="tel:7801234567">780 123 4567</a></GoabText>
  );
}
<goab-text as="h1" mt="none">You have completed the application</goab-text>

<goabx-callout type="success" heading="Application submitted">
  <goab-text size="body-m" mt="none" mb="s">You will receive a copy of the confirmation to the email name&#64;email.com</goab-text>
  <goab-text size="body-m" mt="none" mb="none">Your reference number is: <strong>1234ABC</strong></goab-text>
</goabx-callout>

<goab-text as="h2" mt="xl" mb="m">What happens next</goab-text>
<goab-text size="body-m" mt="none" mb="s">We've sent your application to service name. They will contact you to confirm your registration.</goab-text>
<goab-text size="body-m" mt="none" mb="s">You can now close this window.</goab-text>
<goab-text size="body-m" mt="none" mb="s">What did you think of this service? <a href="#">Give feedback</a></goab-text>

<goab-text as="h2" mt="xl" mb="m">If you have questions about your application</goab-text>
<goab-text size="body-m" mt="none" mb="s">Contact the [ministry area].</goab-text>
<goab-text size="body-m" mt="none" mb="s">Email: <a href="mailto:information&#64;gov.ab.ca">information&#64;gov.ab.ca</a></goab-text>
<goab-text size="body-m" mt="none" mb="s">Phone: <a href="tel:7801234567">780 123 4567</a></goab-text>
<goa-text as="h1" mt="none">You have completed the application</goa-text>

<goa-callout version="2" type="success" heading="Application submitted">
  <goa-text size="body-m" mt="none" mb="s">You will receive a copy of the confirmation to the email name@email.com</goa-text>
  <goa-text size="body-m" mt="none" mb="none">Your reference number is: <strong>1234ABC</strong></goa-text>
</goa-callout>

<goa-text as="h2" mt="xl" mb="m">What happens next</goa-text>
<goa-text size="body-m" mt="none" mb="s">We've sent your application to service name. They will contact you to confirm your registration.</goa-text>
<goa-text size="body-m" mt="none" mb="s">You can now close this window.</goa-text>
<goa-text size="body-m" mt="none" mb="s">What did you think of this service? <a href="#">Give feedback</a></goa-text>

<goa-text as="h2" mt="xl" mb="m">If you have questions about your application</goa-text>
<goa-text size="body-m" mt="none" mb="s">Contact the [ministry area].</goa-text>
<goa-text size="body-m" mt="none" mb="s">Email: <a href="mailto:information@gov.ab.ca">information@gov.ab.ca</a></goa-text>
<goa-text size="body-m" mt="none" mb="s">Phone: <a href="tel:7801234567">780 123 4567</a></goa-text>

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
    h3.review-h3 {
      margin-bottom: var(--goa-space-m);
    }
    label.review-label {
      font: var(--goa-typography-body-s);
      color: var(--goa-color-text-secondary);
    }
    .review-content {
      font: var(--goa-typography-body-m);
    }
    p.review-content {
      margin-bottom: 0;
    }
    h5.review-h5 {
      font: var(--goa-typography-body-m);
      color: var(--goa-color-text-secondary);
      margin-top: var(--goa-space-m);
      margin-bottom: var(--goa-space-m);
    }
    h6.review-h6 {
      font: var(--goa-typography-heading-s);
      margin-top: 0;
      margin-bottom: 0;
    }
  `,
  ],
})
export class ReviewAndActionComponent {
  form: FormGroup;

  constructor(private fb: FormBuilder) {
    this.form = this.fb.group({
      case: ["
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>

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

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

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

      <goabx-button mt="xl" (onClick)="onClick()">Confirm adjournment</goabx-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>
const [search, setSearch] = useState("");

  const onClick = () => {
    console.log("search:", search);
  };
<form>
      <GoabxFormItem>
        <GoabBlock gap="xs" direction="row">
          <GoabxInput
            type="search"
            name="search"
            value={search}
            onChange={(e) => setSearch(e.value)}
            leadingIcon="search"
          />
          <GoabxButton type="primary" onClick={onClick}>
            Search
          </GoabxButton>
        </GoabBlock>
      </GoabxFormItem>
    </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">
  <goabx-form-item>
    <goab-block gap="xs" direction="row">
      <goabx-input
        type="search"
        name="search"
        formControlName="search"
        leadingIcon="search">
      </goabx-input>
      <goabx-button type="primary" (onClick)="onClick()">Search</goabx-button>
    </goab-block>
  </goabx-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>

Show a list to help answer a question

const handleChange = (event: GoabRadioGroupOnChangeDetail) => {
    console.log("value is", event.value);
  };
<form>
      <GoabxFormItem
        label="Do you have additional education expenses?"
        helpText="You can request funding for these now or at any time during your program."
        mb="m">
        <GoabxRadioGroup name="additional" onChange={handleChange}>
          <GoabxRadioItem label="Yes" value="yes" name="additional" />
          <GoabxRadioItem label="No" value="no" name="additional" />
        </GoabxRadioGroup>
      </GoabxFormItem>

      <GoabDetails heading="What are additional education expenses?">
        <GoabBlock gap="m" mt="m">
          <div>
            <strong>Examples of education expenses</strong>
            <ul className="goa-unordered-list">
              <li>Laptop and computer hardware</li>
              <li>Computer apps and subscriptions</li>
              <li>Home internet</li>
              <li>Testing and exam fees</li>
              <li>Work or school clothing, like work boots</li>
            </ul>
          </div>
          <div>
            <strong>Do not include</strong>
            <ul className="goa-unordered-list">
              <li>Tuition</li>
              <li>Mandatory fees</li>
              <li>Books and supplies</li>
              <li>School association fees</li>
            </ul>
          </div>
        </GoabBlock>
      </GoabDetails>
    </form>
form: FormGroup;

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

  onRadioChange(event: Event): void {
    const detail = (event as CustomEvent).detail;
    console.log("value is", detail.value);
  }
<form [formGroup]="form">
  <goabx-form-item
    label="Do you have additional education expenses?"
    helpText="You can request funding for these now or at any time during your program."
    mb="m">
    <goabx-radio-group name="additional" (onChange)="onRadioChange($event)">
      <goabx-radio-item label="Yes" value="yes" name="additional"></goabx-radio-item>
      <goabx-radio-item label="No" value="no" name="additional"></goabx-radio-item>
    </goabx-radio-group>
  </goabx-form-item>

  <goab-details heading="What are additional education expenses?">
    <goab-block gap="m" mt="m">
      <div>
        <strong>Examples of education expenses</strong>
        <ul class="goa-unordered-list">
          <li>Laptop and computer hardware</li>
          <li>Computer apps and subscriptions</li>
          <li>Home internet</li>
          <li>Testing and exam fees</li>
          <li>Work or school clothing, like work boots</li>
        </ul>
      </div>
      <div>
        <strong>Do not include</strong>
        <ul class="goa-unordered-list">
          <li>Tuition</li>
          <li>Mandatory fees</li>
          <li>Books and supplies</li>
          <li>School association fees</li>
        </ul>
      </div>
    </goab-block>
  </goab-details>
</form>
document.querySelector('goa-radio-group').addEventListener('_change', (e) => {
  console.log('value is', e.detail.value);
});
<form>
  <goa-form-item version="2"
    label="Do you have additional education expenses?"
    helptext="You can request funding for these now or at any time during your program."
    mb="m">
    <goa-radio-group version="2" name="additional">
      <goa-radio-item label="Yes" value="yes" name="additional"></goa-radio-item>
      <goa-radio-item label="No" value="no" name="additional"></goa-radio-item>
    </goa-radio-group>
  </goa-form-item>

  <goa-details heading="What are additional education expenses?">
    <goa-block gap="m" mt="m">
      <div>
        <strong>Examples of education expenses</strong>
        <ul class="goa-unordered-list">
          <li>Laptop and computer hardware</li>
          <li>Computer apps and subscriptions</li>
          <li>Home internet</li>
          <li>Testing and exam fees</li>
          <li>Work or school clothing, like work boots</li>
        </ul>
      </div>
      <div>
        <strong>Do not include</strong>
        <ul class="goa-unordered-list">
          <li>Tuition</li>
          <li>Mandatory fees</li>
          <li>Books and supplies</li>
          <li>School association fees</li>
        </ul>
      </div>
    </goa-block>
  </goa-details>
</form>

Show multiple actions in a compact table

const rows = [
    { status: "information", statusText: "In progress", name: "Darlene Robertson", id: 45904 },
    { status: "dark", statusText: "Inactive", name: "Floyd Miles", id: 47838 },
    { status: "success", statusText: "Active", name: "Kathryn Murphy", id: 34343 },
    { status: "important", statusText: "Recent", name: "Annette Black", id: 89897 },
    { status: "success", statusText: "Active", name: "Esther Howard", id: 12323 },
    { status: "success", statusText: "Active", name: "Jane Cooper", id: 56565 },
  ];
<GoabxTable width="100%">
      <thead>
        <tr>
          <th>Status</th>
          <th>Name</th>
          <th style={{ textAlign: "right" }}>Id Number</th>
          <th style={{ width: "1%", whiteSpace: "nowrap" }}>Edit | Flag | Send</th>
        </tr>
      </thead>
      <tbody>
        {rows.map((row) => (
          <tr key={row.id}>
            <td>
              <GoabxBadge
                type={row.status as "information" | "dark" | "success" | "important"}
                content={row.statusText}
                icon={false}
              />
            </td>
            <td>{row.name}</td>
            <td className="goa-table-number-column">{row.id}</td>
            <td>
              <GoabBlock>
                <GoabIconButton size="small" icon="pencil" ariaLabel="Edit" />
                <GoabIconButton size="small" icon="flag" ariaLabel="Flag" />
                <GoabIconButton size="small" icon="mail" ariaLabel="Send" />
              </GoabBlock>
            </td>
          </tr>
        ))}
      </tbody>
    </GoabxTable>
rows: TableRow[] = [
    { status: "information", statusText: "In progress", name: "Darlene Robertson", id: 45904 },
    { status: "dark", statusText: "Inactive", name: "Floyd Miles", id: 47838 },
    { status: "success", statusText: "Active", name: "Kathryn Murphy", id: 34343 },
    { status: "important", statusText: "Recent", name: "Annette Black", id: 89897 },
    { status: "success", statusText: "Active", name: "Esther Howard", id: 12323 },
    { status: "success", statusText: "Active", name: "Jane Cooper", id: 56565 },
  ];
<goabx-table width="100%">
  <thead>
    <tr>
      <th>Status</th>
      <th>Name</th>
      <th style="text-align: right">Id Number</th>
      <th style="width: 1%; white-space: nowrap">Edit | Flag | Send</th>
    </tr>
  </thead>
  <tbody>
    @for (row of rows; track row.id) {
    <tr>
      <td>
        <goabx-badge [type]="row.status" [content]="row.statusText" [icon]="false"></goabx-badge>
      </td>
      <td>{{ row.name }}</td>
      <td class="goa-table-number-column">{{ row.id }}</td>
      <td>
        <goab-block>
          <goab-icon-button size="small" icon="pencil" ariaLabel="Edit"></goab-icon-button>
          <goab-icon-button size="small" icon="flag" ariaLabel="Flag"></goab-icon-button>
          <goab-icon-button size="small" icon="mail" ariaLabel="Send"></goab-icon-button>
        </goab-block>
      </td>
    </tr>
    }
  </tbody>
</goabx-table>
<goa-table version="2" width="100%">
  <table width="100%">
    <thead>
    <tr>
      <th>Status</th>
      <th>Name</th>
      <th style="text-align: right">Id Number</th>
      <th style="width: 1%; white-space: nowrap">Edit | Flag | Send</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><goa-badge version="2" type="information" content="In progress" icon="false"></goa-badge></td>
      <td>Darlene Robertson</td>
      <td class="goa-table-number-column">45904</td>
      <td>
        <goa-block>
          <goa-icon-button size="small" icon="pencil" arialabel="Edit"></goa-icon-button>
          <goa-icon-button size="small" icon="flag" arialabel="Flag"></goa-icon-button>
          <goa-icon-button size="small" icon="mail" arialabel="Send"></goa-icon-button>
        </goa-block>
      </td>
    </tr>
    <tr>
      <td><goa-badge version="2" type="dark" content="Inactive" icon="false"></goa-badge></td>
      <td>Floyd Miles</td>
      <td class="goa-table-number-column">47838</td>
      <td>
        <goa-block>
          <goa-icon-button size="small" icon="pencil" arialabel="Edit"></goa-icon-button>
          <goa-icon-button size="small" icon="flag" arialabel="Flag"></goa-icon-button>
          <goa-icon-button size="small" icon="mail" arialabel="Send"></goa-icon-button>
        </goa-block>
      </td>
    </tr>
    <tr>
      <td><goa-badge version="2" type="success" content="Active" icon="false"></goa-badge></td>
      <td>Kathryn Murphy</td>
      <td class="goa-table-number-column">34343</td>
      <td>
        <goa-block>
          <goa-icon-button size="small" icon="pencil" arialabel="Edit"></goa-icon-button>
          <goa-icon-button size="small" icon="flag" arialabel="Flag"></goa-icon-button>
          <goa-icon-button size="small" icon="mail" arialabel="Send"></goa-icon-button>
        </goa-block>
      </td>
    </tr>
    <tr>
      <td><goa-badge version="2" type="important" content="Recent" icon="false"></goa-badge></td>
      <td>Annette Black</td>
      <td class="goa-table-number-column">89897</td>
      <td>
        <goa-block>
          <goa-icon-button size="small" icon="pencil" arialabel="Edit"></goa-icon-button>
          <goa-icon-button size="small" icon="flag" arialabel="Flag"></goa-icon-button>
          <goa-icon-button size="small" icon="mail" arialabel="Send"></goa-icon-button>
        </goa-block>
      </td>
    </tr>
    <tr>
      <td><goa-badge version="2" type="success" content="Active" icon="false"></goa-badge></td>
      <td>Esther Howard</td>
      <td class="goa-table-number-column">12323</td>
      <td>
        <goa-block>
          <goa-icon-button size="small" icon="pencil" arialabel="Edit"></goa-icon-button>
          <goa-icon-button size="small" icon="flag" arialabel="Flag"></goa-icon-button>
          <goa-icon-button size="small" icon="mail" arialabel="Send"></goa-icon-button>
        </goa-block>
      </td>
    </tr>
    <tr>
      <td><goa-badge version="2" type="success" content="Active" icon="false"></goa-badge></td>
      <td>Jane Cooper</td>
      <td class="goa-table-number-column">56565</td>
      <td>
        <goa-block>
          <goa-icon-button size="small" icon="pencil" arialabel="Edit"></goa-icon-button>
          <goa-icon-button size="small" icon="flag" arialabel="Flag"></goa-icon-button>
          <goa-icon-button size="small" icon="mail" arialabel="Send"></goa-icon-button>
        </goa-block>
      </td>
    </tr>
    </tbody>
  </table>
</goa-table>

Show multiple tags together

<GoabBlock gap="xs">
      <GoabxBadge type="information" content="In progress" />
      <GoabxBadge type="important" content="Priority" />
      <GoabxBadge type="emergency" content="Past deadline" />
    </GoabBlock>
<goab-block gap="xs">
  <goabx-badge type="information" content="In progress"></goabx-badge>
  <goabx-badge type="important" content="Priority"></goabx-badge>
  <goabx-badge type="emergency" content="Past deadline"></goabx-badge>
</goab-block>
<goa-block gap="xs">
  <goa-badge version="2" type="information" content="In progress"></goa-badge>
  <goa-badge version="2" type="important" content="Priority"></goa-badge>
  <goa-badge version="2" type="emergency" content="Past deadline"></goa-badge>
</goa-block>

Show number of results per page

interface User {
  id: string;
  firstName: string;
  lastName: string;
  age: number;
}

const [users, setUsers] = useState<User[]>([]);
  const [pageUsers, setPageUsers] = useState<User[]>([]);
  const [page, setPage] = useState<number>(1);
  const [perPage, setPerPage] = useState<number>(10);

  useEffect(() => {
    // Generate sample data
    const firstNames = ["Emma", "Liam", "Olivia", "Noah", "Ava", "James", "Sophia", "William", "Isabella", "Oliver", "Mia", "Benjamin", "Charlotte", "Elijah", "Amelia", "Lucas", "Harper", "Mason", "Evelyn", "Logan"];
    const lastNames = ["Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller", "Davis", "Rodriguez", "Martinez", "Wilson", "Anderson", "Taylor", "Thomas", "Moore", "Jackson", "Martin", "Lee", "Thompson", "White"];
    const _users: User[] = [];
    for (let i = 1; i <= 100; i++) {
      _users.push({
        id: `user-${i}`,
        firstName: firstNames[(i - 1) % firstNames.length],
        lastName: lastNames[(i - 1) % lastNames.length],
        age: 20 + (i % 40),
      });
    }
    setUsers(_users);
    setPageUsers(_users.slice(0, perPage));
  }, [perPage]);

  function changePage(newPage: number) {
    const offset = (newPage - 1) * perPage;
    const _users = users.slice(offset, offset + perPage);
    setPage(newPage);
    setPageUsers(_users);
  }

  function handlePerPageCountChangeEvent(event: GoabDropdownOnChangeDetail) {
    const perPageValue = parseInt(event.value || "10");
    setPage(1);
    setPerPage(perPageValue);
    const _users = users.slice(0, perPageValue);
    setPageUsers(_users);
  }
<GoabxTable width="100%" mb="xl">
        <thead>
          <tr>
            <th>First name</th>
            <th>Last name</th>
            <th>Age</th>
          </tr>
        </thead>
        <tbody>
          {pageUsers.map((u) => (
            <tr key={u.id}>
              <td>{u.firstName}</td>
              <td>{u.lastName}</td>
              <td>{u.age}</td>
            </tr>
          ))}
        </tbody>
      </GoabxTable>

      <GoabBlock alignment="center" width="100%">
        <GoabBlock mb="m" alignment="center">
          Show
          <GoabxDropdown
            onChange={handlePerPageCountChangeEvent}
            value={perPage.toString()}
            width="9ch"
          >
            <GoabxDropdownItem value="10" label="10" />
            <GoabxDropdownItem value="20" label="20" />
            <GoabxDropdownItem value="30" label="30" />
          </GoabxDropdown>
          <span style={{ width: "75px" }}>per page</span>
        </GoabBlock>
        <GoabSpacer hSpacing="fill" />
        <GoabxPagination
          itemCount={users.length}
          perPageCount={perPage}
          pageNumber={page}
          onChange={(event) => changePage(event.page)}
        />
      </GoabBlock>
users: User[] = [];
  pageUsers: User[] = [];
  page = 1;
  perPage = 10;
  total = 100;

  constructor() {
    this.pageUsers = this.prepareUsers().slice(0, this.perPage);
  }

  prepareUsers(): User[] {
    const firstNames = ["Emma", "Liam", "Olivia", "Noah", "Ava", "James", "Sophia", "William", "Isabella", "Oliver", "Mia", "Benjamin", "Charlotte", "Elijah", "Amelia", "Lucas", "Harper", "Mason", "Evelyn", "Logan"];
    const lastNames = ["Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller", "Davis", "Rodriguez", "Martinez", "Wilson", "Anderson", "Taylor", "Thomas", "Moore", "Jackson", "Martin", "Lee", "Thompson", "White"];
    for (let i = 1; i <= this.total; i++) {
      this.users.push({
        id: `user-${i}`,
        firstName: firstNames[(i - 1) % firstNames.length],
        lastName: lastNames[(i - 1) % lastNames.length],
        age: 20 + (i % 40),
      });
    }
    return this.users;
  }

  handlePageChange(event: GoabPaginationOnChangeDetail): void {
    this.page = event.page;
    const offset = (this.page - 1) * this.perPage;
    this.pageUsers = this.users.slice(offset, offset + this.perPage);
  }

  handlePerPageCountChangeEvent(event: GoabDropdownOnChangeDetail): void {
    this.page = 1;
    this.perPage = Number(event.value);
    this.pageUsers = this.users.slice(0, this.perPage);
  }
<goabx-table width="100%" mb="xl">
  <thead>
    <tr>
      <th>First name</th>
      <th>Last name</th>
      <th>Age</th>
    </tr>
  </thead>
  <tbody>
    @for (user of pageUsers; track $index) {
    <tr>
      <td>{{ user.firstName }}</td>
      <td>{{ user.lastName }}</td>
      <td>{{ user.age }}</td>
    </tr>
    }
  </tbody>
</goabx-table>

<goab-block alignment="center" width="100%">
  <goab-block mb="m" alignment="center">
    Show
    <goabx-dropdown
      (onChange)="handlePerPageCountChangeEvent($event)"
      value="10"
      width="9ch">
      <goabx-dropdown-item value="10" label="10"></goabx-dropdown-item>
      <goabx-dropdown-item value="20" label="20"></goabx-dropdown-item>
      <goabx-dropdown-item value="30" label="30"></goabx-dropdown-item>
    </goabx-dropdown>
    <span style="width: 75px">per page</span>
  </goab-block>

  <goab-spacer hSpacing="fill"></goab-spacer>

  <goabx-pagination
    [itemCount]="users.length"
    [perPageCount]="perPage"
    [pageNumber]="page"
    (onChange)="handlePageChange($event)">
  </goabx-pagination>
</goab-block>
const firstNames = ["Emma", "Liam", "Olivia", "Noah", "Ava", "James", "Sophia", "William", "Isabella", "Oliver", "Mia", "Benjamin", "Charlotte", "Elijah", "Amelia", "Lucas", "Harper", "Mason", "Evelyn", "Logan"];
const lastNames = ["Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller", "Davis", "Rodriguez", "Martinez", "Wilson", "Anderson", "Taylor", "Thomas", "Moore", "Jackson", "Martin", "Lee", "Thompson", "White"];
const users = [];
for (let i = 1; i <= 100; i++) {
  users.push({
    id: "user-" + i,
    firstName: firstNames[(i - 1) % firstNames.length],
    lastName: lastNames[(i - 1) % lastNames.length],
    age: 20 + (i % 40),
  });
}

let page = 1;
let perPage = 10;

const tableBody = document.getElementById("table-body");
const pagination = document.getElementById("pagination");
const dropdown = document.getElementById("per-page-dropdown");

function renderTable() {
  const offset = (page - 1) * perPage;
  const pageUsers = users.slice(offset, offset + perPage);

  tableBody.innerHTML = pageUsers
    .map(
      (u) => `
      <tr>
        <td>${u.firstName}</td>
        <td>${u.lastName}</td>
        <td>${u.age}</td>
      </tr>
    `
    )
    .join("");
}

pagination.addEventListener("_change", (e) => {
  page = e.detail.page;
  renderTable();
});

dropdown.addEventListener("_change", (e) => {
  perPage = parseInt(e.detail.value);
  page = 1;
  pagination.setAttribute("perpagecount", perPage);
  pagination.setAttribute("pagenumber", "1");
  renderTable();
});

renderTable();
<goa-table version="2" width="100%" mb="xl">
  <table width="100%">
    <thead>
      <tr>
        <th>First name</th>
        <th>Last name</th>
        <th>Age</th>
      </tr>
    </thead>
    <tbody id="table-body">
      <!-- Rows populated by JavaScript -->
    </tbody>
  </table>
</goa-table>

<goa-block alignment="center" width="100%">
  <goa-block mb="m" alignment="center">
    Show
    <goa-dropdown version="2" id="per-page-dropdown" value="10" width="9ch">
      <goa-dropdown-item value="10" label="10"></goa-dropdown-item>
      <goa-dropdown-item value="20" label="20"></goa-dropdown-item>
      <goa-dropdown-item value="30" label="30"></goa-dropdown-item>
    </goa-dropdown>
    <span style="width: 75px">per page</span>
  </goa-block>

  <goa-spacer hspacing="fill"></goa-spacer>

  <goa-pagination version="2"
    id="pagination"
    itemcount="100"
    perpagecount="10"
    pagenumber="1">
  </goa-pagination>
</goa-block>

Workspace

Preview not available
No React code available

Other

Header section

Main content area

Footer section

Don't use a container for general page layout. Containers are for visual emphasis and grouping content.
All GoA Design System components are built to meet WCAG 2.2 AA standards. The following guidelines provide additional context for accessible implementation.

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