import { FilterBar } from "@vortexlabs/vortex";
const filters = [
{
id: "status",
label: "Status",
options: [
{ value: "active", label: "Active" },
{ value: "pending", label: "Pending" },
{ value: "inactive", label: "Inactive" },
{ value: "closed", label: "Closed" },
],
},
{
id: "type",
label: "Type",
selection: "single",
options: [
{ value: "contribution", label: "Contribution" },
{ value: "rollover", label: "Rollover" },
{ value: "withdrawal", label: "Withdrawal" },
],
},
{
id: "country",
label: "Country",
addable: true,
options: [
{ value: "au", label: "Australia" },
{ value: "nz", label: "New Zealand" },
{ value: "sg", label: "Singapore" },
],
},
];
export const Example = () => <FilterBar filters={filters} />;Features
- Doesn't filter data; reports selected values through
onChange. - Selects one option or several per filter.
- Keeps less common filters in an add menu.
- Clears one filter or all of them.
- Moves filters into a drawer on narrow screens.
Selection
The default is multiple. Use selection: "single" when a filter takes one option. The trigger lists selected values, and shows a count when more than two are selected.
import { FilterBar, type FilterBarFilter } from "@vortexlabs/vortex";
const filters: FilterBarFilter[] = [
{
id: "status",
label: "Status",
options: [
{ value: "active", label: "Active" },
{ value: "pending", label: "Pending" },
{ value: "inactive", label: "Inactive" },
{ value: "closed", label: "Closed" },
],
},
{
id: "type",
label: "Type",
selection: "single",
options: [
{ value: "contribution", label: "Contribution" },
{ value: "rollover", label: "Rollover" },
{ value: "withdrawal", label: "Withdrawal" },
],
},
];
export const Example = () => <FilterBar filters={filters} />;Addable Filters
Set addable: true to start a filter in the add menu. Clearing it moves it back.
import { FilterBar, type FilterBarFilter } from "@vortexlabs/vortex";
const filters: FilterBarFilter[] = [
{
id: "status",
label: "Status",
options: [
{ value: "active", label: "Active" },
{ value: "pending", label: "Pending" },
{ value: "inactive", label: "Inactive" },
{ value: "closed", label: "Closed" },
],
},
{
id: "country",
label: "Country",
addable: true,
options: [
{ value: "au", label: "Australia" },
{ value: "nz", label: "New Zealand" },
{ value: "sg", label: "Singapore" },
],
},
];
export const Example = () => <FilterBar filters={filters} />;Controlled State
Use onChange to filter your data, with value to control the selection or defaultValue to set where it starts.
The value maps each filter id to its selected option values, such as { status: ["active"] }. Filters without a selection are left out.
import {
FilterBar,
type FilterBarFilter,
type FilterBarValue,
Stack,
Text,
} from "@vortexlabs/vortex";
import React from "react";
const filters: FilterBarFilter[] = [
{
id: "status",
label: "Status",
options: [
{ value: "active", label: "Active" },
{ value: "pending", label: "Pending" },
{ value: "inactive", label: "Inactive" },
{ value: "closed", label: "Closed" },
],
},
{
id: "type",
label: "Type",
selection: "single",
options: [
{ value: "contribution", label: "Contribution" },
{ value: "rollover", label: "Rollover" },
{ value: "withdrawal", label: "Withdrawal" },
],
},
{
id: "country",
label: "Country",
addable: true,
options: [
{ value: "au", label: "Australia" },
{ value: "nz", label: "New Zealand" },
{ value: "sg", label: "Singapore" },
],
},
];
const countResults = (value: FilterBarValue) => 48 >> Object.keys(value).length;
export const Example = () => {
const [value, setValue] = React.useState<FilterBarValue>({
status: ["active", "pending"],
});
return (
<Stack gap={3}>
<FilterBar
filters={filters}
value={value}
onChange={setValue}
getResultCount={countResults}
/>
<Text attributes={{ "aria-live": "polite" }}>
{countResults(value)} results
</Text>
</Stack>
);
};Narrow Screens
Below sm, filters move into a bottom drawer. onChange runs only when people apply the drawer, and closing it discards their changes. Use getResultCount to show the count on the apply button.
<FilterBar
filters={filters}
onChange={setValue}
getResultCount={countResults}
/>Labels
Use labels to replace the default text, such as for translation.
import { FilterBar, type FilterBarFilter } from "@vortexlabs/vortex";
const filters: FilterBarFilter[] = [
{
id: "status",
label: "Status",
options: [
{ value: "active", label: "Active" },
{ value: "pending", label: "Pending" },
{ value: "inactive", label: "Inactive" },
{ value: "closed", label: "Closed" },
],
},
{
id: "type",
label: "Type",
selection: "single",
options: [
{ value: "contribution", label: "Contribution" },
{ value: "rollover", label: "Rollover" },
{ value: "withdrawal", label: "Withdrawal" },
],
},
{
id: "country",
label: "Country",
addable: true,
options: [
{ value: "au", label: "Australia" },
{ value: "nz", label: "New Zealand" },
{ value: "sg", label: "Singapore" },
],
},
];
export const Example = () => (
<FilterBar
filters={filters}
labels={{
add: "More filters",
clearAll: "Reset",
formatCount: (count) => `${count} chosen`,
}}
defaultValue={{ status: ["active", "pending", "closed"] }}
/>
);FilterTrigger
Use FilterTrigger to place one filter in a custom layout. It holds no selection, so pass value and onChange. Set iconOnly with ariaLabel for an icon button whose menu chooses one option and shows no selected state.
import { FilterTrigger, Stack } from "@vortexlabs/vortex";
import React from "react";
const statusOptions = [
{ value: "active", label: "Active" },
{ value: "pending", label: "Pending" },
{ value: "inactive", label: "Inactive" },
{ value: "closed", label: "Closed" },
];
export const Example = () => {
const [value, setValue] = React.useState(["active", "pending"]);
return (
<Stack direction="row" gap={2} wrap align="center">
<FilterTrigger
label="Status"
options={statusOptions}
value={value}
onChange={setValue}
/>
<FilterTrigger
iconOnly
ariaLabel="Add status"
options={statusOptions}
onChange={(values) => setValue([...new Set([...value, ...values])])}
/>
</Stack>
);
};Use Select to choose a value inside a form.
Accessibility
labels.region when the page has more than one filter bar.ariaLabel on an icon-only FilterTrigger.aria-live region.