Tree view component

Hierarchical, expandable/collapsible list for nested data — file explorers, settings navigation, nested categories, org structures — with optional tri-state cascading checkboxes, lazy child loading, and full keyboard + ARIA tree semantics. Modeled after Fluent 2 TreeView (and the WAI-ARIA tree pattern). Distinct from a flat list and from a data table.

Status: v0.1.0 — Draft. Promoted from the Microsoft Fluent 2 parity scan (metadocsstack #081). Sources: https://fluent2.microsoft.design/ (TreeView) + WAI-ARIA tree pattern.

R1 — When to use

Use a tree view for data with a parent→child hierarchy the user navigates by expanding nodes (files/folders, nested settings, categories). Do NOT use it for:

  • flat, same-level items → specs/components/lists.kmd;
  • tabularcolumnar records → `specscomponents/data-table.kmd`;
  • transient command lists → specs/components/menus.kmd.

R2 — Anatomy

Each node row: an expand/collapse twisty (only when it has children), depth indentation, an optional checkbox (R4), an optional icon, and the label. Leaf nodes align with their siblings (no orphan twisty).

R3 — Expand / collapse

  • Children may load lazily on first expand (show a

    specs/components/skeleton.kmd placeholder while loading).

  • Expansion state persists across re-render within a session; expand-all /

    collapse-all are optional bulk controls.

  • A node with zero children after load shows no twisty.

R4 — Cascading checkboxes (tri-state)

When selection-by-inclusion is enabled, checkboxes are tri-state:

  • checking a node checks all descendants;
  • unchecking clears all descendants;
  • a node whose descendants are mixed renders indeterminate

    (aria-checked="mixed");

  • a node becomes checked iff all its children are checked (state

    propagates up as well as down).

The checked set is derived from leaves; never store a parent "checked" that contradicts its children.

R5 — Selection vs check (distinct)

  • Focus/selection = the active node (single, keyboard-navigable).
  • Check = membership in an inclusion set (R4), independent of focus.

Both can coexist (you can move focus without changing checks). For pure multi-select without hierarchy semantics, see specs/interaction/selection.kmd.

R6 — Keyboard

  • ↑/↓ move focus across visible nodes; expands (or moves to first

    child), collapses (or moves to parent); Home/End jump to first/last; type-ahead matches labels.

  • Space toggles the focused node's checkbox; Enter activates the

    node's primary action.

  • Exactly one node is in the tab order (roving tabindex); arrows move

    within.

R7 — Scale

Virtualize rendering for large/deep trees (only expanded, on-screen nodes in the DOM). Any truncated/lazy-unloaded branch is disclosed, never silently capped.

R8 — Accessibility

  • role="tree" on the container; role="treeitem" per node; child lists

    wrapped in role="group".

  • Each item carries aria-expanded (when expandable), aria-selected,

    aria-checked (true|false|mixed for R4), and aria-level / aria-setsize / aria-posinset.

  • Indentation/twisty are not the sole structure signal — the ARIA level +

    group convey hierarchy to assistive tech.

Não-escopo

  • Drag-to-reorder / drag-between-nodes (separate enhancement).
  • Columnar tree-grid (a data-table variant, not this).
  • The backing data model / lazy-load transport.