Search
Filter to matching nodes while keeping the path to reach them visible.
TreeKit doesn't ship a search input — you already have opinions about how that should look. Instead, it accepts a searchValue string and does the hard part: filtering to matches, keeping every ancestor needed to reach a match visible, and (optionally) auto-expanding those ancestors.
Show code
<input value={search} onChange={(e) => setSearch(e.target.value)} />
<TreeKit data={data} searchValue={search} />| Prop | Type | Default | Description |
|---|---|---|---|
| searchValue | string | — | The active search term. An empty string (default) disables filtering entirely. |
| filterFn | (node: TreeNode, value: string) => boolean | case-insensitive label match | Override how a node is tested against searchValue. |
| highlightMatches | boolean | true | Wrap the matched substring in a <mark> in the default renderer. |
| autoExpandOnSearch | boolean | true | Automatically reveal ancestors of a match, independent of expandedIds. |
Custom matching
The default matcher checks node.label case-insensitively. Provide filterFn to match against your own data field instead — useful for matching a file path, a tag list, or anything not shown in the label:
<TreeKit
data={fileTree}
searchValue={search}
filterFn={(node, value) =>
node.data?.path.toLowerCase().includes(value.toLowerCase())
}
/>Ancestors stay visible even when they don't match
Building it into your own layout
Because searchValue is just a prop, the input can live anywhere — a page header, a sidebar, a command palette. TreeKit re-filters on every render, so debounce the input yourself if you're filtering a very large tree on every keystroke (see Large Trees).