Data

Accessible hierarchical trees for developer tools

TreeView renders nested data as an accessible, keyboard-navigable tree. Use it for file explorers, org charts, nested configuration, and any hierarchy where users expand, collapse, and select nodes.

  • workspace
      1. apps
          1. web
          2. docs
      2. packages
          1. components
          2. config
      3. package.json

Examples

TreeView renders nested data with keyboard navigation, selection state, optional indentation guides, and an animated expand/collapse variant.


  • src
      1. ui
          1. tree-view.tsx
          2. scroll-area.tsx
      2. index.ts
  • README.md

  • Components
      1. Overview
      2. TreeView
      3. Legacy table

Tree view variants examples

Use Show output / Show code on each row. Snippets start with a Variant line naming the axis and token.


Appearance: DEFAULT

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Appearance: OUTLINE

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Appearance: GHOST

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Appearance: CARD

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Appearance: SEPARATED

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Appearance: SKY

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Appearance: ROSE

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Appearance: PURPLE

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Appearance: PINK

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Appearance: ORANGE

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Appearance: YELLOW

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Appearance: TEAL

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Appearance: INDIGO

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Appearance: EMERALD

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Appearance: GRADIENT-BLUE

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Appearance: GRADIENT-GREEN

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Appearance: GRADIENT-RED

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Appearance: GRADIENT-YELLOW

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Appearance: GRADIENT-PURPLE

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Appearance: GRADIENT-TEAL

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Appearance: GRADIENT-INDIGO

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Appearance: GRADIENT-PINK

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Appearance: GRADIENT-ORANGE

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Appearance: OUTLINE | Size: SM

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Appearance: OUTLINE | Size: MD

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Appearance: OUTLINE | Size: LG

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Indentation guides: ON | Appearance: GHOST

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Animated transition: NONE | Appearance: SKY

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Animated transition: DEFAULT | Appearance: SKY

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Animated transition: SMOOTH | Appearance: SKY

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md

Animated transition: SLOW | Appearance: SKY

  • app
      1. preview
          1. page.tsx
          2. layout.tsx
      2. globals.css
  • components
      1. tree-view.tsx
      2. scroll-area.tsx
      3. draft.tsx
  • README.md
CSS variable overrides

TreeView CSS variables

Override these TreeView variables on :root, a theme selector, or a component wrapper.

137 variables

Pattern: --zui-<component>-<slot?>-<variant?>-<property>-<state?>-dark?

