Filter tree
A hierarchical facet for filtering a list: recursive, selectable rows that each show a count, with a single active selection. It is a controlled component — you own selectedId and it reports changes through onSelect — so the choice can drive a table or report beside it. An optional “all” row sits above the tree; built-in search matches labels and keeps any ancestor of a match, expanding the tree while a query is active. The live version is on the Groups and SOP showcases.
const nodes = [ { id: 'bu-core-platform', label: 'Core Platform', count: 42, children: [ { id: 'dept-platform-architecture', label: 'Platform Architecture', count: 18 }, { id: 'dept-infrastructure', label: 'Infrastructure', count: 14 }, { id: 'dept-reliability', label: 'Reliability', count: 10 }, ], }, // ...more BU and department nodes];
const [selectedId, setSelectedId] = useState('all');
<FilterTree nodes={nodes} selectedId={selectedId} onSelect={setSelectedId} rootLabel="All BUs" rootCount={88} aria-label="Filter by BU"/>Props
| Prop | Type | Default | Notes |
|---|---|---|---|
nodes | FilterTreeNode[] | — | The tree; nests arbitrarily via children. |
selectedId | string | — | Currently selected node id (controlled). |
onSelect | (id) => void | — | Called with the id of the clicked node. |
rootLabel | ReactNode | — | Adds a top-level “all” row above the tree when given. |
rootId | string | 'all' | Id reported when the root row is chosen. |
rootCount | number | — | Count shown on the root row. |
searchable | boolean | true | Show the search field. |
searchPlaceholder | string | 'Search' | Placeholder for the search field. |
aria-label | string | — | Names the tree for assistive tech. |
FilterTreeNode
| Prop | Type | Default | Notes |
|---|---|---|---|
id | string | — | Unique node id, reported through onSelect. |
label | ReactNode | — | Row label; string labels are searchable. |
count | number | — | Count shown on the right of the row. |
children | FilterTreeNode[] | — | Nested nodes; renders an expander. |