Text

Provides consistent sizing, spacing, and colour to written content.

Props

as
span | div | p | h1 | h2 | h3 | h4 | h5
The HTML element to render. Use semantic elements like 'h1'-'h6' for headings.
Defaults to div.
maxWidth
string | none
Sets the max width.
Defaults to 65ch.
size
heading-xl | heading-l | heading-m | heading-s | heading-xs | heading-2xs | body-l | body-m | body-s | body-xs
Overrides the text size.
color
primary | secondary
Sets the text colour.
Defaults to primary.
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

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 direct deposit information

const [bankNumber, setBankNumber] = useState("");
  const [transitNumber, setTransitNumber] = useState("");
  const [accountNumber, setAccountNumber] = useState("");
<GoabText as="h1" size="heading-l" mt="none" mb="m">Direct deposit information</GoabText>
      <GoabText as="p" mb="xl">
        Find this information on your bank's website or on your personal cheques.
        Contact your bank if you can't find this information.
      </GoabText>
      <form>
        <GoabxFormItem
          label="Bank or Institution number"
          helpText="3-4 digits in length"
        >
          <GoabxInput
            maxLength={4}
            name="bankNumber"
            onChange={(e) => setBankNumber(e.value)}
            value={bankNumber}
            ariaLabel="bankNumber"
            width="88px"
          />
        </GoabxFormItem>
        <GoabxFormItem
          label="Branch or Transit number"
          helpText="5 digits in length"
          mt="l"
        >
          <GoabxInput
            maxLength={5}
            name="transitNumber"
            onChange={(e) => setTransitNumber(e.value)}
            value={transitNumber}
            ariaLabel="transitNumber"
            width="143px"
          />
        </GoabxFormItem>
        <GoabxFormItem
          label="Account number"
          helpText="3-12 digits in length"
          mt="l"
        >
          <GoabxInput
            maxLength={12}
            name="accountNumber"
            value={accountNumber}
            onChange={(e) => setAccountNumber(e.value)}
            ariaLabel="accountNumber"
          />
        </GoabxFormItem>
      </form>
      <GoabDetails heading="Where can I find this information on a personal cheque?" mt="l">
        <GoabText as="p" mb="m">
          Below is an example of where you can find the required bank information
          on a personal cheque.
        </GoabText>
        <img src="https://design.alberta.ca/images/details-demo.jpg" alt="Cheque example showing bank information locations" />
      </GoabDetails>

      <GoabxButton type="submit" mt="2xl">
        Save and continue
      </GoabxButton>
form!: FormGroup;

  constructor(private fb: FormBuilder) {
    this.form = this.fb.group({
      bankNumber: [""],
      transitNumber: [""],
      accountNumber: [""],
    });
  }
<goab-text as="h1" size="heading-l" mt="none" mb="m">Direct deposit information</goab-text>
<goab-text as="p" mb="xl">
  Find this information on your bank's website or on your personal cheques.
  Contact your bank if you can't find this information.
</goab-text>
<form [formGroup]="form">
  <goabx-form-item
    label="Bank or Institution number"
    helpText="3-4 digits in length">
    <goabx-input
      [maxLength]="4"
      name="bankNumber"
      [formControl]="form.controls.bankNumber"
      ariaLabel="bankNumber"
      width="88px">
    </goabx-input>
  </goabx-form-item>
  <goabx-form-item
    label="Branch or Transit number"
    helpText="5 digits in length"
    mt="l">
    <goabx-input
      [maxLength]="5"
      name="transitNumber"
      [formControl]="form.controls.transitNumber"
      ariaLabel="transitNumber"
      width="143px">
    </goabx-input>
  </goabx-form-item>
  <goabx-form-item
    label="Account number"
    helpText="3-12 digits in length"
    mt="l">
    <goabx-input
      [maxLength]="12"
      name="accountNumber"
      [formControl]="form.controls.accountNumber"
      ariaLabel="accountNumber">
    </goabx-input>
  </goabx-form-item>
