Skip to Content
Hashti Design System
Components

Tree

Hierarchical data grid for visualizing nested folders, file explorers, and deep parent-child navigation.

Tree

A Tree displays hierarchical data structured into expandable and collapsible branches. It is standard for file directory browsers, organization charts, categorized product taxonomies, and nested JSON/code inspectors.

Built upon React Aria Components’ Tree pattern, Hashti unites architectural TreeView elegance with RAC’s accessible treegrid implementation. Features include optional architectural guideline rules (showGuideLines), recursive chevron indicators, multi-item selection with checkboxes, and keyboard branch navigation.

Live Interactive Navigation TreeKeyboard roving arrow navigation and link href routing.
Spatial Sequences

Import

import { Tree } from "@hashti/react";
// Or named subcomponents:
// Tree.Root, Tree.Item, Tree.Indicator, Tree.Content, Tree.Checkbox

Anatomy

<Tree aria-label="Project filesystem">
  <Tree.Item textValue="src">
    <Tree.Indicator />
    <Tree.Content>src</Tree.Content>
    <Tree.Item textValue="components">
      <Tree.Indicator />
      <Tree.Content>components</Tree.Content>
    </Tree.Item>
  </Tree.Item>
</Tree>

Examples

File Directory Explorer

Construct a multi-level file hierarchy with custom folder and document icons:

import { Tree, Icon } from "@hashti/react";

const fileHierarchy = [
  {
    id: "src",
    name: "src",
    type: "folder",
    children: [
      {
        id: "components",
        name: "components",
        type: "folder",
        children: [
          { id: "button.tsx", name: "button.tsx", type: "file" },
          { id: "toolbar.tsx", name: "toolbar.tsx", type: "file" },
          { id: "tree.tsx", name: "tree.tsx", type: "file" },
        ],
      },
      { id: "index.ts", name: "index.ts", type: "file" },
      { id: "styles.css", name: "styles.css", type: "file" },
    ],
  },
  { id: "package.json", name: "package.json", type: "file" },
  { id: "README.md", name: "README.md", type: "file" },
];

export function FileTreeExplorer() {
  return (
    <div className="max-w-md p-4 border border-[var(--divider)] rounded-lg">
      <h3 className="text-sm font-semibold mb-3">Project Directory</h3>
      <Tree aria-label="Filesystem Tree" items={fileHierarchy} showGuideLines size="md">
        {function renderItem(item: any) {
          const isFolder = item.type === "folder";
          return (
            <Tree.Item key={item.id} textValue={item.name}>
              <div className="flex items-center gap-2 py-1">
                {isFolder && <Tree.Indicator />}
                <Icon
                  name={isFolder ? "menu" : "edit"}
                  size={16}
                  className="text-[var(--text-muted)]"
                />
                <Tree.Content>{item.name}</Tree.Content>
              </div>
              {item.children && item.children.map(renderItem)}
            </Tree.Item>
          );
        }}
      </Tree>
    </div>
  );
}

Multi-Item Selection with Checkboxes

Enable batch selection across parent and child nodes by setting selectionMode="multiple" and including <Tree.Checkbox />:

import { useState } from "react";
import { Tree } from "@hashti/react";
import type { Selection } from "react-aria-components";

export function SelectableTreeExample() {
  const [selected, setSelected] = useState<Selection>(new Set(["button.tsx"]));

  return (
    <div className="max-w-md space-y-3">
      <Tree
        aria-label="Export file selection"
        selectionMode="multiple"
        selectedKeys={selected}
        onSelectionChange={setSelected}
      >
        <Tree.Item id="frontend" textValue="Frontend">
          <div className="flex items-center gap-2 py-1">
            <Tree.Indicator />
            <Tree.Checkbox />
            <Tree.Content>Frontend Applications</Tree.Content>
          </div>
          <Tree.Item id="docs" textValue="Documentation">
            <div className="flex items-center gap-2 py-1">
              <Tree.Indicator />
              <Tree.Checkbox />
              <Tree.Content>Astro Docs</Tree.Content>
            </div>
          </Tree.Item>
          <Tree.Item id="storybook" textValue="Storybook">
            <div className="flex items-center gap-2 py-1">
              <Tree.Indicator />
              <Tree.Checkbox />
              <Tree.Content>Storybook Workshop</Tree.Content>
            </div>
          </Tree.Item>
        </Tree.Item>
      </Tree>
    </div>
  );
}

Guide Lines

The showGuideLines prop renders subtle vertical alignment lines connecting nested child rows to their ancestor folders. This aids visual scanning in deeply nested hierarchies (4+ levels deep).

<Tree showGuideLines={true} aria-label="Deeply nested tree">
  {/* Nested items */}
</Tree>

Props Reference

Tree (Tree.Root)

PropTypeDefaultDescription
selectionMode'none' | 'single' | 'multiple''none'Row selection mode.
selectedKeys'all' | Iterable<Key>—Currently selected node keys.
onSelectionChange(keys: Selection) => void—Callback fired on selection change.
expandedKeys'all' | Iterable<Key>—Keys of nodes currently expanded.
defaultExpandedKeys'all' | Iterable<Key>—Keys expanded initially.
onExpandedChange(keys: Set<Key>) => void—Callback fired when branches expand or collapse.
showGuideLinesbooleantrueWhether to display vertical dashed branch guideline rules.
size'sm' | 'md''md'Row height and indentation density.
aria-labelstring—Accessible tree description.

Tree.Item (TreeItem)

PropTypeDefaultDescription
idKey—Unique key identifying this tree node.
textValuestring—Plain text string used for keyboard typeahead navigation.
isDisabledbooleanfalseWhether this node cannot be expanded or selected.

Tree.Indicator (TreeIndicator)

PropTypeDefaultDescription
childrenReactNode<Icon name="chevronRight" />Expand/collapse arrow. Rotates 90° when expanded.

Tree.Checkbox (TreeCheckbox)

PropTypeDefaultDescription
childrenReactNode—Optional custom checkbox label.

Keyboard Interactions

Hashti Tree adheres to the WAI-ARIA Treegrid Pattern:

KeyAction
→When on a collapsed node, expands the branch. When on an expanded node, moves focus to the first child.
←When on an expanded node, collapses the branch. When on a child node, moves focus to the parent node.
↓ / ↑Moves focus vertically between visible nodes without expanding closed branches.
Enter / SpaceToggles node selection or activates the primary action.
* (Asterisk)Expands the focused node and all its siblings at the same depth.
Home / EndMoves focus directly to the first or last visible node.

Hashti Token Bindings

TokenCSS VariableApplied Element
Guideline Stroke--divider1px vertical branch indentation guide
Selected Surface--selected (#e7edff)Highlight background for selected nodes
Focus Ring--focus2px focus border on active node
Hover State--surface-hoverSubtle row hover feedback
Text Main--textPrimary node label
Text Muted--text-mutedFile icons and metadata

Keyboard Interactions

KeyAction
↓ / ↑Navigates between visible tree nodes.
→Expands collapsed branch node, or moves into first child.
←Collapses expanded branch node, or moves back to parent.
Home / EndJumps to the first or last visible tree node.
SpaceToggles node selection.

WAI-ARIA & Data Attributes

AttributeTargetDescription
[data-hovered]Tree NodeActive on pointer hover.
[data-selected]Tree NodeSet when tree item is selected.
[data-expanded]Tree BranchPresent on expanded branch nodes.
[data-focused]Tree NodeSet when tree item holds focus.