BreadcrumbTree
A breadcrumb-style picker that opens a Finder-style Miller-column panel, anchored to the breadcrumb. The panel floats above any clipping ancestor. Children are fetched on demand with pagination, results are reused when you revisit a node, and the columns auto-scroll to the deepest level.
Demo
Click the chevron to open the panel. Drill into nodes by clicking rows. Click a breadcrumb item to navigate back (the panel closes).
rootPath and fetchChildren
When rootPath is provided (e.g. "my-project"), the component prepends it to
every fetchChildren call:
| Column depth | path argument to fetchChildren |
|---|---|
| Root | "my-project" |
| After selecting "datasets" | "my-project/datasets" |
| After selecting "droid-2024" | "my-project/datasets/droid-2024" |
Without rootPath, the root call uses "" (empty string) and sub-calls use
"datasets", "datasets/droid-2024", etc.
Results are reused when you drill into the same node twice, so revisiting a folder does not trigger a second request.
Pagination
Each column loads its first page on open. Scrolling to the bottom of a column loads the next page automatically.
Floating panel
The panel floats above the content, so it is not clipped by overflow: hidden,
transform, or sticky containers. It tracks the trigger as the page scrolls or
resizes.
Controlled path —
BreadcrumbTreeis fully controlled. Row clicks callonNavigate(node, newPath); the caller updatespath. The panel stays open after a row click and closes when a breadcrumb item is clicked.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
path | BreadcrumbNode[] | — | Controlled path from root to the selected node. Empty array = root. |
onNavigate | (node, newPath) => void | — | Fires on row click (panel stays open) and breadcrumb click (panel closes). Update path here. |
fetchChildren | (path, page, limit) => Promise<FetchChildrenResult> | — | Async loader. path is slash-separated. Prepended with rootPath when set. |
rootPath | string | — | Root prefix shown as the first breadcrumb item. |
renderEmpty | (parentNode) => ReactNode | "No items" | Custom empty-state per column. Receives the parent node (null at root). |
refreshKey | number | 0 | Increment to re-fetch the deepest visible column. |
refreshToken | number | 0 | Increment to drop the whole cache after a host mutation (delete/rename). Open columns re-fetch immediately; otherwise they re-fetch fresh on next open. |
placeholder | string | "Select folder" | Shown when path is empty and rootPath is unset. |
className | string | — | Extra classes on the wrapper. |