</form>
<goab-details heading="Where can I find this information on a personal cheque?" mt="l">
  <goab-text as="p" mb="m">Below is an example of where you can find the required bank information on a personal cheque.</goab-text>
  <img src="https://design.alberta.ca/images/details-demo.jpg" alt="Cheque example" />
</goab-details>

<goabx-button type="submit" mt="2xl" (onClick)="onSubmit()">
  Save and continue
</goabx-button>
["bank-number-input", "transit-number-input", "account-number-input"].forEach((id) => {
  document.getElementById(id)?.addEventListener("_change", (e) => {
    console.log(`${id}:`, e.detail.value);
  });
});
<goa-text as="h1" size="heading-l" mt="none" mb="m">Direct deposit information</goa-text>
<goa-text as="p" mb="xl">
  Find this information on your bank's website or on your personal cheques.
  Contact your bank if you can't find this information.
</goa-text>
<form>
  <goa-form-item version="2"
    label="Bank or Institution number"
    helptext="3-4 digits in length">
    <goa-input version="2"
      maxlength="4"
      name="bankNumber"
      id="bank-number-input"
      aria-label="bankNumber"
      width="88px">
    </goa-input>
  </goa-form-item>
  <goa-form-item version="2"
    label="Branch or Transit number"
    helptext="5 digits in length"
    mt="l">
    <goa-input version="2"
      maxlength="5"
      name="transitNumber"
      id="transit-number-input"
      aria-label="transitNumber"
      width="143px">
    </goa-input>
  </goa-form-item>
  <goa-form-item version="2"
    label="Account number"
    helptext="3-12 digits in length"
    mt="l">
    <goa-input version="2"
      maxlength="12"
      name="accountNumber"
      id="account-number-input"
      aria-label="accountNumber">
    </goa-input>
  </goa-form-item>
</form>
<goa-details heading="Where can I find this information on a personal cheque?" mt="l">
  <goa-text as="p" mb="m">Below is an example of where you can find the required bank information on a personal cheque.</goa-text>
  <img src="https://design.alberta.ca/images/details-demo.jpg" alt="Cheque example" />
</goa-details>

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

Card grid

<GoabGrid gap="xl" minChildWidth="320px">
      <GoabContainer accent="thin" mb="none">
        <GoabxLink size="large" mb="m">
          <a href="#">Waitlist submission</a>
        </GoabxLink>
        <GoabText mt="none" mb="none">
          Enter and maintain information about the households waiting for affordable housing
          with your organization.
        </GoabText>
      </GoabContainer>

      <GoabContainer accent="thin" mb="none">
        <GoabxLink size="large" mb="m">
          <a href="#">Lodge assistance program</a>
        </GoabxLink>
        <GoabText mt="none" mb="none">
          Keep track of the individuals who are placed in lodges and may qualify for the Lodge
          Assistance Program subsidy.
        </GoabText>
      </GoabContainer>

      <GoabContainer accent="thin" mb="none">
        <GoabxLink size="large" mb="m">
          <a href="#">Education Support</a>
        </GoabxLink>
        <GoabText mt="none" mb="none">
          Explore educational resources, enroll in courses, and track your academic progress
          effortlessly.
        </GoabText>
      </GoabContainer>

      <GoabContainer accent="thin" mb="none">
        <GoabxLink size="large" mb="m">
          <a href="#">Social Assistance</a>
        </GoabxLink>
        <GoabText mt="none" mb="none">
          Learn about available support programs, apply for financial aid, and access community
          resources.
        </GoabText>
      </GoabContainer>

      <GoabContainer accent="thin" mb="none">
        <GoabxLink size="large" mb="m">
          <a href="#">Employment Opportunity</a>
        </GoabxLink>
        <GoabText mt="none" mb="none">
          Search for job openings, access career development tools, and receive
          employment-related updates.
        </GoabText>
      </GoabContainer>

      <GoabContainer accent="thin" mb="none">
        <GoabxLink size="large" mb="m">
          <a href="#">Housing Assistance</a>
        </GoabxLink>
        <GoabText mt="none" mb="none">
          Find affordable housing options, apply for housing subsidies, and report maintenance
          issues seamlessly.
        </GoabText>
      </GoabContainer>
    </GoabGrid>
