Standards · ARIA

Role Widget

treeitem

Marks an element as one item inside a tree. A treeitem can be expandable (a parent of more treeitems) or terminal (a leaf). Use only when building a hierarchical navigator — file explorer, org chart, nested categories — that needs single-tab-stop arrow-key navigation.

When to use

Inside a role="tree", for each visible node. If the node has children, set aria-expanded="true" or "false" and contain or own a role="group" holding the child treeitems. If the node has no children, omit aria-expanded entirely (do NOT set it to "false" on a leaf — that announces “collapsed” with nothing to expand).

Set aria-level (1-indexed depth), aria-posinset (position among siblings, 1-indexed), and aria-setsize (total siblings) on each treeitem when the visual nesting cannot be inferred from the DOM hierarchy.

For navigation that is really just “a list of links with nested sub-links”, <nav> with nested <ul> and <a> is the better choice. Use treeview only when the experience is a single-tab-stop hierarchical browser.

Keyboard + focus contract

Per the APG treeview pattern:

  • Tab moves focus into the tree, onto the current treeitem; Tab moves OUT.
  • Up/Down arrows move focus between visible nodes (skipping over collapsed children).
  • Right arrow: if the node is collapsed, expand it; if expanded, move to first child.
  • Left arrow: if the node is expanded, collapse it; if collapsed, move to parent.
  • Home / End move to the first / last visible node.
  • Enter or Space activates (selects) the current item.
  • Typeahead: typing a letter moves focus to the next matching visible node.

Common failures

  • aria-expanded="false" on a leaf node — announces a phantom collapsible state.
  • Every treeitem has tabindex="0". The pattern is single tab-stop; only the focused item carries tabindex="0".
  • Right/Left arrow used for “next sibling / previous sibling” rather than expand/collapse.
  • Child treeitems placed directly inside the parent’s <li> without a wrapping role="group". Screen readers cannot announce the group as a unit.
  • Missing aria-level when the DOM is flat (when the tree is rendered with absolute positioning, for example).

Example

<ul role="tree" aria-label="Files">
  <li role="treeitem" aria-expanded="true" tabindex="0">
    Documents
    <ul role="group">
      <li role="treeitem" tabindex="-1">Resume.pdf</li>
      <li role="treeitem" aria-expanded="false" tabindex="-1">
        Photos
        <ul role="group">
          <li role="treeitem" tabindex="-1">2025-summer.jpg</li>
        </ul>
      </li>
    </ul>
  </li>
  <li role="treeitem" tabindex="-1">Downloads</li>
</ul>