Treegrid
Hierarchical grid combining tree and grid patterns.
Usage
<w-treegrid label="File browser">
<w-slot row data-level="1" expandable>
<div>
<w-slot cell><div>Documents</div></w-slot>
<w-slot cell><div>Folder</div></w-slot>
</div>
</w-slot>
<w-slot row data-level="2">
<div>
<w-slot cell><div>Report.pdf</div></w-slot>
<w-slot cell><div>File</div></w-slot>
</div>
</w-slot>
</w-treegrid>
Sized columns
Use size="N" on a cell slot to give it a wider flex grow value. Sizes 1–12 are supported.
<w-treegrid label="File browser">
<w-slot row data-level="1" expandable>
<div>
<w-slot cell size="2"><div>Name</div></w-slot>
<w-slot cell><div>Type</div></w-slot>
</div>
</w-slot>
</w-treegrid>
Fixed height + sticky header
Set height on the treegrid to make it scroll, and add sticky to a row slot to pin it to the top. Give the header row a solid background so scrolling content doesn't bleed through.
<w-treegrid height="240px">
<w-slot row sticky>
<div style="background: #f5f5f5;">
<w-slot cell><div>Name</div></w-slot>
<w-slot cell><div>Type</div></w-slot>
</div>
</w-slot>
<!-- many rows… -->
</w-treegrid>
Layout
Rows default to display: flex and cells default to flex: 1, so a bare treegrid lays out as a horizontal row of equal-width cells without any inline styles. <w-slot cell size="N"> sets flex: N on the cell (1–12). Defaults are applied with zero specificity (:where()), so any inline style="flex: ..." or class-based rule overrides them — note that custom cell classes (e.g. a .treegrid-cell { flex: 1 } rule) will override size because class selectors out-rank :where().
Props
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | "" | Accessible label |
selection-mode | "none" | "single" | "multiple" | "single" | Selection behavior on rows |
height | string | — | CSS height (e.g. "240px", "50vh"). Applies overflow: auto for you. |
Slots
| Slot | Element | Description |
|---|---|---|
row | Container | Grid row (use data-level, expandable attributes) |
cell | Any | Grid cell |
Row Attributes
| Attribute | Description |
|---|---|
data-level | Nesting level (1, 2, 3, etc.) |
expandable | Row can be expanded |
sticky | Pins the row to the top of a scrolling treegrid (position: sticky) |
Cell Attributes
| Attribute | Values | Description |
|---|---|---|
size | 1–12 | Sets flex: N on the cell. Default 1. |
Keyboard
| Key | Action |
|---|---|
ArrowRight | Expand row or move right |
ArrowLeft | Collapse row or move left |
ArrowDown | Next visible row |
ArrowUp | Previous visible row |
Styling
Rows are flex; cells default to flex: 1. Depth is exposed via aria-level and the library mirrors expansion state to data-expanded. aria-selected marks selected rows.
/* Indent rows by depth */
w-treegrid w-slot[row] > *[aria-level="1"] {
padding-left: 0;
}
w-treegrid w-slot[row] > *[aria-level="2"] {
padding-left: 1.5rem;
}
w-treegrid w-slot[row] > *[aria-level="3"] {
padding-left: 3rem;
}
/* Expanded folder row */
w-treegrid w-slot[row] > *[aria-expanded="true"] {
background: #fafafa;
}
/* Selected row */
w-treegrid w-slot[row] > *[aria-selected="true"] {
background: #eef2ff;
}
/* Sticky header */
w-treegrid w-slot[row][sticky] > * {
background: #f5f5f5;
font-weight: 600;
}
| Selector | Targets |
|---|---|
w-treegrid w-slot[row] > *[aria-level="N"] | Rows at depth N |
w-treegrid w-slot[row] > *[aria-expanded="true"] | Expanded folder row |
w-treegrid w-slot[row] > *[aria-selected="true"] | Selected row |
w-treegrid w-slot[row][sticky] > * | Sticky header row |
Accessibility
- Combines
role="treegrid"with tree navigation - Rows have
aria-expandedwhen expandable aria-levelindicates depth