Tree Grid
CTreeGrid combines a finite Row hierarchy with Data Grid columns. It is for account trees, threaded records, work breakdowns, and similar structured data, not spreadsheet formulas or inline editing.
Show code
# ruff: noqa: ANN001, ANN201 - public snippets keep focus on component use
import citry_ui
from citry import Component, citry
from citry_ui import CTreeGridColumn, CTreeGridRow
citry.register_library(citry_ui)
COLUMNS = [CTreeGridColumn("name", "Account", width=240), CTreeGridColumn("owner", "Owner")]
ROWS = [
CTreeGridRow(
"north",
"Northern region",
{"name": "Northern region", "owner": "Ada"},
children=[
CTreeGridRow("prague", "Prague", {"name": "Prague", "owner": "Mira"}),
CTreeGridRow("berlin", "Berlin", {"name": "Berlin", "owner": "Noah"}),
],
)
]
class TreeGridAtAGlance(Component):
def template_data(self, _kwargs, _slots):
return {"columns": COLUMNS, "rows": ROWS}
template = '<c-CTreeGrid c-columns="columns" c-rows="rows" label="Account hierarchy" c-expanded="[\'north\']" />'
preview = TreeGridAtAGlance()
preview # noqa: B018
Expand nested Rows
Put child CTreeGridRow records in children and list initially open branch keys in expanded. The first Column owns indentation and expansion.
Show code
# ruff: noqa: ANN001, ANN201 - public snippets keep focus on component use
import citry_ui
from citry import Component, citry
from citry_ui import CTreeGridColumn, CTreeGridRow
citry.register_library(citry_ui)
class TreeGridExpansion(Component):
def template_data(self, _kwargs, _slots):
return {
"columns": [CTreeGridColumn("work", "Work item", 260), CTreeGridColumn("state", "State")],
"rows": [
CTreeGridRow(
"launch",
"Launch",
{"work": "Launch", "state": "Active"},
children=[
CTreeGridRow("design", "Design", {"work": "Design", "state": "Done"}),
CTreeGridRow("build", "Build", {"work": "Build", "state": "Active"}),
],
)
],
}
template = '<c-CTreeGrid c-columns="columns" c-rows="rows" label="Project plan" c-expanded="[\'launch\']" />'
preview = TreeGridExpansion()
preview # noqa: B018
Select and submit Rows
Choose single or multiple selection and set name to emit repeated hidden Row keys in preorder. Shift+Space toggles the focused Row, including unselect.
Show code
# ruff: noqa: ANN001, ANN201, E501 - public template stays readable
import citry_ui
from citry import Component, citry
from citry_ui import CTreeGridColumn, CTreeGridRow
citry.register_library(citry_ui)
class TreeGridSelection(Component):
def template_data(self, _kwargs, _slots):
return {
"columns": [CTreeGridColumn("team", "Team"), CTreeGridColumn("people", "People")],
"rows": [
CTreeGridRow("product", "Product", {"team": "Product", "people": 18}),
CTreeGridRow("ops", "Operations", {"team": "Operations", "people": 12}),
],
}
template = '<form><c-CTreeGrid c-columns="columns" c-rows="rows" label="Teams" selection="multiple" c-selected="[\'product\']" name="team" /></form>'
preview = TreeGridSelection()
preview # noqa: B018
Own state in Alpine
Client expanded and selected props are controlled. Their callbacks report the requested vector, previous vector, Row key, requested boolean state, controlled flag, source, and native event.
Show code
# ruff: noqa: ANN001, ANN201, E501 - public template stays readable
import citry_ui
from citry import Component, citry
from citry_ui import CTreeGridColumn, CTreeGridRow
citry.register_library(citry_ui)
class TreeGridControlled(Component):
def template_data(self, _kwargs, _slots):
return {
"columns": [CTreeGridColumn("name", "Name")],
"rows": [
CTreeGridRow(
"root", "Root", {"name": "Root"}, children=[CTreeGridRow("child", "Child", {"name": "Child"})]
)
],
}
template = """<div x-data="{open:[],chosen:[]}"><c-CTreeGrid c-columns="columns" c-rows="rows" label="Controlled tree" selection="multiple" $c-props="{expanded:open,selected:chosen,onExpandedChange:value=>open=value,onSelectionChange:value=>chosen=value}" /></div>"""
preview = TreeGridControlled()
preview # noqa: B018
Customize cells
Use header, cell, toolbar, and caption slots. Cell navigation stays on the gridcell; interactive editing remains the separate Data Grid contract.
Show code
# ruff: noqa: ANN001, ANN201, E501 - public template stays readable
import citry_ui
from citry import Component, citry
from citry_ui import CTreeGridColumn, CTreeGridRow
citry.register_library(citry_ui)
class TreeGridCustomCells(Component):
def template_data(self, _kwargs, _slots):
return {
"columns": [CTreeGridColumn("name", "Initiative", 240), CTreeGridColumn("score", "Score", align="end")],
"rows": [
CTreeGridRow(
"quality",
"Quality",
{"name": "Quality", "score": 92},
children=[CTreeGridRow("a11y", "Accessibility", {"name": "Accessibility", "score": 98})],
)
],
}
template = """<c-CTreeGrid c-columns="columns" c-rows="rows" label="Initiatives" c-expanded="['quality']"><c-fill name="cell" data="{ column, cell }"><strong c-if="column.key == 'score'">{{ cell.value }}%</strong><span c-else>{{ cell.value }}</span></c-fill></c-CTreeGrid>"""
preview = TreeGridCustomCells()
preview # noqa: B018
Navigate accessibly
Arrow keys move through visible Rows and Columns. Left and Right also collapse, expand, and return to parents from the hierarchy cell. Disabled Rows remain readable but cannot mutate or activate.
Show code
# ruff: noqa: ANN001, ANN201 - public snippets keep focus on component use
import citry_ui
from citry import Component, citry
from citry_ui import CTreeGridColumn, CTreeGridRow
citry.register_library(citry_ui)
class TreeGridAccessibility(Component):
def template_data(self, _kwargs, _slots):
return {
"columns": [CTreeGridColumn("name", "Record", 260), CTreeGridColumn("status", "Status")],
"rows": [
CTreeGridRow("available", "Available record", {"name": "Available record", "status": "Ready"}),
CTreeGridRow(
"locked", "Locked record", {"name": "Locked record", "status": "Archived"}, disabled=True
),
],
}
template = (
'<c-CTreeGrid c-columns="columns" c-rows="rows" label="Records" selection="multiple" density="spacious" />'
)
preview = TreeGridAccessibility()
preview # noqa: B018
Hierarchical sorting, async children, virtual Rows, and editing are explicit future or adjacent contracts, not hidden Tree Grid modes.
API reference
Inputs
CTreeGrid server inputs
Server inputs are passed in a template through <c-CTreeGrid ... /> or in Python through CTreeGrid(...).
| Input | Type | Default | Effect |
|---|---|---|---|
columns | Sequence[CTreeGridColumn] | required | Defines ordered aligned Columns; the first owns hierarchy controls. |
rows | Sequence[CTreeGridRow] | required | Defines a finite recursive Row hierarchy. |
label | str | required | Names the treegrid. |
id | str | None | generated | Sets the root ID. |
expanded | Sequence[str] | "()" | Supplies initially expanded branch Row keys. |
selection | CTreeGridSelection (CTreeGridSelection) | "none" | Enables no single or multiple Row selection. |
selected | Sequence[str] | "()" | Supplies initially selected Row keys. |
name | str | None | None | Emits selected keys as repeated hidden inputs. |
form | str | None | None | Associates hidden inputs with an external form. |
disabled | bool | False | Disables mutation activation and form output. |
density | CTreeGridDensity (CTreeGridDensity) | "comfortable" | Selects Row height. |
expand_label | str | "Expand {row}" | Overrides branch Expand names and must retain row. |
collapse_label | str | "Collapse {row}" | Overrides branch Collapse names and must retain row. |
expanded_label | str | "Expanded {row}" | Overrides expanded announcements and must retain row. |
collapsed_label | str | "Collapsed {row}" | Overrides collapsed announcements and must retain row. |
selected_label | str | "Selected {row}" | Overrides selected announcements and must retain row. |
unselected_label | str | "Unselected {row}" | Overrides unselected announcements and must retain row. |
class_ | CClassValue | None (CClassValue) | None | Adds root classes. |
style | CStyleValue | None (CStyleValue) | None | Adds root styles. |
attrs | Mapping[str, object] | None | None | Adds copied allowed root attributes. |
table_attrs | Mapping[str, object] | None | None | Adds copied allowed table attributes. |
CTreeGrid client inputs
Client inputs are passed in the browser through the $c-props="{ ... }" attribute on <c-CTreeGrid />.
| Input | Type | Omitted behavior | Effect |
|---|---|---|---|
expanded | string[] | Uncontrolled server branch state. | Controls expanded branch keys. |
selected | string[] | Uncontrolled server selection. | Controls selected Row keys. |
disabled | boolean | Uses the server value. | Reactively disables behavior and inputs. |
onExpandedChange | function | No component callback runs. | Receives expansion requests. |
onSelectionChange | function | No component callback runs. | Receives selection requests. |
onCellActivate | function | No component callback runs. | Receives Enter or double-click activation outside the hierarchy toggle. |
Slots
Slots are passed as nested content or <c-fill> tags in a template, or through the slots={...} argument in Python.
CTreeGrid slots
| Slot | Required | Data | Fallback |
|---|---|---|---|
caption | no | {} (CTreeGridCaptionSlotData) | No native caption. |
toolbar | no | {} (CTreeGridToolbarSlotData) | No toolbar. |
header | no | {column, column_index} (CTreeGridHeaderSlotData) | Column label. |
cell | no | {row, column, cell, row_index, column_index, level, expanded, selected} (CTreeGridCellSlotData) | Cell value. |
Events
Component events are callback inputs supplied through $c-props. Native browser events remain available through Alpine @... attributes.
CTreeGrid events
| Event | Signature | Trigger and timing | Detail | Controlled and cancellation behavior |
|---|---|---|---|---|
onExpandedChange | (expanded: string[], detail: CTreeGridExpandedChangeDetail) => void (CTreeGridExpandedChangeDetail) | A branch changes. | {expanded, previousExpanded, rowKey, rowExpanded, controlled, source, sourceEvent} (CTreeGridExpandedChangeDetail) | Commits only while uncontrolled. |
onSelectionChange | (selected: string[], detail: CTreeGridSelectionChangeDetail) => void (CTreeGridSelectionChangeDetail) | A Row selection toggles. | {selected, previousSelected, rowKey, rowSelected, controlled, source, sourceEvent} (CTreeGridSelectionChangeDetail) | Commits only while uncontrolled. |
onCellActivate | (detail: CTreeGridCellActivateDetail) => void (CTreeGridCellActivateDetail) | Enter or double-click activates a non-hierarchy Cell. | {rowKey, columnKey, rowIndex, columnIndex, sourceEvent} (CTreeGridCellActivateDetail) | Reports without changing data. |
Methods
-
CSS
CSS variables to theme the components. Set them on an ancestor or the component itself.
CTreeGrid CSS variables
Apply these variables to CTreeGrid or one of its ancestors.
| Variable | Type | Purpose | Default |
|---|---|---|---|
--cui-tree-grid-min-width | length | Computed minimum table width. | Sum of Column widths |
--cui-tree-grid-row-height | length | Comfortable Row height. | 3rem |
--cui-tree-grid-indent | length | Per-level logical indent. | 1.25rem |
--cui-tree-grid-border | complete border | Viewport Row and header boundaries. | Adaptive 1px neutral |
--cui-tree-grid-surface | color | Body surface. | Canvas |
--cui-tree-grid-header-surface | color | Header surface. | Adaptive neutral |
--cui-tree-grid-selected-surface | color | Selected Row surface. | Adaptive indigo |
--cui-tree-grid-focus | color | Gridcell and expander focus. | Highlight |
Attributes
HTML attributes defined on the components that you can refer to for CSS, inspection, and testing. Read-only.
CTreeGrid attributes
| Attribute | Element | Type | Meaning |
|---|---|---|---|
data-density | Root | CTreeGridDensity (CTreeGridDensity) | Reflects Row density. |
data-selection | Root | CTreeGridSelection (CTreeGridSelection) | Reflects selection policy. |
data-disabled | Root and Row | present | absent | Reflects unavailable behavior. |
data-expanded | Row | present | absent | Reflects expanded branch state. |
data-selected | Row | present | absent | Reflects selected state. |
data-row-key | Row and Cell | string | Exposes stable Row identity. |
data-parent-key | Row | string | absent | Exposes parent identity. |
data-level | Row | positive integer string | Exposes hierarchy depth. |
Selectors
Selectors for the DOM nodes in the components that you can use for CSS, inspection, and testing.
CTreeGrid selectors
| Selector | Element | Purpose |
|---|---|---|
[data-citry-ui-part="tree-grid"] | Root | Theme and state destination. |
[data-citry-ui-part="toolbar"] | Optional div | Application controls. |
[data-citry-ui-part="status"] | Polite status | Expansion and selection announcements. |
[data-citry-ui-part="viewport"] | Scroll container | Narrow horizontal overflow. |
[data-citry-ui-part="table"] | Native table with treegrid role | Composite owner. |
[data-citry-ui-part="header-cell"] | Columnheader | Column label. |
[data-citry-ui-part="row"] | Hierarchical Row | Expansion selection and hierarchy metadata. |
[data-citry-ui-part="cell"] | Gridcell | Roving focus unit. |
[data-citry-ui-part="hierarchy"] | First-Cell wrapper | Indent branch control and content. |
[data-citry-ui-part="expander"] | Native button | Pointer branch toggle. |
[data-citry-ui-part="cell-content"] | Span | Cell slot destination. |
[data-citry-ui-part="inputs"] | Hidden span | Native selected-key controls. |
Interfaces
Aliases and data shapes referenced above.
Input type aliases
| Interface | Definition |
|---|---|
CTreeGridSelection | Literal["none", "single", "multiple"] |
CTreeGridDensity | Literal["compact", "comfortable", "spacious"] |
CTreeGridAlign | Literal["start", "center", "end"] |
CTreeGridSource | Literal["pointer", "keyboard", "reset"] |
CClassValue | str | Mapping[str, bool] | Sequence[CClassValue] |
CStyleValue | str | Mapping[str, object] | Sequence[CStyleValue] |
CTreeGridCaptionSlotData
Empty dataclass: {}.
CTreeGridToolbarSlotData
Empty dataclass: {}.
CTreeGridHeaderSlotData
| Field | Type | Default | Meaning |
|---|---|---|---|
column | CTreeGridColumn | - | Current Column. |
column_index | int | - | Zero-based Column index. |
CTreeGridCellSlotData
| Field | Type | Default | Meaning |
|---|---|---|---|
row | CTreeGridRow | - | Current Row. |
column | CTreeGridColumn | - | Current Column. |
cell | CTreeGridCell | - | Current Cell. |
row_index | int | - | Zero-based flattened Row index. |
column_index | int | - | Zero-based Column index. |
level | int | - | One-based hierarchy depth. |
expanded | bool | - | Initial branch expansion. |
selected | bool | - | Initial Row selection. |
CTreeGridExpandedChangeDetail
| Field | Type | Default | Meaning |
|---|---|---|---|
expanded | list[str] | - | Requested expanded keys. |
previousExpanded | list[str] | - | Previous keys. |
rowKey | str | - | Changed Row. |
rowExpanded | bool | - | Requested Row state. |
controlled | bool | - | Whether client state is controlled. |
source | CTreeGridSource | - | Interaction source. |
sourceEvent | object | - | Native Event. |
CTreeGridSelectionChangeDetail
| Field | Type | Default | Meaning |
|---|---|---|---|
selected | list[str] | - | Requested selected keys. |
previousSelected | list[str] | - | Previous keys. |
rowKey | str | - | Changed Row. |
rowSelected | bool | - | Requested Row state. |
controlled | bool | - | Whether client state is controlled. |
source | CTreeGridSource | - | Interaction source. |
sourceEvent | object | - | Native Event. |
CTreeGridCellActivateDetail
| Field | Type | Default | Meaning |
|---|---|---|---|
rowKey | str | - | Activated Row. |
columnKey | str | - | Activated Column. |
rowIndex | int | - | Flattened Row index. |
columnIndex | int | - | Column index. |
sourceEvent | object | - | Native Event. |
Translation keys
Catalog keys used by this family. An explicit component input or slot listed in Override takes precedence over the catalog for that instance.
CTreeGrid translation keys
| Key | Purpose | Variables | Override | Browser updates |
|---|---|---|---|---|
citry-ui-tree-grid-expand | Names a collapsed branch control. | row: str | expand_label with {row} | Imperative reactive i18n.bind(). |
citry-ui-tree-grid-collapse | Names an expanded branch control. | row: str | collapse_label with {row} | Imperative reactive i18n.bind(). |
citry-ui-tree-grid-expanded | Announces branch expansion. | row: str | expanded_label with {row} | Browser-created one-shot i18n.tr(). |
citry-ui-tree-grid-collapsed | Announces branch collapse. | row: str | collapsed_label with {row} | Browser-created one-shot i18n.tr(). |
citry-ui-tree-grid-selected | Announces Row selection. | row: str | selected_label with {row} | Browser-created one-shot i18n.tr(). |
citry-ui-tree-grid-unselected | Announces Row unselection. | row: str | unselected_label with {row} | Browser-created one-shot i18n.tr(). |