A file tree is two components wearing one name. One is a picture: the folder structure of a project, shown on a documentation page so a reader can see where files go. The other is a control: an explorer someone navigates, selects in and acts on. They share a shape and share almost nothing else.
31 public components on 21st have "tree" in the name. Deciding which of the two you are building is the whole job.
The picture
Static, decorative, usually beside an install command. File Tree by dillionverma and File Tree by Jatin Yadav are the documentation shapes, the second with expand and collapse.
For this version, keep it simple and keep it text. It is a nested list, and its whole value is that a reader can scan it and copy a path out of it. Do not put it in a canvas, do not animate it, and make sure the file names are selectable.
The control
An explorer: keyboard navigable, selectable, sometimes with drag and drop and a context menu. Tree View by preetsuthar17 and Tree by Hayden Bleasel are the interactive versions.
This one has a real specification, and it is the most demanding keyboard contract of any common component. One tab stop for the whole tree, arrows to move: down and up through visible nodes, right to expand or descend, left to collapse or ascend. Typeahead jumps to a node by name. Home and End go to the ends. Every node exposes its level, its position among siblings and whether it is expanded.
That is a lot, and it is the reason to take the behaviour from a library rather than write it. A tree built from nested divs with click handlers is unusable without a mouse, and unlike a menu, nobody notices until someone tries.
Performance, which arrives sooner than you think
A repository tree with ten thousand nodes rendered eagerly is ten thousand DOM elements before anyone expands anything. Three rules keep it usable.
Render only expanded branches. A collapsed folder's children should not exist in the DOM at all.
Virtualise the visible rows past a few hundred, the same as the data table guide describes, remembering that it breaks find-in-page.
Load children on demand for anything backed by a network. An explorer that fetches the whole tree to show the root is the slowest possible first paint.
The details that make it feel right
Indentation guides. Vertical lines at each level, drawn with a border on a pseudo-element rather than as elements, because a deep tree is otherwise impossible to read.
Icons that say something. A folder open and closed, and a file icon by extension if you have one. Decorative, so aria-hidden, with the name carrying the meaning.
Selection separate from expansion. Clicking the chevron expands; clicking the name selects. Conflating them makes browsing impossible without changing the selection.
A stable order. Folders before files, then alphabetical. Whatever the API returns is not an order.
Where else to look
The honest list, because the answer is not always us:
| Source | Best for | Trade-off |
|---|---|---|
A nested <ul> | The documentation picture, which is most uses | Not a control |
| React Aria | The full tree keyboard and screen reader contract | More API, and the visuals are yours |
| TanStack Virtual | Large trees at a stable frame rate | Breaks find-in-page |
| 21st | Documentation trees and interactive explorers | Quality varies by author, so preview before you take it |
Taking one
Every component page has a live preview and the code. Installing goes through the shadcn CLI against our registry:
That key comes from your 21st account, and installs require a membership. Set API_KEY_21ST once in your shell and the command works for anything in the catalogue.
Frequently asked
- What is the keyboard contract for a tree view?
- One tab stop for the whole tree, arrows to navigate: down and up through visible nodes, right to expand or descend, left to collapse or ascend. Typeahead jumps by name, Home and End reach the ends, and each node exposes its level, position among siblings and expanded state.
- How do you keep a large file tree fast?
- Do not render collapsed branches at all, virtualise the visible rows past a few hundred, and load children on demand when the tree is backed by a network. Fetching an entire repository tree to display the root is the slowest possible first paint.
- Should clicking a folder name expand it?
- Keep selection and expansion separate: the chevron expands, the name selects. Conflating them makes it impossible to browse the structure without changing what is selected, which is the most common complaint about hand-built explorers.
- What does a documentation file tree need?
- Much less. It is a nested list whose value is that a reader can scan it and copy a path out of it, so keep the names as real selectable text, skip the animation, and never render it into a canvas.



