Filter chip
Allow the user to enter information, filter content, and make selections.
Props
error
boolean
Shows an error state.
Defaults to
false.
content
string
Text label of the chip.
secondarytext
string
Secondary text displayed in a smaller size before the main content.
leadingIcon
GoAIconType
Icon displayed at the start of the chip.
testId
string
Sets a data-testid attribute for automated testing.
ariaLabel
string
Accessible label for the filter chip. Defaults to content with 'removable' suffix.
version
1 | 2
The design system version for styling purposes.
Defaults to
1.
mt, mr, mb, ml
none | 3xs | 2xs | xs | s | m | l | xl | 2xl | 3xl | 4xl
Apply margin to the top, right, bottom, and/or left of the component.
Events
onClick
(event: Event) => void
_click
CustomEvent
Add a filter chip
const [activeFilters, setActiveFilters] = useState<string[]>([]);
const addFilter = () => {
const randomFilter = `Filter ${Math.floor(Math.random() * 100)}`;
if (!activeFilters.includes(randomFilter)) {
setActiveFilters((prevFilters) => [...prevFilters, randomFilter]);
}
};
const removeFilter = (filter: string) => {
setActiveFilters((prevFilters) => prevFilters.filter((f) => f !== filter));
};<div>
{activeFilters.map((filter) => (
<GoabFilterChip
key={filter}
content={filter}
onClick={() => removeFilter(filter)}
mr="s"
mb="s"
mt="s"
/>
))}
</div>
<GoabButton mt="l" onClick={addFilter}>Add Random Filter</GoabButton>Filter data in a table
const [typedChips, setTypedChips] = useState<string[]>([]);
const [inputValue, setInputValue] = useState("");
const [inputError, setInputError] = useState("");
const errorEmpty = "Empty filter";
const errorDuplicate = "Enter a unique filter";
const data = useMemo(
() => [
{
status: { type: "information" as GoabBadgeType, text: "In progress" },
name: "Ivan Schmidt",
id: "7838576954",
},
{
status: { type: "success" as GoabBadgeType, text: "Completed" },
name: "Luz Lakin",
id: "8576953364",
},
{
status: { type: "information" as GoabBadgeType, text: "In progress" },
name: "Keith McGlynn",
id: "9846041345",
},
{
status: { type: "success" as GoabBadgeType, text: "Completed" },
name: "Melody Frami",
id: "7385256175",
},
{
status: { type: "important" as GoabBadgeType, text: "Updated" },
name: "Frederick Skiles",
id: "5807570418",
},
{
status: { type: "success" as GoabBadgeType, text: "Completed" },
name: "Dana Pfannerstill",
id: "5736306857",
},
],
[]
);
const [dataFiltered, setDataFiltered] = useState(data);
const handleInputChange = (detail: GoabInputOnChangeDetail) => {
const newValue = detail.value.trim();
setInputValue(newValue);
};
const handleInputKeyPress = (detail: GoabInputOnKeyPressDetail) => {
if (detail.key === "Enter") {
applyFilter();
}
};
const applyFilter = () => {
if (inputValue === "") {
setInputError(errorEmpty);
return;
}
if (typedChips.length > 0 && typedChips.includes(inputValue)) {
setInputError(errorDuplicate);
return;
}
setTypedChips([...typedChips, inputValue]);
setTimeout(() => {
setInputValue("");
}, 0);
setInputError("");
};
const removeTypedChip = (chip: string) => {
setTypedChips(typedChips.filter(c => c !== chip));
setInputError("");
};
const checkNested = useCallback((obj: object, chip: string): boolean => {
return Object.values(obj).some(value =>
typeof value === "object" && value !== null
? checkNested(value, chip)
: typeof value === "string" && value.toLowerCase().includes(chip.toLowerCase())
);
}, []);
const getFilteredData = useCallback(
(typedChips: string[]) => {
if (typedChips.length === 0) {
return data;
}
return data.filter((item: object) =>
typedChips.every(chip => checkNested(item, chip))
);
},
[checkNested, data]
);
useEffect(() => {
setDataFiltered(getFilteredData(typedChips));
}, [getFilteredData, typedChips]);<GoabFormItem id="filterChipInput" error={inputError} mb="m">
<GoabBlock gap="xs" direction="row" alignment="start" width="100%">
<div style={{ flex: 1 }}>
<GoabInput
name="filterChipInput"
aria-labelledby="filterChipInput"
value={inputValue}
leadingIcon="search"
width="100%"
onChange={handleInputChange}
onKeyPress={handleInputKeyPress}
/>
</div>
<GoabButton type="secondary" onClick={applyFilter} leadingIcon="filter">
Filter
</GoabButton>
</GoabBlock>
</GoabFormItem>
{typedChips.length > 0 && (
<div>
<GoabText tag="span" color="secondary" mb="xs" mr="xs">
Filter:
</GoabText>
{typedChips.map((typedChip, index) => (
<GoabFilterChip
key={index}
content={typedChip}
mb="xs"
mr="xs"
onClick={() => removeTypedChip(typedChip)}
/>
))}
<GoabButton type="tertiary" size="compact" mb="xs" onClick={() => setTypedChips([])}>
Clear all
</GoabButton>
</div>
)}
<GoabTable width="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>
<GoabBadge type={item.status.type} content={item.status.text} icon={false} />
</td>
<td>{item.name}</td>
<td className="goa-table-number-column">{item.id}</td>
</tr>
))}
</tbody>
</GoabTable>
{dataFiltered.length === 0 && data.length > 0 && (
<GoabBlock mt="l" mb="l">
No results found
</GoabBlock>
)}Remove a filter
const [chips, setChips] = useState(["Chip 1", "Chip 2", "Chip 3"]);
const deleteChip = (chip: string) => {
setChips((prevChips) => prevChips.filter((c) => c !== chip));
};<div>
{chips.map((chip) => (
<GoabFilterChip
key={chip}
content={chip}
onClick={() => deleteChip(chip)}
mr="s"
/>
))}
</div>Type to create a new filter
const [typedChips, setTypedChips] = useState<string[]>([]);
const [inputValue, setInputValue] = useState("");<GoabFormItem label="Type to create a chip" mb="m">
<GoabInput
name="chipInput"
value={inputValue}
onChange={(e) => setInputValue(e.value.trim())}
onKeyPress={(e) => {
if (e.key === "Enter" && e.value.trim()) {
setTypedChips([...typedChips, e.value.trim()]);
setTimeout(() => setInputValue(""), 0);
} else if (e.key === "Backspace" && !e.value.trim() && typedChips.length > 0) {
setTypedChips(typedChips.slice(0, -1));
}
}}
width="100%"
/>
</GoabFormItem>
<div>
{typedChips.map((chip, index) => (
<GoabFilterChip
key={index}
content={chip}
mb="xs"
mr="xs"
onClick={() => setTypedChips(typedChips.filter((c) => c !== chip))}
/>
))}
</div>