:root {
  --zui-tree-view-card-bg: #0000000d;
  --zui-tree-view-card-border: #0000001a;
  --zui-tree-view-chevron: oklch(55.5% 0.041 257.417);
  --zui-tree-view-default-border: #0000001a;
  --zui-tree-view-emerald-border: oklch(43.2% 0.095 166.913);
  --zui-tree-view-emerald-selected: oklch(95% 0.052 163.051);
  --zui-tree-view-emerald-selected-fg: oklch(43.2% 0.095 166.913);
  --zui-tree-view-fg: oklch(20.8% 0.042 265.755);
  --zui-tree-view-gradient-blue-border: oklch(42.4% 0.199 265.638);
  --zui-tree-view-gradient-blue-from: oklch(80.9% 0.105 251.813);
  --zui-tree-view-gradient-blue-to: oklch(82.7% 0.119 306.383);
  --zui-tree-view-gradient-fg: #ffffff;
  --zui-tree-view-gradient-green-border: oklch(44.8% 0.119 151.328);
  --zui-tree-view-gradient-green-from: oklch(87.1% 0.15 154.449);
  --zui-tree-view-gradient-green-to: oklch(89.7% 0.196 126.665);
  --zui-tree-view-gradient-indigo-border: oklch(39.8% 0.195 277.366);
  --zui-tree-view-gradient-indigo-from: oklch(78.5% 0.115 274.713);
  --zui-tree-view-gradient-indigo-to: oklch(82.7% 0.119 306.383);
  --zui-tree-view-gradient-orange-border: oklch(47% 0.157 37.304);
  --zui-tree-view-gradient-orange-from: oklch(83.7% 0.128 66.29);
  --zui-tree-view-gradient-orange-to: oklch(80.8% 0.114 19.571);
  --zui-tree-view-gradient-pink-border: oklch(45.9% 0.187 3.815);
  --zui-tree-view-gradient-pink-from: oklch(82.3% 0.12 346.018);
  --zui-tree-view-gradient-pink-to: oklch(81% 0.117 11.638);
  --zui-tree-view-gradient-purple-border: oklch(43.8% 0.218 303.724);
  --zui-tree-view-gradient-purple-from: oklch(82.7% 0.119 306.383);
  --zui-tree-view-gradient-purple-to: oklch(82.3% 0.12 346.018);
  --zui-tree-view-gradient-red-border: oklch(44.4% 0.177 26.899);
  --zui-tree-view-gradient-red-from: oklch(80.8% 0.114 19.571);
  --zui-tree-view-gradient-red-to: oklch(82.3% 0.12 346.018);
  --zui-tree-view-gradient-teal-border: oklch(43.7% 0.078 188.216);
  --zui-tree-view-gradient-teal-from: oklch(85.5% 0.138 181.071);
  --zui-tree-view-gradient-teal-to: oklch(86.5% 0.127 207.078);
  --zui-tree-view-gradient-yellow-border: oklch(47.6% 0.114 61.907);
  --zui-tree-view-gradient-yellow-from: oklch(90.5% 0.182 98.111);
  --zui-tree-view-gradient-yellow-to: oklch(83.7% 0.128 66.29);
  --zui-tree-view-guide: #0000001a;
  --zui-tree-view-icon: oklch(55.5% 0.041 257.417);
  --zui-tree-view-indigo-border: oklch(39.8% 0.195 277.366);
  --zui-tree-view-indigo-selected: oklch(93% 0.034 272.788);
  --zui-tree-view-indigo-selected-fg: oklch(39.8% 0.195 277.366);
  --zui-tree-view-item-hover: #0000000d;
  --zui-tree-view-orange-border: oklch(47% 0.157 37.304);
  --zui-tree-view-orange-selected: oklch(95.4% 0.038 75.164);
  --zui-tree-view-orange-selected-fg: oklch(47% 0.157 37.304);
  --zui-tree-view-outline-border: #00000026;
  --zui-tree-view-pink-border: oklch(45.9% 0.187 3.815);
  --zui-tree-view-pink-selected: oklch(94.8% 0.028 342.258);
  --zui-tree-view-pink-selected-fg: oklch(45.9% 0.187 3.815);
  --zui-tree-view-purple-border: oklch(43.8% 0.218 303.724);
  --zui-tree-view-purple-selected: oklch(94.6% 0.033 307.174);
  --zui-tree-view-purple-selected-fg: oklch(43.8% 0.218 303.724);
  --zui-tree-view-ring-focus: #0000004d;
  --zui-tree-view-rose-border: oklch(45.5% 0.188 13.697);
  --zui-tree-view-rose-selected: oklch(94.1% 0.03 12.58);
  --zui-tree-view-rose-selected-fg: oklch(45.5% 0.188 13.697);
  --zui-tree-view-selected: #00000014;
  --zui-tree-view-selected-fg: oklch(20.8% 0.042 265.755);
  --zui-tree-view-separated-bg: oklch(98.4% 0.003 247.858 / 0.4);
  --zui-tree-view-separated-border: #0000001a;
  --zui-tree-view-sky-border: oklch(44.3% 0.11 240.79);
  --zui-tree-view-sky-selected: oklch(95.1% 0.026 236.824);
  --zui-tree-view-sky-selected-fg: oklch(44.3% 0.11 240.79);
  --zui-tree-view-teal-border: oklch(43.7% 0.078 188.216);
  --zui-tree-view-teal-selected: oklch(95.3% 0.051 180.801);
  --zui-tree-view-teal-selected-fg: oklch(43.7% 0.078 188.216);
  --zui-tree-view-yellow-border: oklch(47.6% 0.114 61.907);
  --zui-tree-view-yellow-selected: oklch(97.3% 0.071 103.193);
  --zui-tree-view-yellow-selected-fg: oklch(47.6% 0.114 61.907);
}

/* Dark theme variables follow the same names with -dark appended. */
.dark {
  --zui-tree-view-card-bg-dark: #00000099;
  --zui-tree-view-card-border-dark: #ffffff1a;
}

What it does

TreeView turns an array of nested nodes into an accessible tree with expandable branches and selectable leaves.

It manages expansion and selection state (controlled or uncontrolled), roving tabindex focus, and full keyboard navigation, while leaving node rendering open through renderNode.

Composition and API

Pass a data array of nodes, each with an id, label, optional icon, optional disabled flag, and optional children. Use defaultExpanded or expanded for expansion, defaultSelected or selected for selection, and onSelect and onExpandedChange for events. Variants such as appearance, size, and showGuides theme the container and indentation.

Common use cases

Use TreeView for file and folder explorers, nested navigation, settings categories, taxonomy editors, and org charts. The renderNode prop lets each row carry icons, badges, counts, or inline actions while the component keeps accessibility and keyboard behavior consistent.

Accessibility

The container uses role=tree and each node uses role=treeitem with aria-expanded, aria-selected, aria-level, and aria-disabled. A roving tabindex keeps one node in the tab order, and arrow keys, Home, End, Enter, and Space follow the WAI-ARIA tree interaction pattern.

Next.js integration notes

TreeView ships as a client-safe package entry because it owns focus and keyboard state. Render it inside App Router preview pages while keeping SEO content server-rendered, and reach for the ui/tree-view/animated entry only when you want motion on expand and collapse.

FAQ

Is TreeView keyboard accessible?

Yes. TreeView implements the WAI-ARIA tree pattern: arrow keys move between visible nodes, ArrowRight expands or steps into children, ArrowLeft collapses or steps to the parent, Home and End jump to the first and last node, and Enter or Space selects.

How do I control which nodes are expanded?

Pass defaultExpanded for uncontrolled state, or expanded plus onExpandedChange for controlled state. Selection works the same way with defaultSelected or selected plus onSelect.

Does the animated variant require Framer Motion?

Only the animated entry imports framer-motion. Import TreeView from ui/tree-view for the static version, or TreeViewAnimated from ui/tree-view/animated for spring-based expand and collapse.