Present the hierarchy as a tree grid with labelled columns, expandable parent rows, indented row headers, truthful level and position metadata, managed row or cell focus, distinct focus and selection, and clear rules for sorting, filtering, editing, lazy loading, and collapsed descendants.
Rows have real parent-child hierarchy and shared comparable columns.
Users need to inspect, select, edit, sort, filter, or act on hierarchical records without losing column context.
Collapsed parents may summarize descendant state, counts, validation, selection, or progress.
The team can implement and test tree, grid, focus, expansion, and dynamic-row semantics together.
Avoid when
Rows are flat or only visually grouped.
Users only choose items in a hierarchy and do not compare columns.
The data is read-only and a table with a hierarchy column is sufficient.
The hierarchy is too deep or irregular for a dense row-and-column workspace.
Sorting, filtering, virtualization, or lazy loading cannot preserve descendant state truthfully.
Problem it prevents
Users need to inspect or act on hierarchical records that also have comparable columns, but separate tree and table controls force context switching, while a flat data grid loses parent-child ownership and descendant state.
Pattern anatomy
What a strong implementation has to make clear
User need
Rows represent nested objects such as folders and files, work breakdown structures, threaded records, accounts and subaccounts, requirements and tasks, or organization units and members.
Pattern promise
Present the hierarchy as a tree grid with labelled columns, expandable parent rows, indented row headers, truthful level and position metadata, managed row or cell focus, distinct focus and selection, and clear rules for sorting, filtering, editing, lazy loading, and collapsed descendants.
Required state
Default tree grid state with label, column headers, visible root rows, row hierarchy, row count context, and focused row or cell.
Recovery path
Screen reader users hear a grid but cannot tell which rows are parents, leaves, expanded, collapsed, or selected.
Access contract
Use treegrid semantics only when rows can expand or collapse and the content also behaves as a grid.
Quality bar
The difference between expert and weak execution
Strong implementation
Specific, visible, recoverable
A project work-breakdown tree grid shows parent rows for phases, child rows for tasks, columns for Owner, Due, Status, and Cost, and a collapsed parent badge that says 2 selected children.
A folder permission tree grid indents folders and files in the Name column, omits expand buttons from files, and keeps column headers aligned for Owner, Role, Inherited, and Last changed.
A user expands Design, edits a child task status, collapses Design, sees a dirty-child badge on the parent, re-expands, and focus returns to the edited child row.
A user filters to overdue tasks; parent rows remain visible only when they contain matching descendants, and collapsed parents show the number of hidden matches.
Weak implementation
Vague, hidden, hard to recover from
A flat data grid uses chevron icons in every first cell but no row actually owns children.
A simple folder picker with one label column is implemented as a tree grid even though users only choose folders.
A user collapses a parent and unknowingly hides a selected invalid child row before bulk approval.
A user sorts by Due date and child tasks scatter away from their parent phases, destroying the hierarchy.
UI guidance
Render a labelled tree grid with a persistent hierarchy column, visible column headers, indentation by level, expandable parent rows, leaf rows without fake expand controls, and status text for visible rows, selected descendants, sort, filter, and loading children.
Show parent, child, focused, selected, mixed, collapsed-with-descendant-state, dirty, invalid, readonly, and loading states with distinct text or programmatic state as well as visual treatment.
UX guidance
Use tree grid when users need to keep hierarchy and column comparison in one workspace, especially for nested operational records that can be expanded, selected, edited, or acted on in context.
Preserve users' mental model of containment: expansion, collapse, sort, filter, save, lazy load, and virtual scroll must not make descendant state disappear without an explicit explanation.
Implementation contract
What the implementation must handle
States
Default tree grid state with label, column headers, visible root rows, row hierarchy, row count context, and focused row or cell.
Expanded parent row state with visible child rows, level indentation, and truthful aria-expanded state.
Collapsed parent row state with child rows hidden, descendant count or state summary when relevant, and no focus left inside hidden rows.
Leaf row state without expansion affordance or aria-expanded.
Interaction
The first column or row header communicates the hierarchical object name, level, expansion state, and parent-child relationship.
Expansion and collapse affect only descendant rows and never leave keyboard focus on a hidden row.
Rows without children do not expose expansion state or an inert disclosure control.
Arrow keys move by row or cell according to the documented focus model; Right Arrow expands collapsed parents or moves into cells, and Left Arrow collapses expanded parents or moves toward row focus.
Accessibility
Use treegrid semantics only when rows can expand or collapse and the content also behaves as a grid.
Give the treegrid a visible or programmatic label and optional description for keyboard help, counts, filters, and selection state.
Use row, columnheader, rowheader, and gridcell roles or native equivalents with role treegrid.
Expose aria-expanded only on parent rows or the controlling cell; omit it from leaves.
Review
What parent-child relationship does the first column encode?
Which rows are parents, which are leaves, and what happens to hidden descendants when a parent collapses?
Does the task require comparing columns across hierarchical rows, or is a tree selection enough?
Is focus row-first, cell-first, or cell-only, and can users recover after expansion, collapse, sort, filter, and lazy load?
Interactive lab
Inspect the states before you copy the pattern
Expand hierarchical rows in a grid
Move focus through parent and child rows, expand and collapse phases, preserve dirty child state, filter overdue descendants, select child rows, restore focus, and compare flat-grid, fake-leaf, hidden-dirty, sort-break, stale-index, and mobile-crush failures.
Tree grid
Interactive demo is ready
Launch the live UI/UX lab when you want to inspect states, keyboard behavior, and common failure modes.
State To Inspect
Default tree grid state with label, column headers, visible root rows, row hierarchy, row count context, and focused row or cell.
Keyboard / Access
Tab moves into the treegrid at the current row or cell and exits after the managed row or inner row widgets according to the documented model.
Avoid Generating
Using treegrid for a flat data grid with no expandable parent rows.
APG treegrid guidance supports the hierarchy-plus-grid boundary, keyboard navigation, focus and selection distinction, roles, expansion state, sort, readonly, and dynamic index requirements.
MDN treegrid role guidance supports the tree and grid combination, parent row semantics, managed focus, aria-expanded placement, accessible naming, and dynamic row metadata.
KendoReact TreeList keyboard guidance supports single tab stop focus management, roving tabindex or active descendant, and cell versus inner-widget focus choices.
KendoReact TreeList ARIA guidance supports separate toolbar and treegrid structure, aria-controls, role treegrid, aria-expanded rows, and hidden decorative icons.
DevExtreme TreeList keyboard demo supports region navigation and keyboard expansion or collapse of the focused row.
Full agent/debug reference
Problem Context
Rows represent nested objects such as folders and files, work breakdown structures, threaded records, accounts and subaccounts, requirements and tasks, or organization units and members.
Users need to compare values across shared columns such as owner, status, due date, amount, count, permissions, or last activity.
Parent rows can summarize, contain, select, lock, or expand child rows, and child rows may have independent values or actions.
The interface may support editable cells, row actions, selection, bulk operations, sorting, filtering, lazy loading, pagination, or virtual scrolling.
Selection Rules
Choose tree grid when hierarchical rows and tabular columns are both essential to the task.
Use data grid when rows are flat and expansion is only a detail panel, grouping, or visual section.
Use tree selection when users choose hierarchical nodes but do not need shared data columns or cell-level interaction.
Use table when users only compare rows and any hierarchy can be represented by a separate column or grouping label.
Use details panel or master-detail when a selected object's nested detail is easier to inspect beside the source grid than inline.
Use accordion or disclosure details for short content groups that are not comparable rows.
Avoid tree grid when parent-child relationships are decorative indentation rather than real containment.
Avoid tree grid when sorting, filtering, lazy loading, or bulk selection cannot preserve descendant state truthfully.
Avoid tree grid on narrow screens unless the product has a tested reduced-column, horizontal-scroll, or drill-in strategy.
Avoid tree grid if the team cannot implement managed focus, aria-expanded, row levels, row positions, and screen reader verification.
Required States
Default tree grid state with label, column headers, visible root rows, row hierarchy, row count context, and focused row or cell.
Expanded parent row state with visible child rows, level indentation, and truthful aria-expanded state.
Collapsed parent row state with child rows hidden, descendant count or state summary when relevant, and no focus left inside hidden rows.
Leaf row state without expansion affordance or aria-expanded.
Focused row or cell state that remains visually distinct from selected rows and checked rows.
Single-select, multi-select, parent-selected, child-selected, and mixed-descendant states when selection is supported.
Editable cell, readonly cell, dirty child row, invalid child value, saving, saved, and failed-save states when editing is supported.
Sorted and filtered states that preserve hierarchy rules and explain hidden or empty parents.
Lazy-loaded, loading-children, load-failed, virtualized, and paginated states with truthful row counts, levels, positions, and row indices.
Narrow-screen state that preserves hierarchy, column meaning, expansion, and row actions or routes users to a focused detail view.
Interaction Contract
The first column or row header communicates the hierarchical object name, level, expansion state, and parent-child relationship.
Expansion and collapse affect only descendant rows and never leave keyboard focus on a hidden row.
Rows without children do not expose expansion state or an inert disclosure control.
Arrow keys move by row or cell according to the documented focus model; Right Arrow expands collapsed parents or moves into cells, and Left Arrow collapses expanded parents or moves toward row focus.
Tab enters and exits the composite predictably and does not force users through every visible cell unless the row has an intentional inner-widget sequence.
Selection is independent from focus in multi-select tree grids and makes descendant inclusion, exclusion, or mixed state explicit.
Sorting, filtering, pagination, refresh, and lazy loading preserve expanded state, selected descendants, dirty edits, and focused row whenever possible.
Parent rows state whether values are aggregates, inherited values, editable values, or actions that apply to descendants.
Implementation Checklist
Define the hierarchy model, root rows, child rows, leaf rows, row identifiers, parent identifiers, columns, and expansion ownership.
Choose whether focus is row-first, cell-first, or cell-only and document the keyboard model in the UI.
Use treegrid, row, columnheader, rowheader, and gridcell semantics, or native table semantics with role treegrid when appropriate.
Set aria-expanded only on parent rows or the controlling rowheader cell, and remove it from leaves.
Expose aria-level, aria-posinset, aria-setsize, aria-rowcount, aria-colcount, aria-rowindex, and aria-colindex when rows or columns are dynamic, virtualized, lazy-loaded, or not all present in the DOM.
Keep expansion icons decorative when their state is already exposed by the parent row or cell.
Distinguish focus, selection, checked state, mixed descendant state, dirty edits, invalid cells, and loading children with text or programmatic state, not color alone.
Define how sorting and filtering treat descendants, parent aggregates, collapsed selected children, lazy-loaded children, and empty parent branches.
Test keyboard navigation, expansion, collapse, selection, editing, screen reader announcements, lazy loading, virtual scroll, high contrast, zoom, and mobile layouts.
Common Generated-UI Mistakes
Using treegrid for a flat data grid with no expandable parent rows.
Using treegrid for a simple folder tree that has only one label column and no tabular comparison.
Putting aria-expanded on leaf rows or every first-column cell.
Collapsing a parent while focus, validation, or dirty edits remain hidden inside descendants.
Sorting child rows away from parents without explaining the hierarchy rule.
Losing selected children when a parent is collapsed, filtered, virtualized, or paged away.
Rendering nested tables inside expandable rows instead of one coherent row and column model.
Treating parent rows, aggregate values, inherited values, and editable child values as the same interaction.
Critique Questions
What parent-child relationship does the first column encode?
Which rows are parents, which are leaves, and what happens to hidden descendants when a parent collapses?
Does the task require comparing columns across hierarchical rows, or is a tree selection enough?
Is focus row-first, cell-first, or cell-only, and can users recover after expansion, collapse, sort, filter, and lazy load?
Are selected, focused, mixed, dirty, invalid, readonly, and loading states visibly and programmatically distinct?
Would a flat data grid, table, tree selection, details panel, accordion, or drill-in route be less costly?
Accessibility
Use treegrid semantics only when rows can expand or collapse and the content also behaves as a grid.
Give the treegrid a visible or programmatic label and optional description for keyboard help, counts, filters, and selection state.
Use row, columnheader, rowheader, and gridcell roles or native equivalents with role treegrid.
Expose aria-expanded only on parent rows or the controlling cell; omit it from leaves.
Expose aria-selected for selectable rows or cells, and keep selection independent from focus in multi-select tree grids.
Expose aria-level, aria-posinset, aria-setsize, aria-rowcount, aria-colcount, aria-rowindex, and aria-colindex when rows or columns are dynamic, hidden, virtualized, or lazy-loaded.
Use aria-sort on sortable header cells, not on the treegrid container.
Use aria-readonly at the grid or cell level when navigable values cannot be edited.
Ensure decorative expand and collapse icons are hidden when the row or cell already exposes expanded state.
Keyboard Behavior
Tab moves into the treegrid at the current row or cell and exits after the managed row or inner row widgets according to the documented model.
Right Arrow expands a collapsed parent row; on an expanded row or leaf it moves into the first cell or rightward cell depending on row or cell focus.
Left Arrow collapses an expanded parent row; on a collapsed row, leaf row, or first cell it moves toward row focus or stays put according to the focus model.
Down Arrow and Up Arrow move by visible row or by cell in the same column without entering hidden descendants.
Home and End move to the first or last visible row or the first or last cell in the current row depending on focus mode.
Control+Home and Control+End move to the first or last visible row or corresponding cell in the treegrid.
Enter activates the default row or cell action or toggles expansion when focus is on the expanding first cell in a cell-only model.
Shift+Space selects the focused row when row selection is supported; Control+Space, Shift+Arrow, and Control+A only apply when column, cell, or range selection is supported.
Typing, Enter, or F2 enters cell edit mode only for editable cells and must define how Escape restores treegrid navigation.