Zero runtime dependencies · ESM + CJS · MIT

@grida/tree-view

Headless, agnostic tree-view controller for editors and IDEs. No DOM imports in the core, no widget library on top — just a state machine plus a small set of pure helpers, and you render the rows with whatever framework and stylesheet you want.

One controller, many trees

Wire it to a real editor.

Each section below is the same TreeController wired to a working surface — a canvas, an editor pane, a desktop. Select, hover, reorder, and delete flow both ways through the package's channels. Different fixture, row renderer, and constraint stack; identical core.

Grida

Layers, wired to a canvas.

One TreeController drives the panel and the artboard. Select, hover, reorder, delete on either side — the other follows.

Cover
Actions
Get started →
Button BG
Subhead
Headline
Badge
Glow
Photo
Nothing selected
CoverShip a tree today.Headless controller · zero deps.Get started →

Drag rows to reorder · click a shape to select · ⌫ to delete

Figma

Same wiring, dark chrome.

Identical controller and intent bridge — only the row renderer and the canvas palette changed. Reordering a layer re-stacks the design.

LayersCover
Cover
Actions
Get started →
Button BG
Subhead
Headline
Badge
Glow
Photo
Nothing selected
CoverShip a tree today.Headless controller · zero deps.Get started →

Drag rows to reorder · click a shape to select · ⌫ to delete

VS Code

Explorer, opening files.

Filesystem semantics: drops resolve into the nearest folder. Selecting a file opens it — selection is the only wire to the editor pane.

Explorer
src
components
Button.tsx
Card.tsx
app
page.tsx
layout.tsx
globals.css
lib
utils.ts
api.ts
index.ts
public
favicon.ico
vercel.svg
package.json
tsconfig.json
README.md
@grida/tree-view
Select a file in the explorer to open it
Show All Commands⇧⌘P
Go to File⌘P
Find in Files⇧⌘F
Toggle Terminal⌃`
Open Settings⌘,
Finder

It just looks native.

Multi-column rows, zebra striping, double-click to expand — the same core, dressed as macOS and dropped onto the desktop.

Finder
Mon 9:41 AM
softmarshmallow
Name
Documents
grida
README.md
Notes.md
Resume.pdf
Screenshot.png
Downloads
Installer.dmg
Trailer.mp4
Applications
Figma.app
Visual Studio Code.app
Grida.app

Built for editor scale.

The state machine, the math, the intents — packaged so adopters ship a tree in a day, not a quarter.

Zero runtime dependencies

~500 LOC of business logic, ESM + CJS, full TypeScript types. Nothing else gets pulled in.

You own your data

TreeSource is read-only — wrap your editor state; the package never mutates your store.

Headless drag & drop

Pure state machine plus geometry helpers. Compose move constraints, fire move / copy intents, plug into any pointer or touch backend.

Six subscription channels

rows · expanded · focus · drag · selection · intent — fine-grained so a row only re-renders for its own slice.

Keyboard, with type-ahead

Configurable keymap dispatch, default keymap shipped (never auto-wired), platform-consistent modifier composition.

Virtualization-ready

controller.getRows() is a stable flat list — plug straight into @tanstack/react-virtual or any windowing library.

Production-grown

Driven by the same controller as the Grida editor's layers panel. The demo gallery reproduces Figma, VS Code, and Finder from one core.

Optional React peer

Core runs unchanged in Node, Bun, Deno, browser, web worker. React bindings are an opt-in /react subpath.

See every pattern.

The documentation page walks through 18 panels — themed showcases, virtualization at 10,000 rows, inline rename, type-ahead, grouping highlights, and more.