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.
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>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@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>