esc
navigate select
Browse documentation

Accessibility

TreeKit implements the WAI-ARIA Tree View pattern, not just enough ARIA to pass a linter.

Click into the tree below and try navigating with only your keyboard — every interaction available with a mouse (expand, collapse, check, select) has a keyboard equivalent.

Engineering
Show code
<TreeKit data={data} aria-label="Organization" />

Keyboard reference

↓ / ↑Move focus to the next / previous visible row
Expand the focused node, or move focus into its first child if already expanded
Collapse the focused node, or move focus to its parent if already collapsed
Home / EndMove focus to the first / last visible row
SpaceToggle the checkbox (or the active/selected state, if checkboxes are hidden)
EnterActivate/select the focused node

Roving tabindex

The tree itself is a single tab stop. Tabbing in focuses the first row (or the previously-focused row, if you tabbed out and back); arrow keys then move focus within the tree without moving the browser's tab stop, exactly as the ARIA Tree View pattern specifies. Internally, exactly one row has tabindex="0" at any time and every other row has tabindex="-1".

ARIA structure

  • role="tree" on the root, with an accessible name from aria-label/aria-labelledby.
  • role="treeitem" on every row.
  • aria-expanded on any row with children (omitted on leaves, per spec).
  • aria-selected reflects the "active" row (see Selection), not checkbox state.
  • aria-disabled on disabled rows.
  • aria-level, aria-posinset, and aria-setsize so assistive tech can announce depth and position even though TreeKit renders a flattened, virtualization-friendly list rather than nested DOM groups.

Real checkboxes

Each checkbox is a genuine <input type="checkbox">, with the native indeterminate DOM property set imperatively (there is no HTML attribute for it) and aria-labelledby pointing at the row's label — screen readers announce it exactly like any other checkbox with an associated label.

Verified, not assumed

TreeKit's test suite runs every interactive state (expanded, checked, indeterminate, disabled, selected) through jest-axe as part of CI — accessibility regressions fail the build the same way a broken test does.

Reduced motion

All transitions respect prefers-reduced-motion: reduce automatically. You can also force animations off regardless of the OS setting with disableAnimations — see Animations.