<goab-grid gap="xl" minChildWidth="320px">
  <goab-container accent="thin" mb="none">
    <goabx-link size="large" mb="m">
      <a href="#">Waitlist submission</a>
    </goabx-link>
    <goab-text mt="none" mb="none">
      Enter and maintain information about the households waiting for affordable housing
      with your organization.
    </goab-text>
  </goab-container>

  <goab-container accent="thin" mb="none">
    <goabx-link size="large" mb="m">
      <a href="#">Lodge assistance program</a>
    </goabx-link>
    <goab-text 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-container>

  <goab-container accent="thin" mb="none">
    <goabx-link size="large" mb="m">
      <a href="#">Education Support</a>
    </goabx-link>
    <goab-text mt="none" mb="none">
      Explore educational resources, enroll in courses, and track your academic progress
      effortlessly.
    </goab-text>
  </goab-container>

  <goab-container accent="thin" mb="none">
    <goabx-link size="large" mb="m">
      <a href="#">Social Assistance</a>
    </goabx-link>
    <goab-text mt="none" mb="none">
      Learn about available support programs, apply for financial aid, and access community
      resources.
    </goab-text>
  </goab-container>

  <goab-container accent="thin" mb="none">
    <goabx-link size="large" mb="m">
      <a href="#">Employment Opportunity</a>
    </goabx-link>
    <goab-text mt="none" mb="none">
      Search for job openings, access career development tools, and receive
      employment-related updates.
    </goab-text>
  </goab-container>

  <goab-container accent="thin" mb="none">
    <goabx-link size="large" mb="m">
      <a href="#">Housing Assistance</a>
    </goabx-link>
    <goab-text mt="none" mb="none">
      Find affordable housing options, apply for housing subsidies, and report maintenance
      issues seamlessly.
    </goab-text>
  </goab-container>
</goab-grid>
<goa-grid gap="xl" minchildwidth="320px">
  <goa-container accent="thin" mb="none">
    <goa-link size="large" mb="m">
      <a href="#">Waitlist submission</a>
    </goa-link>
    <goa-text mt="none" mb="none">
      Enter and maintain information about the households waiting for affordable housing
      with your organization.
    </goa-text>
  </goa-container>

  <goa-container accent="thin" mb="none">
    <goa-link size="large" mb="m">
      <a href="#">Lodge assistance program</a>
    </goa-link>
    <goa-text 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-container>

  <goa-container accent="thin" mb="none">
    <goa-link size="large" mb="m">
      <a href="#">Education Support</a>
    </goa-link>
    <goa-text mt="none" mb="none">
      Explore educational resources, enroll in courses, and track your academic progress
      effortlessly.
    </goa-text>
  </goa-container>

  <goa-container accent="thin" mb="none">
    <goa-link size="large" mb="m">
      <a href="#">Social Assistance</a>
    </goa-link>
    <goa-text mt="none" mb="none">
      Learn about available support programs, apply for financial aid, and access community
      resources.
    </goa-text>
  </goa-container>

  <goa-container accent="thin" mb="none">
    <goa-link size="large" mb="m">
      <a href="#">Employment Opportunity</a>
    </goa-link>
    <goa-text mt="none" mb="none">
      Search for job openings, access career development tools, and receive
      employment-related updates.
    </goa-text>
  </goa-container>

  <goa-container accent="thin" mb="none">
    <goa-link size="large" mb="m">
      <a href="#">Housing Assistance</a>
    </goa-link>
    <goa-text mt="none" mb="none">
      Find affordable housing options, apply for housing subsidies, and report maintenance
      issues seamlessly.
    </goa-text>
  </goa-container>
</goa-grid>

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>

No usage guidelines have been documented for this component yet.

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

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