A file explorer tree built on the full WAI-ARIA tree pattern: folders open and close with a height animation and a spring on the chevron, indent guides run under every open folder and the branch holding the focus lights up, and each file gets an icon from its extension. Arrow keys walk the tree, Right and Left open, close and climb, Home and End jump, `*` opens every sibling folder and typing a name jumps to it. Single or multiple selection with Shift ranges and Cmd or Ctrl toggles, controlled or uncontrolled expansion and selection, and optional actions at the end of each row.
The import and the props worth knowing about, in one place.
import { TreeView } from "@/components/beste/component/tree-view";
<TreeView
aria-label="Project files"
items={[
{ id: "app", name: "app", children: [{ id: "app/page.tsx", name: "page.tsx" }] },
{ id: "package.json", name: "package.json" },
]}
defaultExpanded={["app"]}
/>
// Multiple selection, controlled, with an action on Enter or double click
<TreeView
items={items}
selectionMode="multiple" // "single" (default) | "multiple" | "none"
selected={selected}
onSelectedChange={setSelected}
onAction={(item) => console.log("Open", item.name)}
renderActions={(item) => <button type="button" onClick={() => console.log("Rename", item.name)}>Rename</button>}
tone="outline" // "ghost" (default) | "muted" | "outline"
size="sm" // "sm" | "default" | "lg"
/>Every one of these is in the component already. They are listed because a props table cannot mention a gesture, so nothing else on this page can tell you they exist.
| Arrow Up / Down | Move between visible items; the tree is one tab stop. |
|---|---|
| Arrow Right | Open a closed folder, or step into an open one. |
| Arrow Left | Close an open folder, or climb to the parent. |
| Home / End | Jump to the first or last visible item. |
| * | Open every folder at the focused item's level. |
| Type a name | Jump to the next item starting with the letters typed. |
| Enter / Double-click | Select the item and run onAction; without one, a folder opens or closes. |
| Space | Select the item; in multiple mode it toggles, with Shift it selects a range. |
| Shift + Arrow / Click | Extend a range in multiple mode. |
| Cmd or Ctrl + Click | Toggle one item in multiple mode. |
| Cmd or Ctrl + A | Select every visible item in multiple mode. |
Read from the component's own type, so this cannot drift from what it accepts.
| Prop | Type | Default | Description |
|---|---|---|---|
items* | TreeViewItem[] | — | |
selectionMode | "single" | "multiple" | "none" | — | "single" (default), "multiple" (Shift for ranges, Cmd or Ctrl to toggle) or "none". |
selected | string[] | — | |
defaultSelected | string[] | — | |
onSelectedChange | (ids: string[]) => void | — | |
expanded | string[] | — | |
defaultExpanded | string[] | — | |
onExpandedChange | (ids: string[]) => void | — | |
onAction | (item: TreeViewItem) => void | — | Enter or a double click on an item. |
renderActions | (item: TreeViewItem) => React.ReactNode | — | Controls at the end of a row, shown on hover, focus and selection. |
expandOnClick | boolean | — | Clicking a folder row also opens or closes it. |
guides | boolean | — | Vertical guides under each open folder; the branch holding the focus lights up. |
icons | boolean | — | File and folder icons. |
tone | "muted" | "outline" | "ghost" | — | |
size | "sm" | "default" | "lg" | — | |
className | string | — | |
aria-label | string | — |