@chromvoid/uikit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +8 -0
- package/README.md +96 -0
- package/dist/components/cv-accordion-item.d.ts +69 -0
- package/dist/components/cv-accordion-item.js +176 -0
- package/dist/components/cv-accordion.d.ts +79 -0
- package/dist/components/cv-accordion.js +310 -0
- package/dist/components/cv-alert-dialog.d.ts +86 -0
- package/dist/components/cv-alert-dialog.js +393 -0
- package/dist/components/cv-alert.d.ts +48 -0
- package/dist/components/cv-alert.js +156 -0
- package/dist/components/cv-badge.d.ts +56 -0
- package/dist/components/cv-badge.js +280 -0
- package/dist/components/cv-breadcrumb-item.d.ts +35 -0
- package/dist/components/cv-breadcrumb-item.js +64 -0
- package/dist/components/cv-breadcrumb.d.ts +39 -0
- package/dist/components/cv-breadcrumb.js +160 -0
- package/dist/components/cv-button.d.ts +83 -0
- package/dist/components/cv-button.js +541 -0
- package/dist/components/cv-callout.d.ts +32 -0
- package/dist/components/cv-callout.js +221 -0
- package/dist/components/cv-card.d.ts +48 -0
- package/dist/components/cv-card.js +269 -0
- package/dist/components/cv-carousel-slide.d.ts +25 -0
- package/dist/components/cv-carousel-slide.js +51 -0
- package/dist/components/cv-carousel.d.ts +96 -0
- package/dist/components/cv-carousel.js +457 -0
- package/dist/components/cv-checkbox.d.ts +84 -0
- package/dist/components/cv-checkbox.js +274 -0
- package/dist/components/cv-combobox-group.d.ts +15 -0
- package/dist/components/cv-combobox-group.js +34 -0
- package/dist/components/cv-combobox-option.d.ts +30 -0
- package/dist/components/cv-combobox-option.js +66 -0
- package/dist/components/cv-combobox.d.ts +135 -0
- package/dist/components/cv-combobox.js +834 -0
- package/dist/components/cv-command-item.d.ts +30 -0
- package/dist/components/cv-command-item.js +68 -0
- package/dist/components/cv-command-palette.d.ts +105 -0
- package/dist/components/cv-command-palette.js +578 -0
- package/dist/components/cv-context-menu.d.ts +98 -0
- package/dist/components/cv-context-menu.js +515 -0
- package/dist/components/cv-copy-button.d.ts +61 -0
- package/dist/components/cv-copy-button.js +318 -0
- package/dist/components/cv-date-picker.d.ts +161 -0
- package/dist/components/cv-date-picker.js +803 -0
- package/dist/components/cv-dialog.d.ts +89 -0
- package/dist/components/cv-dialog.js +459 -0
- package/dist/components/cv-disclosure.d.ts +57 -0
- package/dist/components/cv-disclosure.js +241 -0
- package/dist/components/cv-drawer.d.ts +102 -0
- package/dist/components/cv-drawer.js +595 -0
- package/dist/components/cv-feed-article.d.ts +26 -0
- package/dist/components/cv-feed-article.js +52 -0
- package/dist/components/cv-feed.d.ts +62 -0
- package/dist/components/cv-feed.js +310 -0
- package/dist/components/cv-grid-cell.d.ts +30 -0
- package/dist/components/cv-grid-cell.js +57 -0
- package/dist/components/cv-grid-column.d.ts +30 -0
- package/dist/components/cv-grid-column.js +43 -0
- package/dist/components/cv-grid-row.d.ts +30 -0
- package/dist/components/cv-grid-row.js +42 -0
- package/dist/components/cv-grid.d.ts +119 -0
- package/dist/components/cv-grid.js +567 -0
- package/dist/components/cv-icon.d.ts +57 -0
- package/dist/components/cv-icon.js +352 -0
- package/dist/components/cv-input.d.ts +127 -0
- package/dist/components/cv-input.js +482 -0
- package/dist/components/cv-landmark.d.ts +32 -0
- package/dist/components/cv-landmark.js +62 -0
- package/dist/components/cv-link.d.ts +22 -0
- package/dist/components/cv-link.js +99 -0
- package/dist/components/cv-listbox-group.d.ts +15 -0
- package/dist/components/cv-listbox-group.js +42 -0
- package/dist/components/cv-listbox.d.ts +81 -0
- package/dist/components/cv-listbox.js +388 -0
- package/dist/components/cv-menu-button.d.ts +118 -0
- package/dist/components/cv-menu-button.js +822 -0
- package/dist/components/cv-menu-group.d.ts +20 -0
- package/dist/components/cv-menu-group.js +48 -0
- package/dist/components/cv-menu-item.d.ts +52 -0
- package/dist/components/cv-menu-item.js +105 -0
- package/dist/components/cv-menu.d.ts +62 -0
- package/dist/components/cv-menu.js +414 -0
- package/dist/components/cv-meter.d.ts +66 -0
- package/dist/components/cv-meter.js +154 -0
- package/dist/components/cv-number.d.ts +139 -0
- package/dist/components/cv-number.js +553 -0
- package/dist/components/cv-option.d.ts +30 -0
- package/dist/components/cv-option.js +84 -0
- package/dist/components/cv-popover.d.ts +87 -0
- package/dist/components/cv-popover.js +373 -0
- package/dist/components/cv-progress-ring.d.ts +45 -0
- package/dist/components/cv-progress-ring.js +169 -0
- package/dist/components/cv-progress.d.ts +45 -0
- package/dist/components/cv-progress.js +148 -0
- package/dist/components/cv-radio-group.d.ts +79 -0
- package/dist/components/cv-radio-group.js +398 -0
- package/dist/components/cv-radio.d.ts +36 -0
- package/dist/components/cv-radio.js +123 -0
- package/dist/components/cv-select-group.d.ts +15 -0
- package/dist/components/cv-select-group.js +44 -0
- package/dist/components/cv-select-option.d.ts +30 -0
- package/dist/components/cv-select-option.js +66 -0
- package/dist/components/cv-select.d.ts +128 -0
- package/dist/components/cv-select.js +666 -0
- package/dist/components/cv-sidebar-item.d.ts +26 -0
- package/dist/components/cv-sidebar-item.js +142 -0
- package/dist/components/cv-sidebar.d.ts +171 -0
- package/dist/components/cv-sidebar.js +767 -0
- package/dist/components/cv-slider-multi-thumb.d.ts +73 -0
- package/dist/components/cv-slider-multi-thumb.js +374 -0
- package/dist/components/cv-slider.d.ts +84 -0
- package/dist/components/cv-slider.js +328 -0
- package/dist/components/cv-spinbutton.d.ts +121 -0
- package/dist/components/cv-spinbutton.js +486 -0
- package/dist/components/cv-spinner.d.ts +18 -0
- package/dist/components/cv-spinner.js +95 -0
- package/dist/components/cv-switch.d.ts +81 -0
- package/dist/components/cv-switch.js +285 -0
- package/dist/components/cv-tab-panel.d.ts +20 -0
- package/dist/components/cv-tab-panel.js +37 -0
- package/dist/components/cv-tab.d.ts +40 -0
- package/dist/components/cv-tab.js +132 -0
- package/dist/components/cv-table-cell.d.ts +31 -0
- package/dist/components/cv-table-cell.js +49 -0
- package/dist/components/cv-table-column.d.ts +37 -0
- package/dist/components/cv-table-column.js +63 -0
- package/dist/components/cv-table-row.d.ts +30 -0
- package/dist/components/cv-table-row.js +45 -0
- package/dist/components/cv-table.d.ts +147 -0
- package/dist/components/cv-table.js +607 -0
- package/dist/components/cv-tabs.d.ts +70 -0
- package/dist/components/cv-tabs.js +524 -0
- package/dist/components/cv-textarea.d.ts +108 -0
- package/dist/components/cv-textarea.js +328 -0
- package/dist/components/cv-toast-region.d.ts +39 -0
- package/dist/components/cv-toast-region.js +162 -0
- package/dist/components/cv-toast.d.ts +67 -0
- package/dist/components/cv-toast.js +315 -0
- package/dist/components/cv-toolbar-item.d.ts +25 -0
- package/dist/components/cv-toolbar-item.js +72 -0
- package/dist/components/cv-toolbar-separator.d.ts +25 -0
- package/dist/components/cv-toolbar-separator.js +45 -0
- package/dist/components/cv-toolbar.d.ts +63 -0
- package/dist/components/cv-toolbar.js +295 -0
- package/dist/components/cv-tooltip.d.ts +83 -0
- package/dist/components/cv-tooltip.js +455 -0
- package/dist/components/cv-treegrid-cell.d.ts +30 -0
- package/dist/components/cv-treegrid-cell.js +57 -0
- package/dist/components/cv-treegrid-column.d.ts +37 -0
- package/dist/components/cv-treegrid-column.js +53 -0
- package/dist/components/cv-treegrid-row.d.ts +55 -0
- package/dist/components/cv-treegrid-row.js +90 -0
- package/dist/components/cv-treegrid.d.ts +96 -0
- package/dist/components/cv-treegrid.js +632 -0
- package/dist/components/cv-treeitem.d.ts +58 -0
- package/dist/components/cv-treeitem.js +144 -0
- package/dist/components/cv-treeview.d.ts +70 -0
- package/dist/components/cv-treeview.js +396 -0
- package/dist/components/cv-window-splitter.d.ts +79 -0
- package/dist/components/cv-window-splitter.js +316 -0
- package/dist/components/index.d.ts +94 -0
- package/dist/components/index.js +79 -0
- package/dist/dialog/create-dialog-controller.d.ts +31 -0
- package/dist/dialog/create-dialog-controller.js +320 -0
- package/dist/dialog/index.d.ts +2 -0
- package/dist/dialog/index.js +1 -0
- package/dist/form-associated/FormAssociatedReatomElement.d.ts +25 -0
- package/dist/form-associated/FormAssociatedReatomElement.js +70 -0
- package/dist/form-associated/withFormAssociated.d.ts +5 -0
- package/dist/form-associated/withFormAssociated.js +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +9 -0
- package/dist/reatom-lit/ReatomLitElement.d.ts +27 -0
- package/dist/reatom-lit/ReatomLitElement.js +118 -0
- package/dist/reatom-lit/html.d.ts +4 -0
- package/dist/reatom-lit/html.js +10 -0
- package/dist/reatom-lit/index.d.ts +4 -0
- package/dist/reatom-lit/index.js +4 -0
- package/dist/reatom-lit/watch.d.ts +15 -0
- package/dist/reatom-lit/watch.js +40 -0
- package/dist/reatom-lit/withReatomElement.d.ts +4 -0
- package/dist/reatom-lit/withReatomElement.js +57 -0
- package/dist/register.d.ts +1 -0
- package/dist/register.js +84 -0
- package/dist/styles/component-styles.d.ts +4 -0
- package/dist/styles/component-styles.js +78 -0
- package/dist/theme/cv-theme-provider.d.ts +32 -0
- package/dist/theme/cv-theme-provider.js +110 -0
- package/dist/theme/index.d.ts +4 -0
- package/dist/theme/index.js +2 -0
- package/dist/theme/theme-engine.d.ts +4 -0
- package/dist/theme/theme-engine.js +67 -0
- package/dist/theme/tokens.css +265 -0
- package/dist/theme/types.d.ts +7 -0
- package/dist/theme/types.js +1 -0
- package/dist/toast/create-toast-controller.d.ts +12 -0
- package/dist/toast/create-toast-controller.js +12 -0
- package/dist/toast/index.d.ts +2 -0
- package/dist/toast/index.js +1 -0
- package/package.json +146 -0
- package/specs/_template.md +110 -0
- package/specs/components/accordion.md +207 -0
- package/specs/components/alert.md +83 -0
- package/specs/components/badge.md +183 -0
- package/specs/components/breadcrumb.md +152 -0
- package/specs/components/button.md +227 -0
- package/specs/components/callout.md +153 -0
- package/specs/components/card.md +192 -0
- package/specs/components/carousel.md +232 -0
- package/specs/components/checkbox.md +141 -0
- package/specs/components/combobox.md +427 -0
- package/specs/components/context-menu.md +375 -0
- package/specs/components/copy-button.md +236 -0
- package/specs/components/date-picker.md +290 -0
- package/specs/components/dialog.md +184 -0
- package/specs/components/disclosure.md +151 -0
- package/specs/components/drawer.md +216 -0
- package/specs/components/feed.md +266 -0
- package/specs/components/grid.md +423 -0
- package/specs/components/input.md +237 -0
- package/specs/components/landmark.md +92 -0
- package/specs/components/link.md +117 -0
- package/specs/components/listbox.md +327 -0
- package/specs/components/menu.md +508 -0
- package/specs/components/meter.md +148 -0
- package/specs/components/number.md +268 -0
- package/specs/components/option.md +167 -0
- package/specs/components/popover.md +207 -0
- package/specs/components/progress-ring.md +134 -0
- package/specs/components/progress.md +110 -0
- package/specs/components/radio.md +208 -0
- package/specs/components/select.md +305 -0
- package/specs/components/sidebar.md +204 -0
- package/specs/components/spinbutton.md +157 -0
- package/specs/components/spinner.md +83 -0
- package/specs/components/switch.md +145 -0
- package/specs/components/table.md +372 -0
- package/specs/components/tabs.md +242 -0
- package/specs/components/textarea.md +166 -0
- package/specs/components/theme.md +364 -0
- package/specs/components/toast.md +198 -0
- package/specs/components/toolbar.md +258 -0
- package/specs/components/tooltip.md +152 -0
- package/specs/components/treegrid.md +363 -0
- package/specs/components/treeview.md +263 -0
- package/specs/components/window-splitter.md +225 -0
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
# cv-treegrid
|
|
2
|
+
|
|
3
|
+
Hierarchical tabular data grid combining multi-column structure with tree expansion/collapse behavior, providing APG-aligned keyboard navigation and row selection.
|
|
4
|
+
|
|
5
|
+
**Headless:** [`createTreegrid`](https://github.com/chromvoid/headless-ui/blob/main/specs/components/treegrid.md)
|
|
6
|
+
|
|
7
|
+
## Anatomy
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
<cv-treegrid> (host)
|
|
11
|
+
└── <div part="base" role="treegrid">
|
|
12
|
+
└── <slot> ← accepts cv-treegrid-column and cv-treegrid-row children
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Attributes
|
|
16
|
+
|
|
17
|
+
| Attribute | Type | Default | Description |
|
|
18
|
+
| ----------------- | ------ | ---------- | ---------------------------------------------------------------------------------------------------------------------- |
|
|
19
|
+
| `value` | String | `""` | Active cell identifier encoded as `"rowId::colId"`; reflects current `activeCellId` from headless state |
|
|
20
|
+
| `selected-values` | — | `[]` | Property-only (not an HTML attribute). Array of selected row id strings; reflects `selectedRowIds` from headless state |
|
|
21
|
+
| `expanded-values` | — | `[]` | Property-only (not an HTML attribute). Array of expanded row id strings; reflects `expandedRowIds` from headless state |
|
|
22
|
+
| `selection-mode` | String | `"single"` | Row selection mode: `single` \| `multiple` |
|
|
23
|
+
| `aria-label` | String | `""` | Accessible label applied to the root `[role=treegrid]` element |
|
|
24
|
+
| `aria-labelledby` | String | `""` | Id reference applied as `aria-labelledby` on the root `[role=treegrid]` element |
|
|
25
|
+
|
|
26
|
+
## Slots
|
|
27
|
+
|
|
28
|
+
| Slot | Description |
|
|
29
|
+
| ----------- | --------------------------------------------------------------------------------------------------------------------------- |
|
|
30
|
+
| `(default)` | Accepts `cv-treegrid-column` definition elements followed by `cv-treegrid-row` elements; slot changes trigger model rebuild |
|
|
31
|
+
|
|
32
|
+
## CSS Parts
|
|
33
|
+
|
|
34
|
+
| Part | Element | Description |
|
|
35
|
+
| ------ | ------- | -------------------------------------------------------------------------------------------------------------- |
|
|
36
|
+
| `base` | `<div>` | Root interactive element with `role="treegrid"`; receives all ARIA grid attributes and keyboard event handling |
|
|
37
|
+
|
|
38
|
+
## CSS Custom Properties
|
|
39
|
+
|
|
40
|
+
| Property | Default | Description |
|
|
41
|
+
| ---------------------------- | -------- | -------------------------------------------------------------------------------------------------------------- |
|
|
42
|
+
| `--cv-treegrid-column-count` | computed | Number of columns; auto-written by `syncElementsFromModel()` onto each row element as an inline style property |
|
|
43
|
+
|
|
44
|
+
Additionally, component styles depend on theme tokens through fallback values:
|
|
45
|
+
|
|
46
|
+
| Theme Property | Default | Description |
|
|
47
|
+
| -------------------- | --------- | ---------------------------------------- |
|
|
48
|
+
| `--cv-color-border` | `#2a3245` | Border color for the base wrapper |
|
|
49
|
+
| `--cv-color-surface` | `#141923` | Background color for the base wrapper |
|
|
50
|
+
| `--cv-color-primary` | `#65d7ff` | Focus outline color for the base wrapper |
|
|
51
|
+
| `--cv-radius-md` | `10px` | Border radius for the base wrapper |
|
|
52
|
+
|
|
53
|
+
## Visual States
|
|
54
|
+
|
|
55
|
+
| Host selector | Description |
|
|
56
|
+
| ----------------------------- | --------------------------------------------------------------------- |
|
|
57
|
+
| `:host` | `display: block`; contains scrollable overflow |
|
|
58
|
+
| `[part="base"]:focus-visible` | `outline: 2px solid var(--cv-color-primary)` at `outline-offset: 1px` |
|
|
59
|
+
|
|
60
|
+
## Events
|
|
61
|
+
|
|
62
|
+
| Event | Detail | Description |
|
|
63
|
+
| ----------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
|
64
|
+
| `cv-input` | `{ value: string \| null, activeCell: TreegridCellId \| null, selectedValues: string[], expandedValues: string[] }` | Fires on any user interaction that changes active cell, selection, or expansion state |
|
|
65
|
+
| `cv-change` | `{ value: string \| null, activeCell: TreegridCellId \| null, selectedValues: string[], expandedValues: string[] }` | Fires when selection or expansion state commits (subset of `cv-input` cases; active-cell-only changes do not fire `cv-change`) |
|
|
66
|
+
|
|
67
|
+
`value` in the detail is `null` when no cell is active, otherwise the `"rowId::colId"` string.
|
|
68
|
+
|
|
69
|
+
`cv-input` and `cv-change` only fire for user-driven interactions (keyboard, pointer). Programmatic changes via `selectedValues`, `expandedValues`, or `value` properties do not re-dispatch these events.
|
|
70
|
+
|
|
71
|
+
## Reactive State Mapping
|
|
72
|
+
|
|
73
|
+
`cv-treegrid` is a visual adapter over headless `createTreegrid`.
|
|
74
|
+
|
|
75
|
+
### UIKit properties → headless actions
|
|
76
|
+
|
|
77
|
+
| UIKit Property | Direction | Headless Binding |
|
|
78
|
+
| ------------------------ | ------------- | ------------------------------------------------------------------------------------------------------- |
|
|
79
|
+
| `value` (attr) | attr → action | `contracts.getCellProps(rowId, colId).onFocus()` (sets active cell) |
|
|
80
|
+
| `selectedValues` (prop) | prop → action | `actions.selectRow(id)` (single mode) or `actions.toggleRowSelection(id)` (multiple mode, diff-applied) |
|
|
81
|
+
| `expandedValues` (prop) | prop → action | `actions.expandRow(id)` / `actions.collapseRow(id)` (diff-applied) |
|
|
82
|
+
| `selectionMode` (attr) | attr → option | passed as `selectionMode` to `createTreegrid(options)` on model rebuild |
|
|
83
|
+
| `aria-label` (attr) | attr → option | passed as `ariaLabel` to `createTreegrid(options)` on model rebuild |
|
|
84
|
+
| `aria-labelledby` (attr) | attr → option | passed as `ariaLabelledBy` to `createTreegrid(options)` on model rebuild |
|
|
85
|
+
|
|
86
|
+
### Headless state → DOM attributes
|
|
87
|
+
|
|
88
|
+
| Headless Signal | Direction | DOM Reflection |
|
|
89
|
+
| ------------------------ | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
90
|
+
| `state.activeCellId()` | state → attr | `value` property (`"rowId::colId"` string); `tabindex="0"` and `data-active="true"` on active cell via `getCellProps` |
|
|
91
|
+
| `state.selectedRowIds()` | state → attr | `selectedValues` property; `aria-selected="true"` on selected rows and cells via `getRowProps`/`getCellProps`; `[selected]` on row and cell elements |
|
|
92
|
+
| `state.expandedRowIds()` | state → attr | `expandedValues` property; `aria-expanded="true/false"` on branch rows via `getRowProps`; child row visibility toggled via `hidden` attribute |
|
|
93
|
+
| `state.rowCount()` | state → attr | `aria-rowcount` on `[part="base"]` via `getTreegridProps` |
|
|
94
|
+
| `state.columnCount()` | state → attr | `aria-colcount` on `[part="base"]` via `getTreegridProps`; `--cv-treegrid-column-count` inline style on each row |
|
|
95
|
+
|
|
96
|
+
### Contracts spread onto DOM elements
|
|
97
|
+
|
|
98
|
+
| Contract | Spread target |
|
|
99
|
+
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
100
|
+
| `contracts.getTreegridProps()` | `[part="base"]` (`role`, `tabindex`, `aria-label`, `aria-labelledby`, `aria-rowcount`, `aria-colcount`, `aria-multiselectable`) |
|
|
101
|
+
| `contracts.getRowProps(rowId)` | Each `cv-treegrid-row` element (`id`, `role`, `aria-level`, `aria-posinset`, `aria-setsize`, `aria-rowindex`, `aria-expanded`, `aria-selected`, `aria-disabled`) |
|
|
102
|
+
| `contracts.getCellProps(rowId, colId)` | Each `cv-treegrid-cell` element (`id`, `role`, `tabindex`, `aria-colindex`, `aria-selected`, `aria-disabled`, `data-active`); `onFocus` wired to cell `focus` event |
|
|
103
|
+
|
|
104
|
+
### Pointer and keyboard action triggers
|
|
105
|
+
|
|
106
|
+
| User Trigger | Action Called |
|
|
107
|
+
| ---------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
108
|
+
| `click` on a cell | Sets active cell via `onFocus()`; then calls `actions.toggleRowSelection(rowId)` in `multiple` mode (plain or `Ctrl/Meta` click both accumulate), or `actions.selectRow(rowId)` (replace) in `single` mode |
|
|
109
|
+
| `keydown` `Enter` or `Space` on active cell | `actions.selectRow(activeRowId)` (non-additive) or `actions.toggleRowSelection(activeRowId)` (when `Ctrl/Meta` held in `multiple` mode) |
|
|
110
|
+
| `keydown` navigation keys | `actions.handleKeyDown(event)` |
|
|
111
|
+
| `focus` on a cell | `contracts.getCellProps(rowId, colId).onFocus()` |
|
|
112
|
+
| slot content change | Model rebuilt from DOM (`rebuildModelFromSlot(preserveState: true)`) |
|
|
113
|
+
| `selection-mode` / `aria-label` / `aria-labelledby` change | Model rebuilt from DOM (`rebuildModelFromSlot(preserveState: true)`) |
|
|
114
|
+
|
|
115
|
+
## Keyboard Interaction
|
|
116
|
+
|
|
117
|
+
Derived from headless `handleKeyDown` contract:
|
|
118
|
+
|
|
119
|
+
| Key | Behavior |
|
|
120
|
+
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
121
|
+
| `ArrowUp` | Move active cell to same column in previous visible enabled row |
|
|
122
|
+
| `ArrowDown` | Move active cell to same column in next visible enabled row |
|
|
123
|
+
| `ArrowLeft` | If focused row is an expanded branch: collapse it. If focused row has a parent: move to same column in parent row. Otherwise: move to previous enabled cell in current row |
|
|
124
|
+
| `ArrowRight` | If focused row is a collapsed branch: expand it (focus stays). If focused row is an expanded branch: move to same column in first child row. Otherwise (leaf): move to next enabled cell in current row |
|
|
125
|
+
| `Home` | Move to first enabled cell in current row |
|
|
126
|
+
| `End` | Move to last enabled cell in current row |
|
|
127
|
+
| `Ctrl+Home` / `Meta+Home` | Move to first enabled cell in first visible enabled row |
|
|
128
|
+
| `Ctrl+End` / `Meta+End` | Move to last enabled cell in last visible enabled row |
|
|
129
|
+
| `Enter` / `Space` | Select active row (toggles in multiple mode when `Ctrl/Meta` held) |
|
|
130
|
+
|
|
131
|
+
Keys `ArrowUp`, `ArrowDown`, `ArrowLeft`, `ArrowRight`, `Home`, `End`, `Enter`, and `Space` are always `preventDefault()`-ed when handled.
|
|
132
|
+
|
|
133
|
+
## ARIA
|
|
134
|
+
|
|
135
|
+
| Element | Role | Required Attributes |
|
|
136
|
+
| ------------------ | ------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
137
|
+
| `[part="base"]` | `treegrid` | `aria-label` or `aria-labelledby`, `aria-multiselectable`, `aria-rowcount`, `aria-colcount` |
|
|
138
|
+
| `cv-treegrid-row` | `row` | `aria-level`, `aria-posinset`, `aria-setsize`, `aria-rowindex`, `aria-selected`; `aria-expanded` (branch rows only); `aria-disabled` (disabled rows only) |
|
|
139
|
+
| `cv-treegrid-cell` | `gridcell` \| `rowheader` \| `columnheader` | `aria-colindex`, `aria-selected`, `tabindex`; `aria-disabled` (disabled cells only) |
|
|
140
|
+
|
|
141
|
+
`aria-level` starts at `1` for root rows. `aria-multiselectable` is `"true"` when `selection-mode="multiple"`, `"false"` otherwise.
|
|
142
|
+
|
|
143
|
+
## Usage
|
|
144
|
+
|
|
145
|
+
```html
|
|
146
|
+
<cv-treegrid aria-label="File tree" selection-mode="single">
|
|
147
|
+
<cv-treegrid-column value="name" cell-role="rowheader">Name</cv-treegrid-column>
|
|
148
|
+
<cv-treegrid-column value="size">Size</cv-treegrid-column>
|
|
149
|
+
|
|
150
|
+
<cv-treegrid-row value="src">
|
|
151
|
+
<cv-treegrid-cell column="name">src/</cv-treegrid-cell>
|
|
152
|
+
<cv-treegrid-cell column="size">—</cv-treegrid-cell>
|
|
153
|
+
<cv-treegrid-row value="index" slot="children">
|
|
154
|
+
<cv-treegrid-cell column="name">index.ts</cv-treegrid-cell>
|
|
155
|
+
<cv-treegrid-cell column="size">2 KB</cv-treegrid-cell>
|
|
156
|
+
</cv-treegrid-row>
|
|
157
|
+
</cv-treegrid-row>
|
|
158
|
+
|
|
159
|
+
<cv-treegrid-row value="readme">
|
|
160
|
+
<cv-treegrid-cell column="name">README.md</cv-treegrid-cell>
|
|
161
|
+
<cv-treegrid-cell column="size">4 KB</cv-treegrid-cell>
|
|
162
|
+
</cv-treegrid-row>
|
|
163
|
+
</cv-treegrid>
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Child Elements
|
|
167
|
+
|
|
168
|
+
### cv-treegrid-row
|
|
169
|
+
|
|
170
|
+
Represents a single data row. Slotted directly into `cv-treegrid` (root rows) or into `slot="children"` of a parent `cv-treegrid-row` (child rows).
|
|
171
|
+
|
|
172
|
+
#### Anatomy
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
<cv-treegrid-row> (host)
|
|
176
|
+
├── <div part="row">
|
|
177
|
+
│ └── <slot> ← accepts cv-treegrid-cell children
|
|
178
|
+
└── <div part="children" hidden?=${!expanded}>
|
|
179
|
+
└── <slot name="children"> ← accepts nested cv-treegrid-row children
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
#### Attributes
|
|
183
|
+
|
|
184
|
+
| Attribute | Type | Default | Description |
|
|
185
|
+
| ---------- | ------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
186
|
+
| `value` | String | `""` | Row identifier. Auto-assigned as `"row-N"` if empty |
|
|
187
|
+
| `index` | Number | `0` | Explicit `aria-rowindex` override; values `< 1` or non-finite are ignored (headless assigns positional index) |
|
|
188
|
+
| `disabled` | Boolean | `false` | Marks row as disabled; excluded from navigation and selection |
|
|
189
|
+
| `active` | Boolean | `false` | Set by parent when a cell in this row is the active cell; drives row-level highlight |
|
|
190
|
+
| `selected` | Boolean | `false` | Set by parent when this row is selected; drives row-level selection styling |
|
|
191
|
+
| `expanded` | Boolean | `false` | Set by parent; controls visibility of `[part="children"]` and reflects `aria-expanded` |
|
|
192
|
+
| `branch` | Boolean | `false` | Set by parent when this row has child rows; used for styling expand/collapse affordance |
|
|
193
|
+
| `level` | Number | `1` | Nesting depth; used to compute `--cv-treegrid-level` for indent. Auto-written by parent `cv-treegrid.syncElementsFromModel()` from `getRowProps()['aria-level']`; root rows get `1`, child rows get `2`, grandchild rows get `3`, etc. |
|
|
194
|
+
|
|
195
|
+
#### Slots
|
|
196
|
+
|
|
197
|
+
| Slot | Description |
|
|
198
|
+
| ----------- | ------------------------------------------------------------------------------ |
|
|
199
|
+
| `(default)` | Accepts `cv-treegrid-cell` elements for the row's columns |
|
|
200
|
+
| `children` | Accepts nested `cv-treegrid-row` elements; shown only when `[expanded]` is set |
|
|
201
|
+
|
|
202
|
+
#### CSS Parts
|
|
203
|
+
|
|
204
|
+
| Part | Element | Description |
|
|
205
|
+
| ---------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
206
|
+
| `row` | `<div>` | Grid row layout element; uses CSS grid with `--cv-treegrid-column-count` columns and left-padding derived from `--cv-treegrid-level` |
|
|
207
|
+
| `children` | `<div>` | Container for nested child rows; `hidden` when `[expanded]` is absent |
|
|
208
|
+
|
|
209
|
+
#### CSS Custom Properties
|
|
210
|
+
|
|
211
|
+
| Property | Default | Description |
|
|
212
|
+
| ---------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
213
|
+
| `--cv-treegrid-child-indent` | `14px` | Horizontal indent per nesting level; applied as `padding-inline-start: calc(--cv-treegrid-child-indent * max(--cv-treegrid-level - 1, 0))` |
|
|
214
|
+
| `--cv-treegrid-level` | `1` | Current nesting depth (written by the row's own render from `this.level`); consumed by `[part="row"]` indent calculation |
|
|
215
|
+
| `--cv-treegrid-column-count` | `1` | Number of columns; written by parent `cv-treegrid` as an inline style on each row; drives the `grid-template-columns` |
|
|
216
|
+
|
|
217
|
+
Additionally, component styles depend on theme tokens:
|
|
218
|
+
|
|
219
|
+
| Theme Property | Default | Description |
|
|
220
|
+
| -------------------- | --------- | ----------------------------------------------------------- |
|
|
221
|
+
| `--cv-color-primary` | `#65d7ff` | Active/selected row background tint and focus outline color |
|
|
222
|
+
| `--cv-space-2` | `8px` | Inline padding for `[part="row"]` |
|
|
223
|
+
|
|
224
|
+
#### Visual States
|
|
225
|
+
|
|
226
|
+
| Host selector | Description |
|
|
227
|
+
| ------------------------------------- | --------------------------------------------------------------------------- |
|
|
228
|
+
| `:host([hidden])` | `display: none` |
|
|
229
|
+
| `:host(:focus-visible) [part="row"]` | `outline: 2px solid var(--cv-color-primary)` at `outline-offset: -2px` |
|
|
230
|
+
| `:host([active]) [part="row"]` | Primary-tinted background (`color-mix(in oklab, primary 18%, transparent)`) |
|
|
231
|
+
| `:host([selected]) [part="row"]` | Same primary-tinted background as `[active]` |
|
|
232
|
+
| `:host([disabled]) [part="row"]` | `opacity: 0.55` |
|
|
233
|
+
| `:host([disabled]) [part="children"]` | `opacity: 0.55` |
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
### cv-treegrid-column
|
|
238
|
+
|
|
239
|
+
Declares a column definition. Rendered as a visual column header inside `cv-treegrid`. Not part of the row grid; used by the parent to build the headless column model.
|
|
240
|
+
|
|
241
|
+
#### Anatomy
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
<cv-treegrid-column> (host)
|
|
245
|
+
└── <span>
|
|
246
|
+
└── <slot> ← falls back to [label] attribute text
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
#### Attributes
|
|
250
|
+
|
|
251
|
+
| Attribute | Type | Default | Description |
|
|
252
|
+
| ----------- | ------- | ------------ | -------------------------------------------------------------------------------------------------- |
|
|
253
|
+
| `value` | String | `""` | Column identifier used to match `cv-treegrid-cell[column]`. Auto-assigned as `"column-N"` if empty |
|
|
254
|
+
| `label` | String | `""` | Fallback text displayed in the default slot when no slot content is provided |
|
|
255
|
+
| `index` | Number | `0` | Explicit `aria-colindex` override; values `< 1` or non-finite are ignored |
|
|
256
|
+
| `disabled` | Boolean | `false` | Disables all cells in this column from navigation |
|
|
257
|
+
| `cell-role` | String | `"gridcell"` | ARIA role for all cells in this column: `gridcell` \| `rowheader` \| `columnheader` |
|
|
258
|
+
|
|
259
|
+
#### Slots
|
|
260
|
+
|
|
261
|
+
| Slot | Description |
|
|
262
|
+
| ----------- | -------------------------------------------------------------- |
|
|
263
|
+
| `(default)` | Column header label; falls back to the `label` attribute value |
|
|
264
|
+
|
|
265
|
+
#### CSS Parts
|
|
266
|
+
|
|
267
|
+
| Part | Element | Description |
|
|
268
|
+
| -------- | ------- | --------------------------------------------------------------- |
|
|
269
|
+
| _(none)_ | — | The column renders an inner `<span>` but exposes no named parts |
|
|
270
|
+
|
|
271
|
+
#### CSS Custom Properties
|
|
272
|
+
|
|
273
|
+
| Property | Default | Description |
|
|
274
|
+
| -------- | ------- | ----------------------------------------------------------------------- |
|
|
275
|
+
| _(none)_ | — | No component-scoped custom properties; layout controlled by host styles |
|
|
276
|
+
|
|
277
|
+
Additionally, component styles depend on theme tokens:
|
|
278
|
+
|
|
279
|
+
| Theme Property | Default | Description |
|
|
280
|
+
| -------------------- | --------- | ----------------------------- |
|
|
281
|
+
| `--cv-color-border` | `#2a3245` | Bottom border color |
|
|
282
|
+
| `--cv-color-text` | `#e8ecf6` | Label text color |
|
|
283
|
+
| `--cv-color-surface` | `#141923` | Column header background base |
|
|
284
|
+
| `--cv-color-primary` | `#65d7ff` | Focus outline color |
|
|
285
|
+
| `--cv-space-2` | `8px` | Inline padding |
|
|
286
|
+
|
|
287
|
+
#### Visual States
|
|
288
|
+
|
|
289
|
+
| Host selector | Description |
|
|
290
|
+
| ----------------------- | ------------------------------------------------------------------------------------------------------ |
|
|
291
|
+
| `:host` | `display: flex`, `min-block-size: 36px`, `font-weight: 600`; bottom border separating header from rows |
|
|
292
|
+
| `:host([disabled])` | `opacity: 0.55` |
|
|
293
|
+
| `:host(:focus-visible)` | `outline: 2px solid var(--cv-color-primary)` at `outline-offset: -2px` |
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
### cv-treegrid-cell
|
|
298
|
+
|
|
299
|
+
Represents a single cell within a `cv-treegrid-row`. The `column` attribute links it to a `cv-treegrid-column` by value.
|
|
300
|
+
|
|
301
|
+
#### Anatomy
|
|
302
|
+
|
|
303
|
+
```
|
|
304
|
+
<cv-treegrid-cell> (host)
|
|
305
|
+
└── <slot> ← cell content
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
#### Attributes
|
|
309
|
+
|
|
310
|
+
| Attribute | Type | Default | Description |
|
|
311
|
+
| ---------- | ------- | ------- | ----------------------------------------------------------------------------------------------------------------- |
|
|
312
|
+
| `column` | String | `""` | Id of the `cv-treegrid-column` this cell belongs to; positional fallback used when value is empty or unrecognized |
|
|
313
|
+
| `disabled` | Boolean | `false` | Marks this specific cell as disabled; excluded from navigation |
|
|
314
|
+
| `active` | Boolean | `false` | Set by parent when this cell is the active cell; drives cell-level highlight |
|
|
315
|
+
| `selected` | Boolean | `false` | Set by parent when the row containing this cell is selected; drives `font-weight: 600` |
|
|
316
|
+
|
|
317
|
+
#### Slots
|
|
318
|
+
|
|
319
|
+
| Slot | Description |
|
|
320
|
+
| ----------- | ------------ |
|
|
321
|
+
| `(default)` | Cell content |
|
|
322
|
+
|
|
323
|
+
#### CSS Parts
|
|
324
|
+
|
|
325
|
+
| Part | Element | Description |
|
|
326
|
+
| -------- | ------- | -------------------------------------------------- |
|
|
327
|
+
| _(none)_ | — | Cell renders a single `<slot>` with no named parts |
|
|
328
|
+
|
|
329
|
+
#### CSS Custom Properties
|
|
330
|
+
|
|
331
|
+
| Property | Default | Description |
|
|
332
|
+
| -------- | ------- | ------------------------------------- |
|
|
333
|
+
| _(none)_ | — | No component-scoped custom properties |
|
|
334
|
+
|
|
335
|
+
Additionally, component styles depend on theme tokens:
|
|
336
|
+
|
|
337
|
+
| Theme Property | Default | Description |
|
|
338
|
+
| -------------------- | --------- | --------------------------------------------------- |
|
|
339
|
+
| `--cv-color-text` | `#e8ecf6` | Cell text color |
|
|
340
|
+
| `--cv-color-primary` | `#65d7ff` | Active cell background tint and focus outline color |
|
|
341
|
+
| `--cv-space-2` | `8px` | Inline padding |
|
|
342
|
+
| `--cv-space-1` | `4px` | Block padding |
|
|
343
|
+
|
|
344
|
+
#### Visual States
|
|
345
|
+
|
|
346
|
+
| Host selector | Description |
|
|
347
|
+
| ----------------------- | --------------------------------------------------------------------------- |
|
|
348
|
+
| `:host` | `display: block` |
|
|
349
|
+
| `:host([active])` | `background: color-mix(in oklab, var(--cv-color-primary) 16%, transparent)` |
|
|
350
|
+
| `:host([selected])` | `font-weight: 600` |
|
|
351
|
+
| `:host([disabled])` | `opacity: 0.55` |
|
|
352
|
+
| `:host(:focus-visible)` | `outline: 2px solid var(--cv-color-primary)` at `outline-offset: -2px` |
|
|
353
|
+
|
|
354
|
+
## Out of Scope
|
|
355
|
+
|
|
356
|
+
- Async loading of child rows (pagination or lazy fetch)
|
|
357
|
+
- Column sorting or column header click behavior
|
|
358
|
+
- Drag and drop row reordering
|
|
359
|
+
- Multiple cell selection (only row-level selection is supported)
|
|
360
|
+
- Virtual / windowed rendering of large datasets
|
|
361
|
+
- Column resizing or column visibility toggling
|
|
362
|
+
- Row grouping beyond the existing tree hierarchy
|
|
363
|
+
- Inline cell editing
|