components / treeview

TreeView

Single-select hierarchical collection with branch expansion, depth cues, and keyboard traversal.

Overview

What it is

This section explains the intent of the component before the implementation details.

  • TreeView exposes hierarchical collections where depth, parentage, and selective expansion matter.
  • The DK contract focuses on dependable single selection and predictable arrow-key navigation.

Aliases

tree

Decision guide

How to choose it

Use these notes to decide quickly whether this is the right DK component for the job.

Decision guide

  • Choose TreeView when the interaction should feel deliberate, documented, and reusable across product surfaces.
  • If the scenario is more specialized than the current TreeView contract, prefer a simpler component or build a dedicated workflow on top of the lower-level DK primitives.

Do

  • Keep the TreeView label, value, or status language direct enough to scan quickly.
  • Use the documented size and state recipes instead of inventing one-off variants in product code.

Do not

  • Do not hide the main purpose of TreeView behind decorative copy or overloaded surface treatments.
  • Do not stretch TreeView into a workflow it was not designed to handle just because the visuals are close.

Usage

When to use

Prefer these situations when choosing this component.

  • Use TreeView for file-like hierarchies, nested resources, or settings structures where branches should open in place.
  • Use descriptions sparingly to support ambiguous nodes without overwhelming the tree.

Usage

When not to use

These patterns are better served by a different component or a simpler surface.

  • Do not use TreeView when the structure is effectively flat.
  • Do not use TreeView for drag-and-drop, typeahead-heavy, or multi-select trees in this v1 contract.

Anti-patterns

  • Using TreeView as a generic layout container instead of a purpose-built interaction or content surface.
  • Forking the documented recipe in product code instead of extending the shared DK contract.

Migration notes

  • Migrate legacy treeview usage by mapping existing variants and states onto the documented DK props before porting any custom styling.
  • Treat the docs examples as the reference contract for accessibility and event behavior during adoption.

Anatomy

Structural parts

The anatomy explains which pieces matter to the recipe and accessibility model.

tree row

item

Single hierarchical row with level, selection, and branch state.

expand/collapse affordance

branch

Opens or closes a node with children.

supporting node text

description

Optional secondary copy beneath the main label.

API

Public interface

The docs contract distinguishes props, DOM events, and slots so integration behavior is explicit.

Props

NameTypeDefaultDescription
itemsArray<{ id: string; label: string; description?: string; disabled?: boolean; children?: TreeViewItem[] }>Tree definitions with nested child arrays.
valuestringControlled selected node id.
expandedIdsstring[]Controlled expanded branch ids.
onChange(detail: { value: string | undefined }) => voidCallback fired when the selected node changes.
onExpandedChange(detail: { ids: string[] }) => voidCallback fired when the expanded branch set changes.
themeThemeContractOverrides the compiled DK theme used to resolve tokens and recipes for this component.

Events

NamePayloadDescription
change{ value: string | undefined }Fires when the component commits a new value.
expandedchange{ ids: string[] }Fires when expanded branches change.

Slots

NameDescription
defaultTreeView is data-driven in v1 and does not expose node slots.

Recipes

Variants, sizes, and states

These notes summarize the intended recipe surface rather than exposing raw implementation detail first.

Variants

  • default: Single-select hierarchical tree with depth indentation.

Sizes

  • default: TreeView uses one density tuned for readable hierarchy.

States

  • collapsed: Branch closed
  • expanded: Branch open
  • selected: Current node selected

Accessibility

Accessibility contract

This is the behavior the component promises to assistive tech and keyboard users today.

Semantics

  • Uses tree and treeitem semantics with explicit level and expanded state.

Keyboard

  • Arrow keys move, expand, collapse, and return to parent nodes. Home and End jump to the first and last visible rows.

Screen readers

  • Depth, branch state, and selection remain understandable through the tree semantics.

Checklist

  • Verify the visible label or title still produces a clear accessible name.
  • Verify focus remains obvious in every supported state and size.
  • Verify disabled, selected, and error states do not rely on color alone.

Implementation

Tokens and slot vars

This section shows the representative compiled slot variables that the runtime consumes for the selected design system.

root

--dk-tree-gap
0.25rem

item

--dk-tree-item-bg
#f2f5fb
--dk-tree-item-fg
#16181c
--dk-tree-item-radius
clamp(0.75rem, 0.6875rem + 0.278vw, 0.938rem)
--dk-tree-item-min-height
44px
--dk-tree-item-inline-padding
0.625rem

label

--dk-tree-label-size
0.92rem
--dk-tree-label-weight
600

description

--dk-tree-description-fg
#16181c
--dk-tree-description-size
0.75rem

branch

--dk-tree-branch-size
0.85rem

Implementation notes

  • TreeView remains single-select in v1 so the mental model and keyboard behavior stay tight.

Implementation checklist

  • Use the public component API first and only drop to lower-level primitives when the component contract genuinely does not fit.
  • Keep theme overrides token-driven so proofs and recipes stay meaningful.
  • Verify the shipped examples and proof fixtures still represent the real product scenario you are implementing.

Examples

Copy-paste examples

Each example is intentionally practical, grouped by starter, common pattern, and edge-case coverage.

Examples
3
Depth
expanded

Starter

1 example

starter

Starter: nested resource list

A readable hierarchical list with one expanded branch.

Copy snippet

<TreeView items={treeItems} expandedIds={['workspace']} value="overview" />

Common patterns

1 example

common

Common: ambiguous nodes with descriptions

Descriptions can clarify similarly named nodes without changing the structure.

Copy snippet

<TreeView items={[{ id: 'workspace', label: 'Workspace', children: [{ id: 'activity', label: 'Activity', description: 'Recent events' }] }]} expandedIds={['workspace']} />

Edge cases

1 example

edge

Edge: externally controlled branches

Control selection and expanded branches when app state owns the hierarchy.

Copy snippet

<TreeView items={treeItems} value={selectedNode} expandedIds={expanded} onChange={(detail) => selectedNode = detail.value} onExpandedChange={(detail) => expanded = detail.ids} />

Verification

Curated proof fixtures

Proofs stay visible in the docs so the system shows what it can guarantee, not just what it can render.

default

pass

  • Contrast: 98.5 Lc
  • Target: 44px
  • Layout: 0 / 240, 320

selected

pass

  • Contrast: 89.9 Lc
  • Target: 44px
  • Layout: 0 / 240, 320