- Accordion
- Action BarUpdated
- Alert Dialog
- Alert
- Announcement
- Aspect Ratio
- Autocomplete
- Avatar
- BadgeUpdated
- Bottom Navigation
- Breadcrumb
- Button Group
- Button
- CalendarUpdated
- CardUpdated
- Carousel
- Chart
- Checkbox
- Circular Progress
- Circular Slider
- Clipboard
- Collapsible
- Color Picker
- Combobox
- Command
- Context MenuUpdated
- Data List
- Date Picker
- DialogUpdated
- DrawerUpdated
- Editable
- FieldUpdated
- File Upload
- Float
- Floating Panel
- Frame
- Hint
- Hover Card
- Image Cropper
- Input Group
- Input OTP
- Input
- Item
- Kbd
- Link Overlay
- Listbox
- MarqueeUpdated
- Menu
- Native Select
- Number InputUpdated
- Pagination
- Popover
- Progress
- Prose
- QR Code
- Radio Group
- Rating
- Resizable
- Scroll Area
- Segment Group
- Select
- Separator
- Sheet
- Sidebar
- Signature Pad
- Skeleton
- Skip Nav
- Slider
- Spinner
- Status
- Steps
- Switch
- TableUpdated
- Tabs
- Textarea
- TimerUpdated
- ToastUpdated
- Toggle Group
- Toggle Tooltip
- Toggle
- Tooltip
- Tour
- Tree View
Installation#
pnpm dlx shadcn@latest add @shark/tree-view
Anatomy#
TreeView ├── TreeViewLabel └── TreeViewTree └── TreeViewNode ├── TreeViewBranch │ ├── TreeViewBranchItem │ │ └── TreeViewBranchIndicator │ └── TreeViewBranchContent │ └── TreeViewNode … └── TreeViewContent └── TreeViewItem └── TreeViewCheckbox
Usage#
import { TreeView, TreeViewLabel, TreeViewTree, TreeViewNode, TreeViewBranch, TreeViewBranchItem, TreeViewBranchContent, TreeViewContent, TreeViewItem, createTreeCollection, } from "@/components/ui/tree-view";
const collection = createTreeCollection({ rootNode: { id: "ROOT", name: "", children: [...] }, }); const Example = () => ( <TreeView collection={collection}> <TreeViewTree> {collection.rootNode.children?.map((node, index) => ( <TreeNode indexPath={[index]} key={node.id} node={node} /> ))} </TreeViewTree> </TreeView> ) const TreeNode = (props: React.ComponentProps<typeof TreeViewNode>) => { const { node, indexPath } = props; return ( <TreeViewNode indexPath={indexPath} key={node.id} node={node}> {node.children ? ( <TreeViewBranch> <TreeViewBranchItem>{node.name}</TreeViewBranchItem> <TreeViewBranchContent> {node.children.map((child, index) => ( <TreeNode indexPath={[...indexPath, index]} key={child.id} node={child} /> ))} </TreeViewBranchContent> </TreeViewBranch> ) : ( <TreeViewContent> <TreeViewItem>{node.name}</TreeViewItem> </TreeViewContent> )} </TreeViewNode> ); };
Controlled#
Use selectedValue and onSelectionChange to control the selected node and react to selection changes.
Select input.tsx
❌
Examples#
Multiple selection#
Use selectionMode="multiple" to allow selecting multiple nodes.
Hold Shift and click to select a range, or use Ctrl/Cmd+click to toggle individual nodes.
With Context Menu#
Right-click on tree items to show a context menu.
Renaming nodes#
Use the canRename prop and onRenameComplete callback to enable inline renaming of nodes. Press F2 to activate rename mode on the focused node.
With checkboxes#
Use the checkedValue and onCheckedChange props to control the checked nodes.
[ "readme.md" ]
Links#
Tree items can be rendered as links. Use asChild on TreeViewContent and wrap an <a> element with TreeViewItem inside.
Docs
Mini Editor#
Use the tree view to create a file editor.
Custom icons#
There are three ways to customize icons:
- Folder —
iconandexpandedIconprops onTreeViewBranchItem, or per-node viaTreeNodeType - Single item —
iconprop onTreeViewItem - By extension —
fileIconsprop onTreeViewwithcreateFileIcons
Folder icons#
Use the icon and expandedIcon props on TreeViewBranchItem to customize folder icons. Pass null to hide the icon.
Single item icon#
Pass the icon prop to TreeViewItem to override the icon for a specific leaf node.
With file extensions#
Use the fileIcons prop on TreeView with createFileIcons to map file extensions to icon components. Icons are resolved from each node's id; unmatched extensions fall back to FileIcon.
API Reference#
TreeView#
Root component. Provides tree context and manages expand/selection state.
| Prop | Type | Default |
|---|---|---|
collection | TreeCollection | required |
fileIcons | Record<string, React.JSX.ElementType | null> | - |
selectedValue | string[] | - |
checkedValue | string[] | - |
onCheckedChange | (details: CheckedChangeDetails) => void | - |
canRename | (details: RenameDetails) => boolean | - |
onRenameComplete | (details: RenameCompleteDetails) => void | - |
defaultSelectedValue | string[] | - |
onSelectionChange | (details: SelectionChangeDetails) => void | - |
expandedValue | string[] | - |
defaultExpandedValue | string[] | - |
onExpandedChange | (details: ExpandedChangeDetails) => void | - |
selectionMode | "single" | "multiple" | "single" |
lazyMount | boolean | true |
unmountOnExit | boolean | true |
className | string | - |
| Attribute | Default |
|---|---|
--indentation | --spacing(4) |
--item-gap | --spacing(2) |
--padding-block | --spacing(1.5) |
--padding-inline | --spacing(3) |
--icon-size | --spacing(4) |
TreeViewLabel#
Accessible label for the tree.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
className | string | - |
TreeViewTree#
Wraps the root-level tree nodes.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
className | string | - |
TreeViewNode#
Provides tree node context. Must wrap each branch or item.
| Prop | Type | Default |
|---|---|---|
node | TreeNodeType | required |
indexPath | number[] | required |
className | string | - |
TreeViewBranch#
Expandable branch with children. Toggles open/closed.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
className | string | - |
TreeViewBranchItem#
Clickable area to expand or collapse a branch.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
icon | React.JSX.ElementType | null | FolderIcon |
expandedIcon | React.JSX.ElementType | null | FolderOpenIcon |
className | string | - |
TreeViewBranchContent#
Holds the branch children. Shown when expanded.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
className | string | - |
TreeViewContent#
Wrapper for leaf (non-expandable) items.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
className | string | - |
TreeViewItem#
Leaf node (non-expandable). The icon prop is fallback when no fileIcons match.
| Prop | Type | Default |
|---|---|---|
icon | React.JSX.ElementType | FileIcon |
className | string | - |
TreeViewCheckbox#
Checkbox for selecting a node in multi-select mode.
| Prop | Type | Default |
|---|---|---|
className | string | - |
createTreeCollection#
Creates a tree collection from node data. Use with collection prop on TreeView.
Options
| Prop | Type | Default |
|---|---|---|
rootNode | T extends TreeNodeType | required |
nodeToValue | (node: T) => string | (node) => node.id |
nodeToString | (node: T) => string | (node) => node.name |
TreeNodeType — Shape of each node (extend with generic T for custom props):
| Property | Type | Default |
|---|---|---|
id | string | - |
name | string | - |
children | TreeNodeType<T>[] | undefined |
icon | React.JSX.ElementType | null | undefined |
expandedIcon | React.JSX.ElementType | null | undefined |
const collection = createTreeCollection({ rootNode: { id: "ROOT", name: "", children: [...] }, }); // With custom node props type LinkNode = TreeNodeType & { href?: string }; const links = createTreeCollection<LinkNode>({ rootNode: { id: "docs", name: "Docs", children: [{ id: "intro", name: "Intro", href: "/intro" }], }, });
createFileIcons#
Creates a type-safe mapping of file extensions to icon components. Use with fileIcons prop on TreeView.
Keys use dotted extensions.
const fileIcons = createFileIcons({ ".tsx": FileCode, ".json": FileJson, ".md": FileText, });
For a complete list of props, see the Ark UI documentation.
On This Page