prime-ui-kit 0.18.0 → 0.20.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/README.md +1 -1
- package/dist/chunks/{chunk-OAXJWF3L.js → chunk-3PY52JP3.js} +1764 -1764
- package/dist/chunks/{chunk-X3JT5CLR.js → chunk-4KONMO7Z.js} +1 -1
- package/dist/chunks/{chunk-MB4CXSLL.js → chunk-W6EGTNG6.js} +3772 -2888
- package/dist/color-picker.js +2 -2
- package/dist/components/data-table/ColumnsMenu.d.ts +39 -17
- package/dist/components/data-table/DataTable.d.ts +41 -12
- package/dist/components/data-table/DataTableColumnsMenu.d.ts +45 -0
- package/dist/components/data-table/Head.d.ts +18 -5
- package/dist/components/data-table/Row.d.ts +10 -4
- package/dist/components/data-table/StateRows.d.ts +5 -3
- package/dist/components/data-table/columnOrder.d.ts +14 -0
- package/dist/components/data-table/reorder.d.ts +15 -5
- package/dist/components/data-table/types.d.ts +5 -0
- package/dist/components/data-table/useFrozenColumns.d.ts +6 -2
- package/dist/components/datepicker/DatepickerPanel.d.ts +1 -1
- package/dist/components/dnd/Dnd.d.ts +9 -5
- package/dist/components/dnd/inPlaceRow.d.ts +7 -0
- package/dist/components/dnd/useDragSource.d.ts +2 -0
- package/dist/components/dnd/useSortableList.d.ts +5 -0
- package/dist/components/field-list/FieldList.d.ts +37 -15
- package/dist/components/gantt/Gantt.d.ts +1 -1
- package/dist/components/index.d.ts +3 -1
- package/dist/components/kanban/Kanban.d.ts +4 -0
- package/dist/components/list/List.d.ts +9 -4
- package/dist/components/scroll-container/ScrollContainer.d.ts +1 -1
- package/dist/index.css +1 -1
- package/dist/index.js +4 -2
- package/dist/internal/ToolRow.d.ts +23 -0
- package/dist/internal/leaveGuard.d.ts +6 -0
- package/dist/internal/overlay/DialogGuard.d.ts +3 -2
- package/dist/internal/overlay/DialogParts.d.ts +14 -5
- package/dist/layout/index.d.ts +1 -1
- package/dist/layout/page/Page.d.ts +8 -14
- package/dist/skill/anti-slop.md +55 -1
- package/dist/skill/api-contract.md +2 -2
- package/dist/skill/cheatsheet.md +12 -4
- package/dist/skill/checklist.md +7 -0
- package/dist/skill/choosing.md +1 -0
- package/dist/skill/components.md +1 -1
- package/dist/skill/composition.md +196 -21
- package/dist/skill/layouts.md +1 -1
- package/dist/skill/reference/components/confirm-dialog/COMPONENT.md +1 -1
- package/dist/skill/reference/components/data-table/COMPONENT.md +110 -49
- package/dist/skill/reference/components/data-table/examples/actions-column.tsx +154 -0
- package/dist/skill/reference/components/data-table/examples/column-order.tsx +152 -0
- package/dist/skill/reference/components/data-table/examples/columns-visibility.tsx +18 -18
- package/dist/skill/reference/components/data-table/examples/controlled.tsx +32 -17
- package/dist/skill/reference/components/data-table/examples/examples.module.css +14 -36
- package/dist/skill/reference/components/data-table/examples/narrow.tsx +25 -19
- package/dist/skill/reference/components/data-table/examples/reorder.tsx +24 -2
- package/dist/skill/reference/components/data-table/examples/row-link.tsx +18 -22
- package/dist/skill/reference/components/data-table/examples/screen.tsx +12 -1
- package/dist/skill/reference/components/data-table/examples/selection.tsx +13 -18
- package/dist/skill/reference/components/data-table/examples/server.tsx +45 -31
- package/dist/skill/reference/components/data-table/examples/toolbar.tsx +22 -35
- package/dist/skill/reference/components/datepicker/COMPONENT.md +2 -2
- package/dist/skill/reference/components/dnd/COMPONENT.md +13 -7
- package/dist/skill/reference/components/dnd/examples/examples.module.css +4 -3
- package/dist/skill/reference/components/dnd/examples/handle.tsx +5 -5
- package/dist/skill/reference/components/dnd/examples/locked.tsx +1 -1
- package/dist/skill/reference/components/dnd/examples/table-columns.tsx +75 -0
- package/dist/skill/reference/components/dnd/examples/table.tsx +6 -6
- package/dist/skill/reference/components/drawer/COMPONENT.md +26 -10
- package/dist/skill/reference/components/drawer/examples/header-actions.tsx +1 -1
- package/dist/skill/reference/components/drawer/examples/loading.tsx +58 -0
- package/dist/skill/reference/components/field-list/COMPONENT.md +78 -47
- package/dist/skill/reference/components/field-list/examples/base-row.tsx +2 -1
- package/dist/skill/reference/components/field-list/examples/locked.tsx +11 -11
- package/dist/skill/reference/components/field-list/examples/narrow.tsx +108 -33
- package/dist/skill/reference/components/field-list/examples/reorder.tsx +1 -1
- package/dist/skill/reference/components/field-list/examples/row-menu.tsx +71 -0
- package/dist/skill/reference/components/field-list/examples/screen.module.css +1 -1
- package/dist/skill/reference/components/field-list/examples/screen.tsx +169 -162
- package/dist/skill/reference/components/field-list/examples/totals.tsx +9 -8
- package/dist/skill/reference/components/field-list/examples/variants.tsx +51 -0
- package/dist/skill/reference/components/gantt/COMPONENT.md +4 -4
- package/dist/skill/reference/components/kanban/COMPONENT.md +6 -2
- package/dist/skill/reference/components/kanban/examples/states.tsx +7 -5
- package/dist/skill/reference/components/list/COMPONENT.md +21 -11
- package/dist/skill/reference/components/list/examples/reorder.tsx +42 -7
- package/dist/skill/reference/components/modal/COMPONENT.md +23 -10
- package/dist/skill/reference/components/scroll-container/COMPONENT.md +1 -1
- package/dist/skill/reference/components/segmented-control/COMPONENT.md +3 -2
- package/dist/skill/reference/components/sheet/COMPONENT.md +18 -7
- package/dist/skill/reference/components/smart-filter/COMPONENT.md +2 -2
- package/dist/skill/reference/layout/page/COMPONENT.md +13 -17
- package/dist/skill/reference/layout/page/examples/screen.module.css +1 -1
- package/dist/skill/reference/layout/page/examples/screen.tsx +93 -104
- package/dist/skill/reference/layout/page/examples/sections.tsx +2 -15
- package/dist/skill/responsive.md +14 -10
- package/dist/tokens/semantic.d.ts +2 -2
- package/dist/tokens/themes/dark.d.ts +1 -1
- package/package.json +1 -1
- package/src/components/confirm-dialog/COMPONENT.md +1 -1
- package/src/components/data-table/COMPONENT.md +110 -49
- package/src/components/data-table/examples/actions-column.tsx +154 -0
- package/src/components/data-table/examples/column-order.tsx +152 -0
- package/src/components/data-table/examples/columns-visibility.tsx +18 -18
- package/src/components/data-table/examples/controlled.tsx +32 -17
- package/src/components/data-table/examples/examples.module.css +14 -36
- package/src/components/data-table/examples/narrow.tsx +25 -19
- package/src/components/data-table/examples/reorder.tsx +24 -2
- package/src/components/data-table/examples/row-link.tsx +18 -22
- package/src/components/data-table/examples/screen.tsx +12 -1
- package/src/components/data-table/examples/selection.tsx +13 -18
- package/src/components/data-table/examples/server.tsx +45 -31
- package/src/components/data-table/examples/toolbar.tsx +22 -35
- package/src/components/datepicker/COMPONENT.md +2 -2
- package/src/components/dnd/COMPONENT.md +13 -7
- package/src/components/dnd/examples/examples.module.css +4 -3
- package/src/components/dnd/examples/handle.tsx +5 -5
- package/src/components/dnd/examples/locked.tsx +1 -1
- package/src/components/dnd/examples/table-columns.tsx +75 -0
- package/src/components/dnd/examples/table.tsx +6 -6
- package/src/components/drawer/COMPONENT.md +26 -10
- package/src/components/drawer/examples/header-actions.tsx +1 -1
- package/src/components/drawer/examples/loading.tsx +58 -0
- package/src/components/field-list/COMPONENT.md +78 -47
- package/src/components/field-list/examples/base-row.tsx +2 -1
- package/src/components/field-list/examples/locked.tsx +11 -11
- package/src/components/field-list/examples/narrow.tsx +108 -33
- package/src/components/field-list/examples/reorder.tsx +1 -1
- package/src/components/field-list/examples/row-menu.tsx +71 -0
- package/src/components/field-list/examples/screen.module.css +1 -1
- package/src/components/field-list/examples/screen.tsx +169 -162
- package/src/components/field-list/examples/totals.tsx +9 -8
- package/src/components/field-list/examples/variants.tsx +51 -0
- package/src/components/gantt/COMPONENT.md +4 -4
- package/src/components/kanban/COMPONENT.md +6 -2
- package/src/components/kanban/examples/states.tsx +7 -5
- package/src/components/list/COMPONENT.md +21 -11
- package/src/components/list/examples/reorder.tsx +42 -7
- package/src/components/modal/COMPONENT.md +23 -10
- package/src/components/scroll-container/COMPONENT.md +1 -1
- package/src/components/segmented-control/COMPONENT.md +3 -2
- package/src/components/sheet/COMPONENT.md +18 -7
- package/src/components/smart-filter/COMPONENT.md +2 -2
- package/src/layout/page/COMPONENT.md +13 -17
- package/src/layout/page/examples/screen.module.css +1 -1
- package/src/layout/page/examples/screen.tsx +93 -104
- package/src/layout/page/examples/sections.tsx +2 -15
- package/src/styles/theme-dark.css +1 -1
- package/src/styles/theme-light.css +1 -1
- package/dist/components/data-table/context.d.ts +0 -14
|
@@ -7,14 +7,16 @@
|
|
|
7
7
|
|
|
8
8
|
## When to use
|
|
9
9
|
- Lists of records with several attributes to compare: orders, invoices, users, campaigns.
|
|
10
|
-
- Data that needs sorting, paging
|
|
10
|
+
- Data that needs sorting, paging or bulk selection.
|
|
11
11
|
- Thousands of records the server sorts and pages (`source="server"` + `rowCount`): the table shows the one page the server returned.
|
|
12
12
|
- Rows that open a record: a page (`getRowHref`, a real link) or a drawer in place (`onRowClick`).
|
|
13
13
|
- Rows grouped by a key with a header and totals per group (`getRowGroup`).
|
|
14
|
-
- Records whose order is data the user sets: pipeline stages, a price list, priorities (`onReorder`).
|
|
14
|
+
- Records whose order is data the user sets: pipeline stages, a price list, priorities (`onReorder`; the grip ends the row, `reorderHandle` moves it).
|
|
15
|
+
- Tables people arrange for themselves: their own column order and set (`columnOrder` + `hiddenColumns`, saved by the app).
|
|
15
16
|
- Hierarchical rows (`getRowChildren`) or rows with a detail panel (`renderExpanded`).
|
|
16
17
|
- Wide numeric reports with a sticky head and first column.
|
|
17
|
-
- Wide records on narrow screens: let people choose the columns (`
|
|
18
|
+
- Wide records on narrow screens: let people choose the columns (`columnsMenu` over the row actions, else `DataTableColumnsMenu` beside the table's other tools) instead of dropping them.
|
|
19
|
+
- A table among other blocks (KPI cards, a chart): its search, filter, chips, column chooser and view stand in its own tools row (`toolbar` + `toolbarChips`) — a filter stands next to what it filters. The page's bar keeps the title, a period that drives several blocks and the primary action.
|
|
18
20
|
- A log or a register that takes the rest of the page height (`scrollHeight="fill"`).
|
|
19
21
|
|
|
20
22
|
## When not to use
|
|
@@ -28,24 +30,34 @@
|
|
|
28
30
|
|
|
29
31
|
## Import
|
|
30
32
|
```tsx
|
|
31
|
-
import { DataTable, type DataTableColumn } from "prime-ui-kit";
|
|
33
|
+
import { DataTable, type DataTableColumn, DataTableColumnsMenu } from "prime-ui-kit";
|
|
32
34
|
```
|
|
33
|
-
Exported types: `DataTableColumn<Row>`, `DataTableProps<Row>`, `DataTableSortState`, `DataTableOrder`, `DataTableGroup<Row>`, `DataTableRowClickEvent`, `
|
|
35
|
+
Exported types: `DataTableColumn<Row>`, `DataTableProps<Row>`, `DataTableSortState`, `DataTableOrder`, `DataTableGroup<Row>`, `DataTableRowClickEvent`, `DataTableLabels`, `DataTableColumnsMenuProps<Row>`, `DataTableColumnsMenuLabels`.
|
|
34
36
|
|
|
35
37
|
## Anatomy
|
|
36
38
|
```
|
|
37
39
|
DataTable card-fill block, radius 12, clips its content
|
|
38
|
-
├── toolbar
|
|
39
|
-
│ └──
|
|
40
|
+
├── toolbar the table's own tools row (ToolRow, as Page.Tools): search, filter, chooser, view, bulk actions
|
|
41
|
+
│ └── toolbarChips the applied filters (SmartFilter.Chips) on a line under it, gone while empty
|
|
40
42
|
├── scroll viewport ScrollContainer, both axes, in a frame that holds the edge shadows
|
|
41
43
|
│ └── table
|
|
42
|
-
│ ├── thead [
|
|
44
|
+
│ ├── thead [grip] [select all] [toggle] head cells [end grip cell]; sortable heads hold a button
|
|
45
|
+
│ │ columnsMenu: an icon Button + Dropdown in the row-actions head cell (the last
|
|
46
|
+
│ │ column, hideHeader); with columnOrder a Dnd.Sortable list inside
|
|
47
|
+
│ │ columnOrder: the head row is a Dnd.Sortable; a header moves alone (drag, Alt + ← / →)
|
|
43
48
|
│ └── tbody rows · sub-rows · detail rows · skeleton / empty / error row
|
|
44
49
|
│ (one per group) with getRowGroup: a <th scope="rowgroup"> header row, then its rows
|
|
45
|
-
│ with onReorder: a Dnd.Sortable tbody
|
|
50
|
+
│ with onReorder: a Dnd.Sortable tbody; a Dnd.Handle ends each row (reorderHandle
|
|
51
|
+
│ "end"), leads it ("start"), or the row itself is the grip ("row")
|
|
46
52
|
└── footer range «Показано 1–5 из 23» · Pagination · infinite-scroll status
|
|
47
53
|
```
|
|
48
|
-
|
|
54
|
+
```
|
|
55
|
+
DataTableColumnsMenu the column chooser outside the table, for the page's tools
|
|
56
|
+
├── soft Button view.columns icon · labels.columns · Badge with the count of shown columns
|
|
57
|
+
└── Dropdown a «Показывать» group of check items (with onColumnOrderChange a Dnd.Sortable list,
|
|
58
|
+
a grip ends each item) · «Показать все» · «Исходный порядок»
|
|
59
|
+
```
|
|
60
|
+
Columns are data (`DataTableColumn<Row>[]`), not child parts; the table has no parts. The column chooser has one place per table: the `columnsMenu` flag puts it in the head of the row-actions column; a table without one gets `DataTableColumnsMenu` beside the table's other tools — in its `toolbar` on a page that holds more than the table, in `Page.Tools` on a page that is the table — bound to the same `hiddenColumns` / `columnOrder` state; never alone in a `toolbar`.
|
|
49
61
|
|
|
50
62
|
## API
|
|
51
63
|
|
|
@@ -57,9 +69,13 @@ Generic `DataTable<Row>`; `ref` → `HTMLDivElement`. A card-fill block with an
|
|
|
57
69
|
| Prop | Type | Default | Description |
|
|
58
70
|
|---|---|---|---|
|
|
59
71
|
| `columns` | `DataTableColumn<Row>[]` | — (required) | Column definitions, see `DataTableColumn<Row>`. |
|
|
60
|
-
| `hiddenColumns` | `string[]` | — | Ids of columns that are not rendered, controlled. A column with `hideable: false` stays.
|
|
72
|
+
| `hiddenColumns` | `string[]` | — | Ids of columns that are not rendered, controlled. A column with `hideable: false` stays. The column chooser (`columnsMenu`, `DataTableColumnsMenu`) changes it. |
|
|
61
73
|
| `defaultHiddenColumns` | `string[]` | `[]` | Initially hidden column ids, uncontrolled. |
|
|
62
|
-
| `onHiddenColumnsChange` | `(hiddenColumns: string[]) => void` | — | The hidden ids changed (`
|
|
74
|
+
| `onHiddenColumnsChange` | `(hiddenColumns: string[]) => void` | — | The hidden ids changed (`columnsMenu`). The kit stores nothing: keep the list (local storage, the user's settings) and pass it back to restore the choice. |
|
|
75
|
+
| `columnOrder` | `string[]` | — | Column ids in screen order, hidden ones keeping their place, controlled. Any prop of this triad makes columns reorder: a header drag (the body stays until the drop), Alt + ← / → on a header, grips in the column chooser. |
|
|
76
|
+
| `defaultColumnOrder` | `string[]` | — | Initial column order, uncontrolled; `[]` — the order of `columns`, reorderable. |
|
|
77
|
+
| `onColumnOrderChange` | `(columnOrder: string[]) => void` | — | The order changed: a header dropped, a keyboard move, a chooser grip or «Исходный порядок». The kit stores nothing: keep it with `hiddenColumns` and pass it back. |
|
|
78
|
+
| `columnsMenu` | `boolean` | `false` | The column chooser in the head of the row-actions column (the last one, `hideHeader`); reorders with `columnOrder`. Without that column it renders nothing and warns: use `DataTableColumnsMenu` in the page's tools. |
|
|
63
79
|
| `rows` | `Row[]` | — (required) | Data; sorted in memory when a sort is set. With `source="server"` — the page (or the loaded batches) as the server returned it. |
|
|
64
80
|
| `source` | `"client" \| "server"` | `"client"` | Who sorts and pages the rows. `client`: the table sorts `rows` and slices pages. `server`: `rows` is one page, already sorted; `sort` / `page` changes are the request, `rowCount` drives Pagination. |
|
|
65
81
|
| `rowCount` | `number` | `rows.length` | Total rows on the server (`source="server"`): the page count and «Показано {from}–{to} из {total}». |
|
|
@@ -78,12 +94,14 @@ Generic `DataTable<Row>`; `ref` → `HTMLDivElement`. A card-fill block with an
|
|
|
78
94
|
| `loadingRows` | `number` | `min(pageSize, 5)` | Number of skeleton rows. |
|
|
79
95
|
| `empty` | `ReactNode` | `labels.empty` | Empty-state content: a string goes into a compact EmptyPage, a node (e.g. a full `EmptyPage`) is rendered as is. |
|
|
80
96
|
| `loadError` | `ReactNode` | — | Load error: replaces the body with the message in `role="alert"`. |
|
|
81
|
-
| `toolbar` | `ReactNode` | — |
|
|
97
|
+
| `toolbar` | `ReactNode` | — | The table's own tools row — search, filter, `DataTableColumnsMenu`, a view, bulk actions; two or more, unwrapped. Laid out as `Page.Tools`: the search takes the free room, the rest keep their width at the end. |
|
|
98
|
+
| `toolbarChips` | `ReactNode` | — | The applied filters (`SmartFilter.Chips`) on a line under the `toolbar`, gone while empty; `SmartFilter.Root` wraps the DataTable. |
|
|
82
99
|
| `selectable` | `boolean` | `false` | Leading checkbox column with «select all», Shift range, press-and-drag and Space. |
|
|
83
100
|
| `selected` | `Key[]` | — | Selected row ids, controlled. |
|
|
84
101
|
| `defaultSelected` | `Key[]` | `[]` | Initially selected ids, uncontrolled. |
|
|
85
102
|
| `onSelectedChange` | `(selected: Key[]) => void` | — | Selection change. |
|
|
86
|
-
| `onReorder` | `(id: Key, beforeId: Key \| null) => void \| Promise<void>` | — | Rows reorder by a
|
|
103
|
+
| `onReorder` | `(id: Key, beforeId: Key \| null) => void \| Promise<void>` | — | Rows reorder (by a grip, see `reorderHandle`). Row `id` goes in front of `beforeId` (`null` = last); apply it with `moveBefore`, return a promise to save. Off while sorted by a column. |
|
|
104
|
+
| `reorderHandle` | `"start" \| "end" \| "row"` | `"end"` | Where a row is picked up (`onReorder`): `end` — a grip ends the row; `start` — a grip column leads it; `row` — no grip, the whole row is carried and takes Alt + ↑ / ↓ itself. |
|
|
87
105
|
| `getRowChildren` | `(row: Row) => Row[] \| undefined` | — | Sub-rows rendered under the parent with the same columns, indented by depth. |
|
|
88
106
|
| `renderExpanded` | `(row: Row) => ReactNode` | — | Full-width detail row under an expanded row. |
|
|
89
107
|
| `isRowExpandable` | `(row: Row) => boolean` | — | Which rows get an expand toggle; by default rows with sub-rows, or every row with `renderExpanded`. |
|
|
@@ -97,6 +115,7 @@ Generic `DataTable<Row>`; `ref` → `HTMLDivElement`. A card-fill block with an
|
|
|
97
115
|
| `scrollHeight` | `number \| string \| "fill"` | `360` with `paging="infinite"`, else none | Max height of the scroll viewport (number = px); `"fill"` — the table takes the height of its flex / grid parent (or a sized block), the rows scroll inside, infinite paging follows it. |
|
|
98
116
|
| `stickyHeader` | `boolean` | `false` | The head sticks while the body scrolls (with `scrollHeight`); on screens lower than 480px it scrolls with the rows. |
|
|
99
117
|
| `stickyFirstColumn` | `boolean` | `false` | The first visible column (with the selection and toggle columns) sticks while scrolling sideways; the start edge shadow falls from its end edge. |
|
|
118
|
+
| `stickyLastColumn` | `boolean` | `false` | The last visible column (row actions) sticks to the end edge while scrolling sideways; the end edge shadow falls from its start edge. |
|
|
100
119
|
| `showHeader` | `boolean` | `true` | Render `<thead>`. |
|
|
101
120
|
| `fullWidth` | `boolean` | `true` | The table spans its container; `false` sizes the table and its surface by its content (up to the container's width, then it scrolls). |
|
|
102
121
|
| `rowDividers` | `boolean` | `true` | Hairlines between rows. |
|
|
@@ -117,14 +136,19 @@ Generic `DataTable<Row>`; `ref` → `HTMLDivElement`. A card-fill block with an
|
|
|
117
136
|
| `className` | `string` | — | Class on the root `<div>`. |
|
|
118
137
|
| `…rest` | `Omit<HTMLAttributes<HTMLDivElement>, "children">` | — | The other attributes of the root `<div>`. |
|
|
119
138
|
|
|
120
|
-
###
|
|
121
|
-
`ref` → `HTMLButtonElement
|
|
139
|
+
### DataTableColumnsMenu
|
|
140
|
+
Generic `DataTableColumnsMenu<Row>`; `ref` → `HTMLButtonElement`. The column chooser outside the table, for the page's tools: a soft Button «Колонки» with the count of shown columns, opening the same menu as `columnsMenu`. Bound to the table's state.
|
|
122
141
|
|
|
123
142
|
| Prop | Type | Default | Description |
|
|
124
143
|
|---|---|---|---|
|
|
125
|
-
| `
|
|
126
|
-
| `
|
|
127
|
-
|
|
|
144
|
+
| `columns` | `DataTableColumn<Row>[]` | — (required) | The table's `columns`, in the order of the code. |
|
|
145
|
+
| `hiddenColumns` | `string[]` | — (required) | The ids the table hides: the same list its `hiddenColumns` reads. |
|
|
146
|
+
| `onHiddenColumnsChange` | `(hiddenColumns: string[]) => void` | — (required) | A column was shown or hidden, or «Показать все». |
|
|
147
|
+
| `columnOrder` | `string[]` | — | The table's `columnOrder`. |
|
|
148
|
+
| `onColumnOrderChange` | `(columnOrder: string[]) => void` | — | Turns the items into a sortable list (a grip, Alt + ↑ / ↓) with «Исходный порядок»; the new order of every column. |
|
|
149
|
+
| `size` | `"xs" \| "s" \| "m" \| "l" \| "xl"` | host tier, else `"m"` | Tier of the trigger and the menu. |
|
|
150
|
+
| `labels` | `Partial<DataTableColumnsMenuLabels>` | — | The chooser's strings: `columns`, `showColumns`, `showAllColumns`, `resetColumnOrder`, `reorderColumn`. |
|
|
151
|
+
| `…rest` | `Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children" \| "type">` | — | `className` and the other attributes of the trigger button. |
|
|
128
152
|
|
|
129
153
|
### Types
|
|
130
154
|
|
|
@@ -147,7 +171,8 @@ One column of `columns`: data, not a part.
|
|
|
147
171
|
| `numeric` | `boolean` | — | Tabular figures, no wrapping, end alignment unless `align` is set. |
|
|
148
172
|
| `truncate` | `boolean` | — | One line with an ellipsis; width from `maxWidth` (or `width`); string values get a `title`. |
|
|
149
173
|
| `grow` | `boolean` | — | Takes the free width and wraps its text; the table then fills its container. With `minWidth` it never gets narrower: below that the table scrolls instead of cells overlapping. |
|
|
150
|
-
| `hideable` | `boolean` | `true` | The column can be hidden through `hiddenColumns` and `
|
|
174
|
+
| `hideable` | `boolean` | `true` | The column can be hidden through `hiddenColumns` and `columnsMenu`; `false` for the key column that names the row and for the row-actions column. |
|
|
175
|
+
| `reorderable` | `boolean` | `true` | The column moves when columns reorder (`columnOrder`); `false` holds its place: no column moves past it, the chooser shows a lock. A `hideHeader` column and a pinned first or last column (`stickyFirstColumn`, `stickyLastColumn`) hold theirs too. |
|
|
151
176
|
| `scale` | `boolean \| { min?: number; max?: number }` | — | Heatmap: each cell is shaded by its numeric value on the five-step chart scale. `true` spans the column's minimum to maximum over all rows; `{ min, max }` fixes either end. |
|
|
152
177
|
| `width · minWidth · maxWidth` | `string` | — | CSS sizes of the column (`"14rem"`). |
|
|
153
178
|
|
|
@@ -205,6 +230,13 @@ on screen.
|
|
|
205
230
|
|
|
206
231
|
With both `getRowHref` and `onRowClick`, `onRowClick` gets only plain clicks: `event.preventDefault()` there routes in the app, while ⌘/Ctrl-clicks, middle clicks and «open in new tab» stay the browser's.
|
|
207
232
|
|
|
233
|
+
### reorderHandle
|
|
234
|
+
| Value | Looks like | Use when | Default |
|
|
235
|
+
|---|---|---|---|
|
|
236
|
+
| `end` | a grip (`Dnd.Handle`) ends every row, in the trailing cell under the column chooser; it sticks with `stickyLastColumn` | most tables: the kit's place for a grip (List, FieldList, Kanban), clear of the selection and the key cell | yes |
|
|
237
|
+
| `start` | a grip column leads every row, before the checkboxes; it sticks with `stickyFirstColumn` | a list whose order is its main point (stages, a playlist) read from the start edge | |
|
|
238
|
+
| `row` | no grip: the whole row is carried (the cursor says so; a finger holds still), the row itself takes Tab and Alt + ↑ / ↓; its text cannot be selected, the checkbox cell only selects | short lists of settings or priorities with nothing to select, copy or open by a link in their rows | |
|
|
239
|
+
|
|
208
240
|
### column `align`
|
|
209
241
|
| Value | Looks like | Use when | Default |
|
|
210
242
|
|---|---|---|---|
|
|
@@ -223,9 +255,13 @@ Heads keep `start` whatever the cell alignment, with the sort icon at the end ed
|
|
|
223
255
|
| `highlightRowOnHover` | `fill-subtle-active` wash on the hovered row (stronger than a zebra step, so a hovered row never takes a zebra row's color) | interactive lists | `true` |
|
|
224
256
|
| `highlightColumnOnHover` | `fill-subtle-active` wash on the hovered column | comparison tables | `false` |
|
|
225
257
|
| `stickyHeader` · `stickyFirstColumn` | opaque sticky head / first column with a hairline edge; on screens lower than 480px the head scrolls with the rows | long / wide tables in a `scrollHeight` window | `false` |
|
|
258
|
+
| `stickyLastColumn` | the last visible column sticks to the end edge, opaque in the row's fill (hover, zebra, selected, expanded), with a hairline on its start edge | a row actions column (⋯ menu, an icon Button) of a table wider than its container | `false` |
|
|
226
259
|
| `stickyGroupHeaders` | group header rows stick under the head while their rows scroll | long grouped tables in a `scrollHeight` window | `false` |
|
|
227
260
|
| `collapsedGroups` · `defaultCollapsedGroups` · `onCollapsedGroupsChange` | any of the three makes groups fold: a chevron toggle leads each group header, a collapsed group shows its header alone | long grouped tables where people work one group at a time; `defaultCollapsedGroups={[]}` starts with every group open | off |
|
|
228
|
-
|
|
|
261
|
+
| `columnsMenu` | an icon-only ghost Button (`view.columns`) in the head cell of the row-actions column (the last column, `hideHeader`), lined up with the ⋯ under it; it opens the column chooser. Without that column nothing renders and the table warns | a table with row actions and more columns than a narrow screen holds; without row actions, `DataTableColumnsMenu` in the page's tools | `false` |
|
|
262
|
+
| column `hideable` | `false`: the column stays even when listed in `hiddenColumns`; checked and disabled in the column chooser | the key column that names the row, the row-actions column | `true` |
|
|
263
|
+
| `columnOrder` · `defaultColumnOrder` · `onColumnOrderChange` | any of the three makes columns reorder: a press that moves on a header carries the header alone (a finger holds still) while the body stays, Alt + ← / → on the header, grips in the column chooser plus «Исходный порядок» | tables people arrange for themselves; `defaultColumnOrder={[]}` starts in the order of `columns` | off |
|
|
264
|
+
| column `reorderable` | `false`: the column holds its place — its header carries nothing, no column moves past it, the chooser shows a lock. A `hideHeader` column and a pinned first / last column hold theirs too | the key column, a total that must stay last | `true` |
|
|
229
265
|
| `showHeader` | head row shown | off only for self-explanatory key/value tables | `true` |
|
|
230
266
|
| `fullWidth` | spans the container; `false` = content width | `false` for short lookup tables in wide layouts | `true` |
|
|
231
267
|
| column `numeric` | tabular figures, end-aligned, no wrap | numbers, money | — |
|
|
@@ -249,37 +285,44 @@ Heads keep `start` whatever the cell alignment, with the sort icon at the end ed
|
|
|
249
285
|
| expanded | `expanded` / `defaultExpanded` | `data-expanded` on the parent row (one step darker); toggle `aria-expanded`, chevron turns 90° |
|
|
250
286
|
| new rows | rows new in `rows` (by `getRowKey`) | `data-animate`: top-level cells drop in from above (`enterMotion`) |
|
|
251
287
|
| sub-rows and detail panels | an expand / a collapse | both fold open and shut through the kit's Disclosure (`0fr ↔ 1fr`, the fade and a short slide on the same `base` clock; a detail opens on the enter curve); the row height and padding live inside the fold, so nothing is left to jump. Sub-rows: `data-fold` on the row (`open` · `closed`), every cell's content a Disclosure; a collapsed row's sub-rows stay mounted until the fold ends. Detail row: `data-state`; it unmounts after the close |
|
|
252
|
-
| overflowing sideways | the table is wider than its viewport | `data-overflow-start` (scrolled from the start) and `data-overflow-end` (more to the end) on the root: a soft shadow over that edge, from the end edge of the sticky first column for the start; fades in and out over `fast` |
|
|
253
|
-
| hidden columns | `hiddenColumns` / `defaultHiddenColumns`, `
|
|
288
|
+
| overflowing sideways | the table is wider than its viewport | `data-overflow-start` (scrolled from the start) and `data-overflow-end` (more to the end) on the root: a soft shadow over that edge, from the end edge of the sticky first column for the start and from the start edge of the sticky last column for the end; fades in and out over `fast` |
|
|
289
|
+
| hidden columns | `hiddenColumns` / `defaultHiddenColumns`, `columnsMenu`, `DataTableColumnsMenu` | the listed columns (except `hideable: false`) are not rendered in the head, rows, skeleton or state rows; widths are measured again; a sort by a hidden column keeps the row order |
|
|
254
290
|
| opening rows | `getRowHref` / `onRowClick`, `isRowClickable` | `data-clickable` (pointer, pressed wash) on rows that open; link rows: `data-link`, an `<a data-row-link>` in every content cell; in-place rows: `tabindex="0"`. Focus (the link, or the row) rings the whole row with the hover wash |
|
|
255
291
|
| grouped | `getRowGroup` | one `<tbody>` per group run on screen, opened by a `<th scope="rowgroup">` row one ladder step off the table; `data-sticky` on it with `stickyGroupHeaders` |
|
|
256
292
|
| collapsed group | `collapsedGroups` / `defaultCollapsedGroups` | `data-collapsed` on the group header row, its toggle `aria-expanded="false"` with the chevron at rest; the group's `<tbody>` holds the header alone, its rows only lay out the column widths in the hidden measuring body. Its rows fold away and back like sub-rows (`data-fold`, `base`), whether a toggle or the owner changed the keys. «Select all» still takes the rows of collapsed groups; paging still counts them |
|
|
257
|
-
| reorderable | `onReorder` (not with `getRowChildren` / `renderExpanded`) | `data-reorderable` on the root; a leading
|
|
293
|
+
| reorderable | `onReorder` (not with `getRowChildren` / `renderExpanded`) | `data-reorderable` and `data-reorder-handle` (`end` · `start` · `row`) on the root; a grip ending each row in the trailing cell, a leading grip column, or the row itself (drag, a touch hold, Alt + ↑ / ↓ on the grip or the row); each run of rows (the page, or each group) is a `Dnd.Sortable` `<tbody>`, so with `getRowGroup` rows move inside their group; a row put last on a page stands in front of the first row of the next page; a lifted row leaves a dashed gap row across every column, its neighbours glide (`base`), the copy flies in a one-row table at the row's column widths and sets down on its new place; a keyboard move glides the same way |
|
|
258
294
|
| saving a move | `onReorder` returned a pending promise | the row stays in its new place, `aria-busy`, its cells at 60% and its grip busy (Dnd: a spinner in the disabled handle); a rejection glides it back |
|
|
259
|
-
| reorder off | a sort by a column | the handles are disabled with a Tooltip (`labels.reorderSorted`); no drag, no Alt + arrows |
|
|
295
|
+
| reorder off | a sort by a column | the handles are disabled with a Tooltip (`labels.reorderSorted`); no drag, no Alt + arrows (rows that are their own grip just hold still) |
|
|
296
|
+
| reorderable columns | `columnOrder` / `defaultColumnOrder` / `onColumnOrderChange` | the head row is a `Dnd.Sortable as="tr"`: each movable head cell is a `Dnd.SortableItem` (`dragFromControls`, so a press on the sort button picks it up too); a plain one is a tab stop (`tabindex="0"`, `aria-keyshortcuts`, the inset ring), a sortable one passes the keys from its sort button; the chooser's items are a `Dnd.Sortable` list with a grip (or a lock) at their end. A new order rebuilds the body once and the cells of the column that moved fade in (`enterMotion` `.enterFade`); a move from outside the head row (the chooser, the owner) glides the head cells (`base`), each column keeps its width by id |
|
|
297
|
+
| carrying a column | a header press that travelled 4 px (a finger: held 280 ms) | Dnd's gesture: a copy of the header alone flies on the lift shadow; the header stays in its column as Dnd's gap (the dashed, tinted slot of every sortable list, `data-lifted`) and glides with the other headers to where they will stand (`base`; at once under reduced motion), and the viewport scrolls near its edges. The body stays still the whole gesture. The drop lands the copy on the header's new place and rebuilds the body once (the moved column fades in); Escape glides the headers back, nothing else moved; the click that ends a drag never sorts |
|
|
260
298
|
| heatmap cell | column `scale` and a numeric value (`sortAccessor`, else `accessor`) | `data-scale="1"…"5"` on the cell: its base is `--prime-color-chart-scale-<n>`, text `--prime-color-chart-scale-fg` on 4–5; the range spans all rows (or the fixed `min` / `max`), so paging and sorting never change a shade; the value stays in the cell, non-numbers stay plain |
|
|
261
299
|
| filling the parent | `scrollHeight="fill"` | `data-scroll-height="fill"` on the root; the viewport takes the free height |
|
|
262
300
|
| state swap | the body moves between loading, rows, empty and error | the body fades in over `base` (opacity only, the same swap motion as [Crossfade](../crossfade/COMPONENT.md)); the head stays still; nothing moves on the first render |
|
|
263
301
|
|
|
264
|
-
Root attributes: `data-size`, `data-row-dividers`, `data-column-dividers`, `data-sticky-header`, `data-sticky-first-column`, `data-table-width` (`fill` · `auto` · `grow`), `data-highlight-row`, `data-highlight-column`, `data-striped`, `data-loading`, `data-reorderable`, `data-selectable`, `data-expandable`, `data-dragging` (while drag-selecting), `data-overflow-start` · `data-overflow-end` (edges that hide columns), `data-scroll-height` (`fill`). Sorting and paging swap rows instantly; everything is still under `prefers-reduced-motion`.
|
|
302
|
+
Root attributes: `data-size`, `data-row-dividers`, `data-column-dividers`, `data-sticky-header`, `data-sticky-first-column`, `data-sticky-last-column`, `data-table-width` (`fill` · `auto` · `grow`), `data-highlight-row`, `data-highlight-column`, `data-striped`, `data-loading`, `data-reorderable`, `data-reorder-handle`, `data-selectable`, `data-expandable`, `data-dragging` (while drag-selecting), `data-overflow-start` · `data-overflow-end` (edges that hide columns), `data-scroll-height` (`fill`). Sorting and paging swap rows instantly; everything is still under `prefers-reduced-motion`.
|
|
265
303
|
|
|
266
304
|
## Layout & spacing
|
|
267
305
|
- The root is a layer of the surface ladder (`data-depth`, one above its host): it fills its container on `--prime-color-layer-current`, radius 12, and clips full-bleed head and rows; zebra rows and the sticky column are one ladder step off it, the head two. On a card or in a modal it is the next layer by itself — never wrap it in a Card.
|
|
268
|
-
-
|
|
306
|
+
- A filter stands next to what it filters. `toolbar` is the table's own tools row whenever the page holds more than this table (KPI cards, a chart, another block): its search and filter (`SmartFilter.Toolbar`, chips in `toolbarChips`), `DataTableColumnsMenu`, a table / cards view, bulk actions on the selected rows. When the table is the whole page, «next to the table» is the page's bar: its search and filter stay in `Page.Tools` and `Page.Chips`. Either way the bar keeps what acts on the whole page — the title with its line of data, a period that drives several blocks, sections, the primary action (`Page.Actions`). One control never gets a row of its own.
|
|
307
|
+
- The tools row is the one tool row of the kit (`Page.Tools` lays out the same way): controls in the order written, a search or a line of text (`Typography`) takes the free room, switchers, pickers and buttons keep their content width at the end edge. Under 36rem of table width the search takes a line of its own and a `SegmentedControl` (`fullWidth` unless set) fills the line it shares with the buttons; a search never parts from its filter button (`SmartFilter.Toolbar` keeps both). Wrap the table in `SmartFilter.Root` so the toolbar and the chips share one state.
|
|
308
|
+
- Toolbar padding `--prime-space-3` × cell padding, items `gap: --prime-space-2`, chips 12 under the row; below 30rem of table width the footer stacks.
|
|
269
309
|
- The footer has a hairline on top: range on the left, Pagination on the right. The range shows only with more than one page or with infinite scroll.
|
|
270
|
-
- Columns scroll sideways inside the table, never the page; pin the identifying column with `stickyFirstColumn
|
|
271
|
-
- While columns are hidden past an edge, that edge shows a `--prime-space-4` shadow (`--prime-color-bg-edge-shadow`) over the content; it takes no space and follows RTL. With `stickyFirstColumn` the start shadow falls from the pinned column's end edge.
|
|
272
|
-
-
|
|
273
|
-
-
|
|
310
|
+
- Columns scroll sideways inside the table, never the page; pin the identifying column with `stickyFirstColumn` and the row actions column with `stickyLastColumn` (it pins the last visible column, so hiding it pins the one before). A 320 px column holds the table without breaking it.
|
|
311
|
+
- While columns are hidden past an edge, that edge shows a `--prime-space-4` shadow (`--prime-color-bg-edge-shadow`) over the content; it takes no space and follows RTL. With `stickyFirstColumn` the start shadow falls from the pinned column's end edge; with `stickyLastColumn` the end shadow falls from the pinned column's start edge. With `stickyHeader` the pinned head cells hold both corners.
|
|
312
|
+
- Layers, bottom to top: every cell that scrolls · the pinned columns (lead cells, the first and the last column, the end grip cell) · sticky group headers · the sticky head · the corners (head cells pinned to a column edge). Each cell keeps what it holds inside its own layer, so a control in a scrolled cell — a Switch, an icon Button, a focus ring — always passes under the pinned columns and the head, whatever its own stacking. A head label truncates inside its cell and never runs under the next one.
|
|
313
|
+
- Fewer columns, less scrolling: offer the column chooser (the key column and the row-actions column `hideable: false`). The kit stores nothing: keep `onHiddenColumnsChange`'s list where the app keeps settings and pass it back as `hiddenColumns`. Never hide columns silently by width.
|
|
314
|
+
- The column chooser has one place per table. Over the row actions (`columnsMenu`): an icon-only ghost neutral Button one tier below the table (the `view.columns` icon; `labels.columns` is its name and its Tooltip) in the head cell of the row-actions column (the last visible column, `hideHeader`), lined up with the ⋯ buttons under it, sticking with that column under `stickyLastColumn`. Without row actions: `DataTableColumnsMenu` in the page's tools (`Page.Tools`, or the host's own toolbar) — a soft neutral Button with the icon, `labels.columns` and a Badge with the count of shown columns, at the host tier — bound to the same `hiddenColumns` (and `columnOrder`) state the table reads. Both open the same Dropdown: a `labels.showColumns` group heading over one check item per column (the check at the end).
|
|
315
|
+
- Reorderable rows: the grip is the fixed `xs` `Dnd.Handle`. At the end it takes a trailing cell (the grip plus the end padding), after the row actions; at the start a leading cell before the checkboxes (the first column's padding is the gap to it). Rows that are their own grip (`row`) add no cell.
|
|
316
|
+
- Reorderable columns move only between the columns that hold their place: the selection, toggle, grip and trailing cells never move, a pinned first or last column stays at its edge, a `hideHeader` (row actions) or `reorderable: false` column keeps its slot. A hidden column keeps its slot in `columnOrder` too, so showing it again puts it back where it was. Keep `columnOrder` with `hiddenColumns` where the app keeps settings. The chooser's Dropdown opens below (lined up with the trigger's end edge over the row actions), lists every column in table order and ends with `labels.showAllColumns` (and `labels.resetColumnOrder` with `columnOrder`); a `hideable: false` column stays checked and disabled, and the last visible column cannot be hidden. With `columnOrder` the items are a `Dnd.Sortable` list, a grip (or a lock) ending each item after its check mark.
|
|
274
317
|
- Row height per `size` is public: `--prime-table-row-height-xs` · `-s` · `-m` · `-l` · `-xl` (36 · 36 · 44 · 52 · 52). A placeholder outside the table that stands in its geometry (a heatmap, a matrix skeleton) uses the same token.
|
|
275
318
|
- A row that opens keeps controls out of its key cell (that cell is the link); controls in other cells stand above the row's link. Mark a custom widget with `data-row-click-ignore`.
|
|
276
319
|
- Group headers: the name at the start, totals at the end (`renderGroupHeader` returns both, the kit lays them out across the visible width), head-tier text in `text-secondary`, row height = the head height. With collapsible groups the chevron toggle (the expand toggle's ghost Button) leads the header at the cell padding.
|
|
277
320
|
- The empty and error content stands in a sticky box of the visible width: a wide table centres it in the viewport, and it stays there while the table scrolls sideways.
|
|
278
321
|
- A trend per row: a compact [Sparkline](../sparkline/COMPONENT.md) (`layout="compact"`) in a cell fits the row height; its pointer and keys never open the row.
|
|
279
|
-
- Long data needs no slicing: past 100 rows a body in a bounded viewport (`scrollHeight`, `"fill"`, `paging="infinite"`) renders only the rows around the view; spacer rows keep the scrollbar exact, the focused row stays rendered, rows carry `aria-rowindex` and the table `aria-rowcount`. Grouped (`getRowGroup`), reorderable (`onReorder`) and `renderExpanded` bodies, and a table the page scrolls, render every row. The browser's find-in-page sees only rendered rows: give a long table a search
|
|
322
|
+
- Long data needs no slicing: past 100 rows a body in a bounded viewport (`scrollHeight`, `"fill"`, `paging="infinite"`) renders only the rows around the view; spacer rows keep the scrollbar exact, the focused row stays rendered, rows carry `aria-rowindex` and the table `aria-rowcount`. Grouped (`getRowGroup`), reorderable (`onReorder`) and `renderExpanded` bodies, and a table the page scrolls, render every row. The browser's find-in-page sees only rendered rows: give a long table a search (the page's `SmartFilter`).
|
|
280
323
|
- `scrollHeight="fill"` needs a parent with a height: a flex or grid column with `min-height: 0`, `Page.Root fill` in an `AppShell.Root fillViewport`, or a sized pane.
|
|
281
324
|
- The sticky head stops sticking on screens lower than 480px (landscape phones), so it never takes a large share of the height.
|
|
282
|
-
- Cell content: text, two-line text (title + `caption`), an Avatar with text, a Badge, or a control one tier down (`s` in an `m` table).
|
|
325
|
+
- Cell content: text, two-line text (title + `caption`), an Avatar with text, a Badge, or a control one tier down (`s` in an `m` table). The column chooser in the head uses `s` in an `m` table; toolbar controls take the table's tier (leave them without `size`).
|
|
283
326
|
- Column widths: `width` / `minWidth` / `maxWidth` strings; never size cells with custom CSS.
|
|
284
327
|
- Sub-rows indent by `--dt-indent` per level (avatar of the tier + gap); override it on the root for other leading content.
|
|
285
328
|
|
|
@@ -290,24 +333,26 @@ Root attributes: `data-size`, `data-row-dividers`, `data-column-dividers`, `data
|
|
|
290
333
|
|
|
291
334
|
| Key | Action |
|
|
292
335
|
|---|---|
|
|
293
|
-
| `Tab` | Moves through the toolbar (`
|
|
336
|
+
| `Tab` | Moves through the toolbar, sort buttons, plain headers that move their column (`columnOrder`), the column chooser (`columnsMenu`, `DataTableColumnsMenu`), row handles, checkboxes, expand toggles, row links, rows that open in place or move themselves (`reorderHandle="row"`) and Pagination. |
|
|
294
337
|
| `Enter` · `Space` | Sorts by the column, toggles the row or the group, or opens the focused row (`onRowClick`); Enter on a row link follows it. |
|
|
295
338
|
| `Space` | Toggles the focused row checkbox. |
|
|
296
339
|
| `Shift + Space` | Selects the range from the last toggled row. |
|
|
297
|
-
| `Alt + ↑` · `Alt + ↓` | On a row handle (`onReorder`), moves the row one place up or down. |
|
|
298
|
-
| `
|
|
340
|
+
| `Alt + ↑` · `Alt + ↓` | On a row handle, or on the row itself with `reorderHandle="row"` (`onReorder`), moves the row one place up or down; on an item of the column chooser (`columnOrder`), moves that column one place. |
|
|
341
|
+
| `Alt + ←` · `Alt + →` | On a header (its sort button, or the plain header) with `columnOrder`, moves the column one place back or on; focus stays on it. A column that holds its place does not move and no column steps over it. The direction follows the writing direction (`dir="rtl"`: ← goes on). |
|
|
342
|
+
| `Escape` | Cancels a row drag or a header drag; the row or the headers glide back, the body never moved. |
|
|
299
343
|
|
|
300
344
|
### ARIA
|
|
301
345
|
<!-- Generated from api.ts by `bun run docs:build`. Edit api.ts, not this section. -->
|
|
302
346
|
|
|
303
|
-
- Native `<table>` semantics; head cells are `scope="col"` (the
|
|
347
|
+
- Native `<table>` semantics; head cells are `scope="col"` (the head cells of the grip columns are `<td>`); sortable heads hold a `<button>` and expose `aria-sort`; the whole head cell shows the inset focus ring.
|
|
348
|
+
- With `columnOrder` the head row is a `Dnd.Sortable`: a header that moves its column carries `aria-keyshortcuts` on its focus target (the sort button; a plain header is a tab stop of its own with Dnd's role description); a pick-up, a drop and a keyboard move are announced by Dnd («Сумма: позиция 3 из 7»). In the column chooser each item keeps `menuitemcheckbox` with `aria-keyshortcuts`, its grip (`labels.reorderColumn`) is out of the Tab order, a column that holds its place shows a lock named «Закреплено».
|
|
304
349
|
- A link row has one link for assistive tech: the `<a>` in the key cell, named by its text. Its copies over the other cells are `aria-hidden` and `tabindex="-1"`, so the pointer can use the whole row. An in-place row is focusable itself (`tabindex="0"`) and reads as its cells. Either way the focused row shows a ring around all its cells.
|
|
305
350
|
- A row never opens from a control inside it (links, buttons, fields, `label`, `summary`, ARIA widgets, `data-row-click-ignore`), from a text selection, or from a React event that bubbled out of a portal (a ⋯ menu item).
|
|
306
351
|
- A group header is a `<th scope="rowgroup">` across every column, first in its own `<tbody>`.
|
|
307
|
-
-
|
|
352
|
+
- The column chooser is a menu button: the icon one (`columnsMenu`) named by `labels.columns` (its tooltip says the same), `DataTableColumnsMenu` by its text and count. Its items are a group named `labels.showColumns` of `menuitemcheckbox` with `aria-checked`; the key column is `aria-disabled`. In the row-actions head cell the column keeps its own name (`aria-labelledby`).
|
|
308
353
|
- Row checkboxes are named by `labels.selectRow` with `{label}` from `getRowLabel` (pass it so the names are unique); the head checkbox by `labels.selectAll`, `indeterminate` on a partial selection.
|
|
309
354
|
- After a selection change a polite live region announces `labels.selectedCount`; selected rows carry `aria-selected`.
|
|
310
|
-
- A row handle is a button named by `labels.reorderRow` with `aria-keyshortcuts`; a pick-up, a drop and a keyboard move are announced in a polite live region («Договор: позиция 2 из 6»). While its move is saved the row is `aria-busy`; while the table is sorted the handles are disabled and a tooltip gives `labels.reorderSorted
|
|
355
|
+
- A row handle is a button named by `labels.reorderRow` with `aria-keyshortcuts`; with `reorderHandle="row"` the row itself is the tab stop with `aria-keyshortcuts` and a role description, and reads as its cells. A pick-up, a drop and a keyboard move are announced in a polite live region («Договор: позиция 2 из 6»). While its move is saved the row is `aria-busy`; while the table is sorted the handles are disabled and a tooltip gives `labels.reorderSorted` (rows that are their own grip just stop moving).
|
|
311
356
|
- The expand toggle is a button with `aria-expanded`, `aria-controls` (detail row or sub-rows) and `labels.expand` / `labels.collapse`.
|
|
312
357
|
- A group toggle (collapsible groups) is a button in the group header with `aria-expanded`, `aria-controls` (the group's rows, while open; not on reorderable rows, which carry no id) and `labels.expandGroup` / `labels.collapseGroup` with `{group}`.
|
|
313
358
|
- A column `description` describes its header cell (`aria-describedby`); its tooltip opens from the sort button, or from the info glyph (a tab stop named `labels.columnInfo`) on a plain header.
|
|
@@ -328,8 +373,11 @@ Root attributes: `data-size`, `data-row-dividers`, `data-column-dividers`, `data
|
|
|
328
373
|
| `selectedCount` | `"Выбрано: {count}"` | Polite announcement after the selection changes. |
|
|
329
374
|
| `expand` | `"Развернуть строку {label}"` | Name of the toggle of a collapsed row. |
|
|
330
375
|
| `collapse` | `"Свернуть строку {label}"` | Name of the toggle of an expanded row. |
|
|
331
|
-
| `columns` | `"Колонки"` |
|
|
332
|
-
| `
|
|
376
|
+
| `columns` | `"Колонки"` | Name and tooltip of the icon trigger (`columnsMenu`), the text of `DataTableColumnsMenu`; `{shown}` and `{total}` are column counts. |
|
|
377
|
+
| `showColumns` | `"Показывать"` | The heading of the chooser's list of columns. |
|
|
378
|
+
| `showAllColumns` | `"Показать все"` | The column chooser item that shows every column again. |
|
|
379
|
+
| `resetColumnOrder` | `"Исходный порядок"` | The column chooser item that puts the order of `columns` back (`columnOrder`). |
|
|
380
|
+
| `reorderColumn` | `"Переместить колонку {label}"` | Name of a column's grip in the column chooser (`columnOrder`); `{label}` is its header. |
|
|
333
381
|
| `reorderRow` | `"Переместить строку {label}"` | `aria-label` of a row's drag handle (`onReorder`); `{label}` is `getRowLabel(row)`. |
|
|
334
382
|
| `reorderSorted` | `"Порядок задан сортировкой. Сбросьте её, чтобы перемещать строки"` | Tooltip of the disabled handles while the table is sorted by a column. |
|
|
335
383
|
| `expandGroup` | `"Развернуть группу {group}"` | Name of the toggle of a collapsed group; `{group}` is the group key. |
|
|
@@ -346,22 +394,24 @@ Root attributes: `data-size`, `data-row-dividers`, `data-column-dividers`, `data
|
|
|
346
394
|
| [trend.tsx](examples/trend.tsx) | Clients with revenue by month as a compact Sparkline in a cell of each row, next to the half-year total — `cell`, `width`. |
|
|
347
395
|
| [content-width.tsx](examples/content-width.tsx) | A short lookup table sized by its content with a centered column, and a `grow` column that takes the free width and wraps — `fullWidth`, `align`, `grow`. |
|
|
348
396
|
| [appearance.tsx](examples/appearance.tsx) | Row styling: zebra rows without lines, a column wash under the pointer, a headless key/value list — `striped`, `rowDividers`, `highlightColumnOnHover`, `columnDividers`, `showHeader`. |
|
|
349
|
-
| [toolbar.tsx](examples/toolbar.tsx) | A campaign
|
|
397
|
+
| [toolbar.tsx](examples/toolbar.tsx) | A campaign table with its own tools row: the search takes the free room, the status switch keeps its width at the end, and on a narrow table they wrap; the empty text when nothing matches — `toolbar`, `empty`. |
|
|
350
398
|
| [selection.tsx](examples/selection.tsx) | Team members with checkboxes: Shift+click range, press-and-drag, «select all» and bulk actions in the toolbar — `selectable`, `selected`, `onSelectedChange`, `getRowLabel`. |
|
|
351
399
|
| [nested-rows.tsx](examples/nested-rows.tsx) | Partners with their expense lines: sub-rows indented under the parent's name, a chevron toggle, together with selection and sorting — `getRowChildren`, `expanded`, `onExpandedChange`. |
|
|
352
400
|
| [detail-panel.tsx](examples/detail-panel.tsx) | Order details in a full-width row under an expanded order, aligned with the first content column; a cancelled order has nothing to show and gets no toggle — `renderExpanded`, `defaultExpanded`, `isRowExpandable`. |
|
|
353
401
|
| [sticky.tsx](examples/sticky.tsx) | Monthly sales by region in a 280 px window: the head and the region column stay while scrolling both ways — `stickyHeader`, `stickyFirstColumn`, `scrollHeight`. |
|
|
402
|
+
| [actions-column.tsx](examples/actions-column.tsx) | Orders wider than the table: the order number stays at the start, the ⋯ row actions at the end with the column chooser in their header cell, and the columns between scroll sideways — `stickyFirstColumn`, `stickyLastColumn`, `columnsMenu`. |
|
|
354
403
|
| [row-link.tsx](examples/row-link.tsx) | Invoices whose rows are links: ⌘-click or a middle click opens a new tab, a plain click routes inside the app, the totals row and the ⋯ menu never open a row — `getRowHref`, `onRowClick`, `isRowClickable`. |
|
|
355
404
|
| [row-open.tsx](examples/row-open.tsx) | Deals that open in a side panel: a click, or Enter and Space on the focused row; the panel keeps the last deal while it slides away — `onRowClick`. |
|
|
356
|
-
| [reorder.tsx](examples/reorder.tsx) | Pipeline stages put in order by the
|
|
405
|
+
| [reorder.tsx](examples/reorder.tsx) | Pipeline stages put in order by a grip at the end of the row, at its start or by the whole row, or with Alt + ↑ / ↓; each move is saved with a spinner in its grip, and sorting by a column turns reordering off — `onReorder`, `reorderHandle`, `getRowLabel`. |
|
|
357
406
|
| [groups.tsx](examples/groups.tsx) | Payments grouped by month with the month's total in its header row; headers stay on top while their rows scroll, a past month folds away — `getRowGroup`, `renderGroupHeader`, `stickyGroupHeaders`, `defaultCollapsedGroups`. |
|
|
358
|
-
| [columns-visibility.tsx](examples/columns-visibility.tsx) | Orders
|
|
407
|
+
| [columns-visibility.tsx](examples/columns-visibility.tsx) | Orders without a row-actions column: the column chooser stands in the tools above the table with the count of shown columns; the choice outlives a reload in local storage, the order number always stays — `DataTableColumnsMenu`, `hiddenColumns`, `onHiddenColumnsChange`, `hideable`. |
|
|
408
|
+
| [column-order.tsx](examples/column-order.tsx) | Orders whose columns a manager puts in place by dragging a header — it moves alone and the gap opens among the headers where it lands — or with Alt + ← / →, and shows, hides and reorders in the chooser over the row menu; the order number stays first and the row menu last, and the choice outlives a reload — `columnOrder`, `onColumnOrderChange`, `reorderable`, `columnsMenu`, `hiddenColumns`. |
|
|
359
409
|
| [infinite-scroll.tsx](examples/infinite-scroll.tsx) | An audit log that reveals loaded rows in batches and then asks the server for more — `paging`, `infiniteBatchSize`, `hasMore`, `loadingMore`, `onLoadMore`. |
|
|
360
|
-
| [server.tsx](examples/server.tsx) | A CRM deal list the server sorts, pages and searches; a new search returns to page 1 — `source`, `rowCount`, `sort`, `page`, `loading`. |
|
|
410
|
+
| [server.tsx](examples/server.tsx) | A CRM deal list the server sorts, pages and searches, with its tools in its own row — search, filter and column chooser, the active filters under them; a new search returns to page 1 — `source`, `rowCount`, `sort`, `page`, `loading`, `toolbar`, `toolbarChips`. |
|
|
361
411
|
| [fill-height.tsx](examples/fill-height.tsx) | An audit log that fills the height of its panel and loads older entries while scrolling; the status shows while the request is pending — `scrollHeight`, `paging`, `onLoadMore`. |
|
|
362
412
|
| [states.tsx](examples/states.tsx) | Loading skeleton, an empty period and a load error with a retry: the head stays, only the body changes — `loading`, `loadingRows`, `empty`, `loadError`. |
|
|
363
413
|
| [controlled.tsx](examples/controlled.tsx) | Sort, page and the column choice owned by the parent (a URL or a store): a header click goes asc → desc → none, a new sort returns to page 1 — `sort`, `onSortChange`, `page`, `onPageChange`, `hiddenColumns`, `onHiddenColumnsChange`. |
|
|
364
|
-
| [narrow.tsx](examples/narrow.tsx) | A 320 px support queue: columns scroll inside the table with the first one pinned, the
|
|
414
|
+
| [narrow.tsx](examples/narrow.tsx) | A 320 px support queue: columns scroll inside the table with the first one pinned, the column chooser stays in reach above it, the footer reflows and the pager turns compact — `stickyFirstColumn`, `DataTableColumnsMenu`, `size`. |
|
|
365
415
|
| [screen.tsx](examples/screen.tsx) | A list page: the title, a line of figures, search, filters and the one primary action in its top bar, a DataTable of invoices with statuses, row actions, pages and a filtered empty state — `empty`, `pageSize`, `stickyFirstColumn`. |
|
|
366
416
|
|
|
367
417
|
## Mistakes
|
|
@@ -373,13 +423,24 @@ Root attributes: `data-size`, `data-row-dividers`, `data-column-dividers`, `data
|
|
|
373
423
|
- Wrapping the table in a Card for a border → the table is already a bounded block.
|
|
374
424
|
- A custom checkbox column → use `selectable` (range, drag and announcements built in).
|
|
375
425
|
- Up / down arrow buttons in a cell to order rows → use `onReorder` (drag, touch hold, Alt + arrows, announcements, server save built in).
|
|
426
|
+
- A grip column added by hand, or the grip moved with CSS → `reorderHandle` (`end` by default, `start`, or `row`).
|
|
427
|
+
- `reorderHandle="row"` on link rows (`getRowHref`) or rows with text to copy → the link takes every press and the text cannot be selected; keep a grip (`end`).
|
|
428
|
+
- Up / down arrows or a «Порядок колонок» dialog to reorder columns, or a hand-made header drag → `columnOrder` (header drag, Alt + ← / →, chooser grips, announcements built in); keep it with `hiddenColumns` in the user's settings.
|
|
429
|
+
- Moving body cells while a header is carried, or a drag that carries the whole column → the head row alone moves; the body takes the order once, on the drop.
|
|
430
|
+
- Removing a column from `columns` to «delete» it for a user → hide it (`hiddenColumns`); its data and its place in `columnOrder` stay.
|
|
376
431
|
- Applying the new order before the server answers and undoing it by hand → return the request's promise from `onReorder` and apply after it resolves: the table keeps the row in place meanwhile and moves it back on a rejection.
|
|
377
432
|
- A long table in a `scrollHeight` window without `stickyHeader` → the head scrolls away.
|
|
378
433
|
- `paging="none"` for hundreds of rows → use `pages` or `infinite`.
|
|
379
|
-
- Dropping columns below a breakpoint → people lose data without knowing it; offer
|
|
380
|
-
- A hand-built column chooser from Dropdown items → `
|
|
434
|
+
- Dropping columns below a breakpoint → people lose data without knowing it; offer the column chooser.
|
|
435
|
+
- A hand-built column chooser from Dropdown items → `columnsMenu` over the row actions, else `DataTableColumnsMenu` (key column, last visible column, «Показать все», reorder built in).
|
|
436
|
+
- `columnsMenu` on a table without a row-actions column → nothing renders and the table warns; put `DataTableColumnsMenu` beside the table's other tools (its `toolbar`, or `Page.Tools` on a page that is the table), bound to the same `hiddenColumns`.
|
|
437
|
+
- A toolbar with one button (the column chooser, «Экспорт», «Создать») → a whole row above the table for one control; the chooser stands over the row actions or beside the table's search, the page's actions go to `Page.Actions`.
|
|
438
|
+
- The table's search, filter, chips or column chooser in the page's bar above KPI cards or a chart they do not filter → people read them as filters of the whole page; put them in the table's `toolbar` / `toolbarChips` and keep the bar for the title, the period that drives every block and the primary action.
|
|
439
|
+
- A period that drives the cards and the table, the page's sections, figures or actions in `toolbar` → they act on the whole page: `Page.Tools`, `Page.Actions`, `Page.Description`.
|
|
440
|
+
- A hand-made flex row or a `SmartFilter.Root` with its own column inside `toolbar` → pass the controls to `toolbar` as they are (it lays them out), the chips to `toolbarChips`, and wrap the DataTable in `SmartFilter.Root`.
|
|
381
441
|
- Letting the key column be hidden → set `hideable: false` on it, so every row keeps its name.
|
|
382
442
|
- Wrapping the table in an `overflow-x` box of your own → it already scrolls inside and shows the edge shadows.
|
|
443
|
+
- A row actions column that scrolls out of view in a wide table, or a hand-made `position: sticky` on it → make it the last column and set `stickyLastColumn`.
|
|
383
444
|
- `onRowClick` with `navigate()` for a record page → use `getRowHref` (⌘-click, new tab, status-bar URL) and route the plain click in `onRowClick` with `event.preventDefault()`.
|
|
384
445
|
- Checking `event.target` in `onRowClick` to skip a button or a menu in the row → the table already ignores controls and portals; mark a custom widget with `data-row-click-ignore`.
|
|
385
446
|
- A totals row that opens like a record → `isRowClickable`.
|
|
@@ -393,5 +454,5 @@ Root attributes: `data-size`, `data-row-dividers`, `data-column-dividers`, `data
|
|
|
393
454
|
- A new search that keeps the current page → set `page` to 1 together with the search.
|
|
394
455
|
|
|
395
456
|
## Related
|
|
396
|
-
- **Built from:** [Checkbox](../checkbox/COMPONENT.md), [Button](../button/COMPONENT.md), [Dropdown](../dropdown/COMPONENT.md) (
|
|
457
|
+
- **Built from:** [Checkbox](../checkbox/COMPONENT.md), [Button](../button/COMPONENT.md), [Dropdown](../dropdown/COMPONENT.md) (the column chooser), [Pagination](../pagination/COMPONENT.md), [ScrollContainer](../scroll-container/COMPONENT.md), [EmptyPage](../empty-page/COMPONENT.md), [VisuallyHidden](../visually-hidden/COMPONENT.md) (loading status, selection announcement), [Skeleton](../skeleton/COMPONENT.md) (loading rows, in the table tier), [Dnd](../dnd/COMPONENT.md) (`onReorder`: `Dnd.Sortable as="tbody"`, `Dnd.Handle`; `columnOrder`: the head row as a `Dnd.Sortable as="tr"`, the chooser's `Dnd.Sortable` list, `Dnd.Handle`, the lock), [Badge](../badge/COMPONENT.md) (the count on `DataTableColumnsMenu`), [Tooltip](../tooltip/COMPONENT.md) (handle hint, a column `description`, the column chooser), Icon (sort arrows, the info glyph of a column `description`, the expand chevron, the column chooser trigger); `useVirtualRows` (the window of a long body); `useFlipList` (the head cells glide to an order set from outside the head row); `enterMotion` (the moved column fades in); `ToolRow` (the `toolbar` row and the `toolbarChips` line) with [SmartFilter](../smart-filter/COMPONENT.md), [Input](../input/COMPONENT.md) and [Typography](../typography/COMPONENT.md) (what grows in the tool row), [SegmentedControl](../segmented-control/COMPONENT.md), [Datepicker](../datepicker/COMPONENT.md) and [Select](../select/COMPONENT.md) (what fills a short line; the first two get `fullWidth`)
|
|
397
458
|
- **See also:** [Sparkline](../sparkline/COMPONENT.md) (`layout="compact"` in a cell), [SmartFilter](../smart-filter/COMPONENT.md), [Page](../../layout/page/COMPONENT.md) (`Page.Tools`, `Page.Chips`), [Gantt](../gantt/COMPONENT.md), [Kanban](../kanban/COMPONENT.md), [Badge](../badge/COMPONENT.md), [Avatar](../avatar/COMPONENT.md), [Card](../card/COMPONENT.md)
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/** Orders wider than the table: the order number stays at the start, the ⋯ row actions at the end with the column chooser in their header cell, and the columns between scroll sideways — `stickyFirstColumn`, `stickyLastColumn`, `columnsMenu`. */
|
|
2
|
+
import { Badge, Button, DataTable, type DataTableColumn, Dropdown, Icon } from "prime-ui-kit";
|
|
3
|
+
|
|
4
|
+
type Order = {
|
|
5
|
+
id: string;
|
|
6
|
+
client: string;
|
|
7
|
+
manager: string;
|
|
8
|
+
city: string;
|
|
9
|
+
address: string;
|
|
10
|
+
status: "new" | "paid" | "shipped" | "cancelled";
|
|
11
|
+
date: string;
|
|
12
|
+
items: number;
|
|
13
|
+
amount: number;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const ORDERS: Order[] = [
|
|
17
|
+
{
|
|
18
|
+
id: "З-2041",
|
|
19
|
+
client: "ООО «Северный ветер»",
|
|
20
|
+
manager: "Анна Смирнова",
|
|
21
|
+
city: "Санкт-Петербург",
|
|
22
|
+
address: "Лиговский пр., 50, склад 3",
|
|
23
|
+
status: "paid",
|
|
24
|
+
date: "02.10.2026",
|
|
25
|
+
items: 14,
|
|
26
|
+
amount: 184_500,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: "З-2042",
|
|
30
|
+
client: "ИП Козлов",
|
|
31
|
+
manager: "Игорь Петров",
|
|
32
|
+
city: "Казань",
|
|
33
|
+
address: "ул. Петербургская, 12, офис 4",
|
|
34
|
+
status: "new",
|
|
35
|
+
date: "03.10.2026",
|
|
36
|
+
items: 3,
|
|
37
|
+
amount: 27_900,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: "З-2043",
|
|
41
|
+
client: "АО «Технопарк»",
|
|
42
|
+
manager: "Анна Смирнова",
|
|
43
|
+
city: "Новосибирск",
|
|
44
|
+
address: "ул. Станционная, 38, терминал Б",
|
|
45
|
+
status: "shipped",
|
|
46
|
+
date: "05.10.2026",
|
|
47
|
+
items: 42,
|
|
48
|
+
amount: 612_000,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
id: "З-2044",
|
|
52
|
+
client: "ООО «Лента Логистик»",
|
|
53
|
+
manager: "Мария Орлова",
|
|
54
|
+
city: "Екатеринбург",
|
|
55
|
+
address: "ул. Монтажников, 4, ворота 2",
|
|
56
|
+
status: "cancelled",
|
|
57
|
+
date: "06.10.2026",
|
|
58
|
+
items: 8,
|
|
59
|
+
amount: 96_300,
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
id: "З-2045",
|
|
63
|
+
client: "ООО «Гранит»",
|
|
64
|
+
manager: "Игорь Петров",
|
|
65
|
+
city: "Москва",
|
|
66
|
+
address: "Варшавское ш., 125, стр. 1",
|
|
67
|
+
status: "paid",
|
|
68
|
+
date: "08.10.2026",
|
|
69
|
+
items: 21,
|
|
70
|
+
amount: 275_400,
|
|
71
|
+
},
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
const STATUS = {
|
|
75
|
+
new: { label: "Новый", tone: "info" },
|
|
76
|
+
paid: { label: "Оплачен", tone: "success" },
|
|
77
|
+
shipped: { label: "Отгружен", tone: "neutral" },
|
|
78
|
+
cancelled: { label: "Отменён", tone: "danger" },
|
|
79
|
+
} as const;
|
|
80
|
+
|
|
81
|
+
const RUB = new Intl.NumberFormat("ru-RU", {
|
|
82
|
+
style: "currency",
|
|
83
|
+
currency: "RUB",
|
|
84
|
+
maximumFractionDigits: 0,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const COLUMNS: DataTableColumn<Order>[] = [
|
|
88
|
+
{ id: "id", header: "Заказ", accessor: "id", hideable: false },
|
|
89
|
+
{ id: "client", header: "Клиент", accessor: "client", minWidth: "14rem" },
|
|
90
|
+
{ id: "manager", header: "Менеджер", accessor: "manager", minWidth: "10rem" },
|
|
91
|
+
{ id: "city", header: "Город", accessor: "city", minWidth: "10rem" },
|
|
92
|
+
{ id: "address", header: "Адрес доставки", accessor: "address", minWidth: "18rem" },
|
|
93
|
+
{
|
|
94
|
+
id: "status",
|
|
95
|
+
header: "Статус",
|
|
96
|
+
cell: (row) => (
|
|
97
|
+
<Badge.Root tone={STATUS[row.status].tone}>{STATUS[row.status].label}</Badge.Root>
|
|
98
|
+
),
|
|
99
|
+
},
|
|
100
|
+
{ id: "date", header: "Дата", accessor: "date", numeric: true, headerAlign: "end" },
|
|
101
|
+
{ id: "items", header: "Позиций", accessor: "items", numeric: true, headerAlign: "end" },
|
|
102
|
+
{
|
|
103
|
+
id: "amount",
|
|
104
|
+
header: "Сумма",
|
|
105
|
+
accessor: "amount",
|
|
106
|
+
numeric: true,
|
|
107
|
+
headerAlign: "end",
|
|
108
|
+
cell: (row) => RUB.format(row.amount),
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
id: "actions",
|
|
112
|
+
header: "Действия",
|
|
113
|
+
hideHeader: true,
|
|
114
|
+
hideable: false,
|
|
115
|
+
align: "end",
|
|
116
|
+
cell: (row) => (
|
|
117
|
+
<Dropdown.Root>
|
|
118
|
+
<Dropdown.Trigger>
|
|
119
|
+
<Button.Root
|
|
120
|
+
variant="ghost"
|
|
121
|
+
tone="neutral"
|
|
122
|
+
size="s"
|
|
123
|
+
aria-label={`Действия с заказом ${row.id}`}
|
|
124
|
+
>
|
|
125
|
+
<Button.Icon>
|
|
126
|
+
<Icon name="action.more" />
|
|
127
|
+
</Button.Icon>
|
|
128
|
+
</Button.Root>
|
|
129
|
+
</Dropdown.Trigger>
|
|
130
|
+
<Dropdown.Content>
|
|
131
|
+
<Dropdown.Item>Открыть</Dropdown.Item>
|
|
132
|
+
<Dropdown.Item>Скачать счёт</Dropdown.Item>
|
|
133
|
+
<Dropdown.Item>Повторить заказ</Dropdown.Item>
|
|
134
|
+
<Dropdown.Separator />
|
|
135
|
+
<Dropdown.Item tone="danger">Отменить</Dropdown.Item>
|
|
136
|
+
</Dropdown.Content>
|
|
137
|
+
</Dropdown.Root>
|
|
138
|
+
),
|
|
139
|
+
},
|
|
140
|
+
];
|
|
141
|
+
|
|
142
|
+
export default function DataTableActionsColumnExample() {
|
|
143
|
+
return (
|
|
144
|
+
<DataTable
|
|
145
|
+
columns={COLUMNS}
|
|
146
|
+
rows={ORDERS}
|
|
147
|
+
getRowKey={(row) => row.id}
|
|
148
|
+
paging="none"
|
|
149
|
+
stickyFirstColumn
|
|
150
|
+
stickyLastColumn
|
|
151
|
+
columnsMenu
|
|
152
|
+
/>
|
|
153
|
+
);
|
|
154
|
+
}
|