C-25 · Components · Navigation
All elements · Tree on the Components page
Last checked 2026-10-22 · Awaiting approval · Accessibility tests
Approve Tree
Approving as
| Axis | Values |
|---|---|
.qf-tree__node[aria-expanded][data-depth] |
expand state and indent level |
.qf-tree__node[aria-selected] · __toggle[data-leaf] ·
__count
|
parts |
data-show-lines |
guide lines |
Guidance
When to use
- Browse a folder or category hierarchy, such as Finance > Invoices > 2026 Q3, and pick one node to filter the content beside it.
- Show item counts per branch with
__countso users see where the work is. - Show nesting clearly in deep or long trees with
data-show-linesguide lines. - Let keyboard users move through a large hierarchy without tabbing through every node.
When to consider something else
- When the items are flat, use List. See List.
- When the hierarchy is the app's main navigation, use the Shell navigation groups. See App shell.
- When there are only a few sections of content to open and close, use Accordion. See Accordion.
- When each row has many columns of data, use Data grid. See DataGrid.
- When the user picks one value inside a form and the options are flat, use Select. See Select.
Usability
- Keep labels short and unique among siblings; truncate long ones and show the full name on hover and focus.
- Expand the path to the current selection when the tree first renders.
- Load large branches on expand and show progress in the row while they load.
- Remember which branches the user expanded.
- Don't put buttons or checkboxes inside rows unless the binding moves them into the tree's keyboard model.
- Don't nest more than five or six levels; the indent eats the label.
- Don't make the small toggle the only pointer target for expanding; Arrow Right must work too.
Accessibility
Keyboard
| Keys | Action |
|---|---|
| Tab | Moves focus into the tree to the last focused node, and Tab again leaves the tree. |
| Arrow Down / Arrow Up | Moves to the next or previous visible node. |
| Arrow Right | Expands a closed node; on an open node, moves to its first child. |
| Arrow Left | Collapses an open node; on a closed or leaf node, moves to its parent. |
| Home / End | Moves to the first or last visible node. |
| Enter or Space | Selects the focused node. |
Roles and names
-
The container has
role="tree"and must have anaria-labeloraria-labelledby, such as "Folders"; the specimen omits it. -
Each
.qf-tree__nodehasrole="treeitem"; parents carryaria-expanded, leaves have noaria-expanded. -
Child nodes sit in
.qf-tree__childrenwithrole="group", so screen readers announce level and position. -
The selected node carries
aria-selected="true";data-depthonly sets the indent. -
The
__countis read as part of the node name; the binding should phrase it, for example with visually hidden "items" text.
Focus
-
The tree is one Tab stop: one node has
tabindex="0", all others-1, and the arrow keys move that stop. - Clicking a row selects and focuses it; clicking the toggle expands or collapses and focuses the node.
- Focus shows the shared focus ring on the node; when a focused node's parent collapses, focus moves to the parent.
Other requirements
- Rows are at least 2rem high, meeting 2.5.8; the 1.25rem toggle relies on the row around it, so keep the row clickable.
- Selection uses a fill plus primary text, not color alone; the fill needs 3:1 against the background (1.4.11).
- The binding should add type-ahead (typing a letter moves to the next matching node), which the static demo does not have.
- Deep indents must still fit at 320px width (1.4.10); truncate labels rather than scroll the tree sideways.
Test your implementation too. This guidance covers the element as specified here. How a screen composes it (labels, order, announcements) still needs its own keyboard and screen reader check.
Accessibility tests
Passed the gate (run 358b316 on 2026-10-22): no finding in any theme. Awaiting a person’s approval of the checklist below.
| Area | Automated | A person checks |
|---|---|---|
| General | Passed | Color is never the only cue, text alternatives say the same thing as the graphic, and the element reads the same in the light and the dark theme. |
| Zoom | Passed | At 200% zoom, at 320 CSS pixels wide and with the WCAG text-spacing overrides, nothing is lost, clipped or overlapping. |
| Keyboard | Passed | Every row of the Keyboard table works, focus is always visible and never trapped, and the tab order follows the reading order. (6 rows) |
| Screen reader | Passed | With NVDA or JAWS on Windows and VoiceOver on macOS, names, roles and states are announced as Roles and names says, and changes are announced once. (5 items) |
Approving. When the checklist passes on the checked run, record it with
bun run a11y:approve -- tree --by "Your name" and commit
a11y/approvals.json with the rebuilt pages.
All test status
Package
Consumers link one stylesheet, css/classic/index.css, which includes every element. The
files below are where this element is defined.
Latest updates
No recorded changes yet.