Treegrid
Treegrids combine tree hierarchy with tabular columns, such as file explorers with size and date columns, or nested budgets.
Try it
Usage
Define columns and nested rows with id, cells, and optional children. Bind value to the selected row id.
import { RuiTreegrid, type RuiTreegridRow } from '@ecopages/radiant-ui/treegrid';
const rows: RuiTreegridRow[] = [
{
id: 'docs',
cells: ['docs'],
children: [{ id: 'intro', cells: ['introduction.md'] }],
},
];
<RuiTreegrid columns={['Name']} rows={rows} value="intro" label="Repository" />Custom markup
<rui-treegrid> coordinates any light-DOM tree that matches its query contract. The RuiTreegrid helper stamps these targets; it is not required.
import '@ecopages/radiant-ui/treegrid';
<rui-treegrid value="intro" label="Repository">
<div role="treegrid" aria-label="Repository">
<div role="row">
<div role="columnheader">Name</div>
</div>
<div role="row" data-row-id="docs" aria-expanded="true">
<div role="gridcell">docs</div>
</div>
<div role="rowgroup">
<div role="row" data-row-id="intro">
<div role="gridcell">introduction.md</div>
</div>
</div>
</div>
</rui-treegrid>;Tree vs treegrid
Use Treegrid when rows have multiple columns of data. Use Tree for single-column hierarchies.
Theming
Treegrid maps to semantic surface and status roles, never Tailwind palette steps:
| Part | CSS roles |
|---|---|
Surface (rui-treegrid) | border, background, on-background, radius-container, shadow-sm |
| Header cells | surface, on-background |
| Row hover | surface |
| Selected row | primary-container, on-primary-container |
| Cell focus | focus-ring, z-dropdown |
| Geometry | --space-control-x (cell padding) |
Override at the theme layer, not in component CSS.
API
RuiTreegrid is a custom element (<rui-treegrid>) that owns expand/collapse and cell-only roving-tabindex navigation; the RuiTreegrid JSX view authors rows, groups, and header cells.
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
label | string | '' | Accessible name for the treegrid. |
value | string | '' | Selected row's data-row-id. |
Light-DOM contract
| Target | Required | Host writes | Author owns |
|---|---|---|---|
[role="treegrid"] | yes | — | root surface; view sets aria-label |
[role="row"][data-row-id] | yes | aria-expanded sync | data-row-id, initial aria-expanded |
[role="gridcell"] | yes | aria-selected, roving tabIndex | cell content |
[role="rowgroup"] | for branches | hidden | sibling after expandable row |
Header rows and [role="columnheader"] cells are presentation-only. Nested hosts: none.
Events
| Event | Detail | Description |
|---|---|---|
rui-change | { rowId: string, columnIndex: number } | Emitted when a cell activates. |
Props
| Prop | Type | Default | Description |
|---|---|---|---|
columns | JsxRenderable[] | Header cell content for the RuiTreegrid view. | |
rows | RuiTreegridRow[] | Nested row structure. |
RuiTreegridRow is { id, cells, children?, expanded? }.
View helpers
| Component | Target stamped | Notes |
|---|---|---|
RuiTreegrid | [role="treegrid"] with data-ref="root" | Accepts columns + rows or children. |
CSS classes
Public BEM classes (documented via @cssclass):
| Class | Description |
|---|---|
.rui-treegrid | Root surface inside the host (role="treegrid"). |
.rui-treegrid__row | Data row (role="row"). |
.rui-treegrid__row--header | Header row. |
.rui-treegrid__group | Collapsible row group (role="rowgroup"). |
.rui-treegrid__cell | Data cell (role="gridcell"). |
.rui-treegrid__cell--header | Column header cell (role="columnheader"). |
Theme roles
| Part | CSS variables consumed |
|---|---|
| Surface | --border, --background, --on-background, --radius-container, --shadow-control |
| Header cells | --surface, --on-background |
| Row hover | --surface |
| Selected row | --primary-container, --on-primary-container |
| Cell focus | --focus-ring, --z-dropdown |
| Cell padding | --space-control-x |
Accessibility
- Treegrid exposes
role="treegrid"with grid navigation semantics. - Column headers provide context for cell values.
- Expandable rows communicate
aria-expandedon parent rows.