File Tree
A hierarchical file explorer with expand/collapse, drag-and-drop, icons, and multi-selection support.
Usage
Anatomy
Import the FileTree component and access all parts using dot notation.
import { FileTree } from "@blakeui/pro-react";
<FileTree>
<FileTree.Section>
<FileTree.Header />
<FileTree.Item>
<FileTree.Indicator />
<FileTree.Item />
</FileTree.Item>
</FileTree.Section>
</FileTree>;Reduced Motion
reduceMotion disables the expand/collapse animation; the user's own reduced-motion preference is always honoured regardless of this prop.
Animated (default)
reduceMotion
With Icons
Custom Indicator
Drag and Drop
Dynamic Collection
Sizes
sm
md
lg
Guide Lines
showGuideLines=true (default)
showGuideLines="hover"
showGuideLines=false
Multiple Selection
2 selected
PR File Review
CSS Classes
Base & Size Classes
.file-tree— Root tree container. Flex column,padding: --spacing * 1, scrolls on overflow..file-tree--sm— Small:--file-tree-indent: --spacing * 2.5,--file-tree-item-px: 10px..file-tree--md— Medium (default):--file-tree-indent: --spacing * 3,--file-tree-item-px: 12px..file-tree--lg— Large:--file-tree-indent: --spacing * 6,--file-tree-item-px: 8px..file-tree__item--sm— Small row:0.75rem/1remtext,3.5 * --spacingicons..file-tree__item--md— Medium row:0.875rem/1.25remtext,4 * --spacingicons..file-tree__item--lg— Large row:1rem/1.5remtext,5 * --spacingicons.
Element Classes
.file-tree__item— A row. Relative, flex,border-radius: --radius * 1,color: --foreground..file-tree__item-content— Row layout wrapper. Indents by(--tree-item-level - 1) * --file-tree-indent..file-tree__guide-line— One 1px absolute vertical rule per ancestor level, painted in--file-tree-guide-color..file-tree__guide-line--hover— Guide lines start atopacity: 0and fade in over0.15swhile the tree is hovered..file-tree__guide-line--none— Guide lines removed (display: none)..file-tree__checkbox— Selection checkbox wrapper, rendered only whenselectionModeis not"none"and the selection behaviour is"toggle"..file-tree__chevron— The expand/collapse button,5 * --spacingsquare.visibility: hiddenuntil the row has children..file-tree__indicator— The glyph inside the chevron,3.5 * --spacingsquare,color: --muted,transition: rotate 0.15s..file-tree__icon— Leading icon slot,color: --muted. Sizes itssvgper row size..file-tree__label— The row label.flex: 1, truncates with an ellipsis,user-select: none..file-tree__section— A group of rows. Adds--spacing * 3top margin when it isn't the first child..file-tree__section-header— Section heading.0.75rem/1rem,font-weight: 500,color: --muted..file-tree__drag-handle— Grip button,5 * --spacingsquare,opacity: 0at rest,cursor: grab.
Interactive States
- Hover —
.file-tree__item:hover/[data-hovered="true"]applies--default. Suppressed while the chevron itself is hovered, via:not(:has(.file-tree__chevron:hover)). Under@media (hover: hover)only. - Pressed —
.file-tree__item:active/[data-pressed="true"]applies--default-hover. - Focus visible —
.file-tree__item:focus-visible/[data-focus-visible="true"]draws a--focusring offset by--ring-offset-width. The tree root carries the same ring under.file-tree[data-focus-visible]. - Disabled —
[aria-disabled="true"]applies--disabled-opacity,--cursor-disabled, andpointer-events: none. - Selected —
[data-selected="true"]applies--default. Adjacent selected rows drop their shared corners so a run reads as one capsule. - Expanded —
[data-expanded]rotates.file-tree__indicatorto90deg. - Has children —
[data-has-child-items]reveals.file-tree__chevron; hovering it applies--default-hover. - Dragging —
[data-dragging]drops the row toopacity: 0.4. The handle fades to0.4on row hover and0.7on its own hover. - Drop target —
[data-drop-target]applies--accent-softwith a 2px inset--accentoutline. The between-rows.react-aria-DropIndicator[data-drop-target]takes a 1px--accentoutline. - Empty —
.file-tree[data-empty]centres an italic--mutedplaceholder atmin-height: 100px. - Reduced motion —
@media (prefers-reduced-motion: reduce)removes the indicator's rotate transition.
CSS Variables
--file-tree-indent— Indent added per nesting level. Set by the size classes.--file-tree-item-px— Horizontal offset the guide lines are measured from. Set by the size classes.--file-tree-guide-color— Guide-line colour. Defaults tocolor-mix(in srgb, currentColor 10%, transparent).--tree-item-level— Consumed, not defined: React Aria sets it per row, and.file-tree__item-contentmultiplies it by--file-tree-indentfor the indent.
API Reference
FileTree
The root. Renders React Aria's Tree, and supplies the size and guide-line context every part reads.
| Prop | Type | Default | Description |
|---|---|---|---|
size | "sm" | "md" | "lg" | "md" | Row size. Drives row padding, font size, icon size, and indent width together. |
showGuideLines | boolean | "hover" | true | Vertical indentation guides. true always, false never, "hover" fades them in while the tree is hovered. |
reduceMotion | boolean | false | Disables the expand/collapse height animation. The user's prefers-reduced-motion setting disables it regardless, so this is an additional opt-out, not an override. |
items | Iterable<T> | — | Data for a dynamic collection. Pass a render function as children, and nest with Collection from react-aria-components. |
dragAndDropHooks | DragAndDropHooks | — | Enables row reordering. Supply the value returned by useFileTreeDrag. |
selectionMode | "none" | "single" | "multiple" | "none" | Selection behaviour. A checkbox is rendered per row when rows are selectable. |
…TreeProps | TreeProps<T> | — | Every remaining React Aria Tree prop — defaultExpandedKeys, expandedKeys, onExpandedChange, selectedKeys, onSelectionChange, disabledKeys, onAction. |
FileTree.Item
A row. Nest items inside one another to build the hierarchy; a row with child items gets a chevron.
| Prop | Type | Default | Description |
|---|---|---|---|
title | ReactNode | — | The row label. Accepts arbitrary content — pair it with textValue whenever it isn't a plain string. |
icon | ReactNode | ((state) => ReactNode) | — | A leading icon, or a function of the row's state — {isExpanded, hasChildItems, allowsDragging} — which is how folders show open and closed glyphs. |
textValue | string | title | The row's plain-text value, used for typeahead and assistive tech. Falls back to title when that is a string, so it is required for aReactNode title — otherwise the row has no accessible name. |
dragIcon | ReactNode | false | Dotted grip | The drag handle, shown only when dragging is enabled. false hides it while leaving the row draggable. |
id | Key | — | The row's key — what expandedKeys, selectedKeys, and disabledKeys refer to. |
…TreeItemProps | TreeItemProps | — | Every remaining React Aria TreeItem prop, including href and onAction. |
FileTree.Indicator
Replaces the expand/collapse chevron. Place it as a direct child of the FileTree.Item it belongs to — it is detected by identity, so wrapping it in another component hides it from the row.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactElement | ChevronRight | The glyph to use. It is cloned with the .file-tree__indicator class, so it inherits the muted colour, the size, and the 90° rotation on expand. |
className | string | — | Appended to the indicator's own class. |
FileTree.Section
Groups rows under an optional header.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | An optional FileTree.Header followed by the section's rows. |
className | string | — | Appended to the section's own class. |
…TreeSectionProps | TreeSectionProps<T> | — | Every remaining React Aria TreeSection prop. |
FileTree.Header
The label above a section's rows.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | The heading content. |
className | string | — | Appended to the header's own class. |
…TreeHeaderProps | TreeHeaderProps | — | Every remaining React Aria TreeHeader prop. |
useFileTree
Derives the values a tree UI usually needs from a nested data array — without walking it by hand.
const { expandableKeys, filterTree, leaves } = useFileTree({ items });| Option | Type | Default | Description |
|---|---|---|---|
items | T[] | — | The tree data. Each node needs an id and may carry children. Required. |
isLeaf | (node: T) => boolean | no children | Identifies non-expandable nodes — override it when an empty folder should still count as a branch. |
| Property | Type | Default | Description |
|---|---|---|---|
expandableKeys | Key[] | — | Every branch key, in depth-first order — pass it to defaultExpandedKeys for an expand-all. |
leaves | T[] | — | Every leaf node, flattened — the file count, a search index, a select-all set. |
filterTree | (predicate: (node: T) => boolean) => T[] | — | Filters by a leaf predicate and prunes branches left empty, so ancestors of a match survive and everything else drops. |
useFileTreeDrag
Wires React Aria drag-and-drop to a useTreeData instance, so rows can be reordered and re-parented.
const { dragAndDropHooks } = useFileTreeDrag({ tree });| Option | Type | Default | Description |
|---|---|---|---|
tree | FileTreeDataLike | — | The useTreeData instance backing the tree. Only getItem, move, moveBefore, and moveAfter are used. Required. |
getItems | (keys: Set<Key>) => Array<Record<string, string>> | text/plain | The drag payload per item. Defaults to each key as plain text. |
onMove | (keys, target) => void | — | Runs after a successful move, with the moved keys and the resolved drop target. |
| Property | Type | Default | Description |
|---|---|---|---|
dragAndDropHooks | DragAndDropHooks | — | Pass straight to the tree's dragAndDropHooks prop. Drops resolve to moveBefore, moveAfter, or an append via move, depending on where the row lands. |