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.kmdplaceholder 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 listswrapped in
role="group".- Each item carries
aria-expanded(when expandable),aria-selected,aria-checked(true|false|mixedfor R4), andaria-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-tablevariant, not this). - The backing data model / lazy-load transport.