prime-ui-kit 0.17.0 → 0.19.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 +2 -1
- package/dist/chunks/{chunk-PRP4B6OG.js → chunk-IVS3J7AS.js} +1 -1
- package/dist/chunks/{chunk-2ODXLPW3.js → chunk-QFHE5GKW.js} +1 -0
- package/dist/chunks/{chunk-7WWZYGRC.js → chunk-RZNGLELR.js} +4497 -3896
- package/dist/chunks/{chunk-A4WE3UNC.js → chunk-WYCTXD63.js} +18399 -17624
- package/dist/chunks/{chunk-SVFWPLNW.js → chunk-ZTZ2ML2B.js} +14 -3
- package/dist/color-picker.js +3 -3
- package/dist/components/badge/Badge.d.ts +17 -0
- package/dist/components/breadcrumb/Breadcrumb.d.ts +11 -2
- package/dist/components/button/Button.d.ts +1 -1
- package/dist/components/button-group/ButtonGroup.d.ts +1 -1
- package/dist/components/card/Card.d.ts +8 -4
- package/dist/components/chat/Chat.d.ts +3 -3
- package/dist/components/chat/MessageList.d.ts +5 -1
- package/dist/components/chat/groupMessages.d.ts +12 -4
- package/dist/components/chat-list/ChatList.d.ts +18 -9
- package/dist/components/chat-list/formatChatTime.d.ts +3 -3
- package/dist/components/checkbox/Checkbox.d.ts +6 -1
- package/dist/components/color-field/ColorField.d.ts +1 -1
- package/dist/components/color-picker/ColorPicker.d.ts +6 -1
- package/dist/components/color-picker/ColorPresets.d.ts +9 -1
- package/dist/components/crossfade/Crossfade.d.ts +1 -1
- package/dist/components/data-table/ColumnsMenu.d.ts +16 -20
- package/dist/components/data-table/DataTable.d.ts +16 -11
- package/dist/components/data-table/Head.d.ts +10 -1
- package/dist/components/data-table/Row.d.ts +7 -1
- package/dist/components/data-table/StateRows.d.ts +3 -1
- package/dist/components/data-table/types.d.ts +5 -0
- package/dist/components/digit-input/DigitInput.d.ts +1 -1
- package/dist/components/drawer/Drawer.d.ts +3 -2
- package/dist/components/field-list/FieldList.d.ts +24 -12
- package/dist/components/hint/Hint.d.ts +8 -2
- package/dist/components/index.d.ts +7 -4
- package/dist/components/input/Input.d.ts +27 -5
- package/dist/components/input/inputSuggestions.d.ts +39 -0
- package/dist/components/kanban/Kanban.d.ts +8 -9
- package/dist/components/list/List.d.ts +25 -6
- package/dist/components/message/Message.d.ts +15 -3
- package/dist/components/message/MessageSticker.d.ts +27 -0
- package/dist/components/message/formatMessageTime.d.ts +5 -2
- package/dist/components/modal/Modal.d.ts +3 -2
- package/dist/components/native-select/NativeSelect.d.ts +1 -1
- package/dist/components/radio/Radio.d.ts +11 -2
- package/dist/components/rich-text/RichText.d.ts +23 -0
- package/dist/components/scroll-container/ScrollContainer.d.ts +1 -1
- package/dist/components/scroll-container/scrollGlide.d.ts +26 -0
- package/dist/components/scroll-container/useScrollMotion.d.ts +25 -0
- package/dist/components/segmented-control/SegmentedControl.d.ts +1 -1
- package/dist/components/select/selectContext.d.ts +7 -0
- package/dist/components/slider/Slider.d.ts +1 -1
- package/dist/components/switch/Switch.d.ts +6 -1
- package/dist/components/tag-select/TagSelect.d.ts +1 -1
- package/dist/components/textarea/Textarea.d.ts +6 -1
- package/dist/components/timeline/Timeline.d.ts +1 -1
- package/dist/icon-set.js +2 -2
- package/dist/index.css +1 -1
- package/dist/index.js +5 -3
- package/dist/internal/ChoiceField.d.ts +3 -1
- package/dist/internal/FieldFrame.d.ts +8 -2
- package/dist/internal/fieldCell.d.ts +7 -1
- package/dist/internal/formatClock.d.ts +23 -2
- package/dist/internal/leaveGuard.d.ts +27 -0
- package/dist/internal/messageList.d.ts +2 -0
- package/dist/internal/overlay/DialogGuard.d.ts +3 -2
- package/dist/internal/overlay/DialogParts.d.ts +40 -6
- package/dist/internal/swatch.d.ts +5 -0
- package/dist/internal/tokenDefaults.d.ts +1 -0
- package/dist/layout/index.d.ts +1 -1
- package/dist/layout/page/Page.d.ts +48 -15
- package/dist/skill/anti-slop.md +28 -0
- package/dist/skill/api-contract.md +14 -7
- package/dist/skill/cheatsheet.md +28 -9
- package/dist/skill/checklist.md +9 -0
- package/dist/skill/choosing.md +25 -12
- package/dist/skill/components.md +1 -0
- package/dist/skill/composition.md +88 -16
- package/dist/skill/layouts.md +6 -4
- package/dist/skill/reference/components/badge/COMPONENT.md +14 -1
- package/dist/skill/reference/components/badge/examples/examples.module.css +7 -0
- package/dist/skill/reference/components/badge/examples/tag-row.tsx +34 -0
- package/dist/skill/reference/components/breadcrumb/COMPONENT.md +9 -4
- package/dist/skill/reference/components/breadcrumb/examples/router.tsx +17 -0
- package/dist/skill/reference/components/button/COMPONENT.md +1 -1
- package/dist/skill/reference/components/button-group/COMPONENT.md +1 -0
- package/dist/skill/reference/components/card/COMPONENT.md +7 -1
- package/dist/skill/reference/components/card/examples/states.tsx +59 -0
- package/dist/skill/reference/components/chat/COMPONENT.md +4 -1
- package/dist/skill/reference/components/chat/examples/time-zone.tsx +83 -0
- package/dist/skill/reference/components/chat-list/COMPONENT.md +12 -6
- package/dist/skill/reference/components/chat-list/examples/links.tsx +1 -1
- package/dist/skill/reference/components/chat-list/examples/router.tsx +63 -0
- package/dist/skill/reference/components/checkbox/COMPONENT.md +1 -0
- package/dist/skill/reference/components/color-field/COMPONENT.md +2 -1
- package/dist/skill/reference/components/color-picker/COMPONENT.md +14 -5
- package/dist/skill/reference/components/color-picker/examples/presets-custom.tsx +31 -0
- package/dist/skill/reference/components/color-swatches/COMPONENT.md +1 -0
- package/dist/skill/reference/components/confirm-dialog/COMPONENT.md +1 -1
- package/dist/skill/reference/components/crossfade/COMPONENT.md +1 -1
- package/dist/skill/reference/components/data-table/COMPONENT.md +46 -41
- package/dist/skill/reference/components/data-table/examples/actions-column.tsx +154 -0
- package/dist/skill/reference/components/data-table/examples/columns-visibility.tsx +3 -12
- package/dist/skill/reference/components/data-table/examples/controlled.tsx +1 -1
- package/dist/skill/reference/components/data-table/examples/narrow.tsx +4 -11
- package/dist/skill/reference/components/data-table/examples/numeric.tsx +9 -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/toolbar.tsx +26 -32
- package/dist/skill/reference/components/datepicker/COMPONENT.md +3 -1
- package/dist/skill/reference/components/datepicker/examples/deadline.tsx +33 -0
- package/dist/skill/reference/components/digit-input/COMPONENT.md +1 -0
- package/dist/skill/reference/components/dnd/COMPONENT.md +4 -3
- 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.tsx +6 -6
- package/dist/skill/reference/components/drawer/COMPONENT.md +38 -9
- package/dist/skill/reference/components/drawer/examples/client-card.tsx +32 -8
- 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 +40 -24
- 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/reorder.tsx +1 -1
- package/dist/skill/reference/components/field-list/examples/saving.tsx +83 -0
- package/dist/skill/reference/components/field-list/examples/screen.module.css +1 -1
- package/dist/skill/reference/components/field-list/examples/screen.tsx +168 -162
- package/dist/skill/reference/components/field-list/examples/totals.tsx +83 -0
- package/dist/skill/reference/components/file-upload/COMPONENT.md +1 -0
- package/dist/skill/reference/components/hint/COMPONENT.md +16 -2
- package/dist/skill/reference/components/hint/examples/variants.tsx +48 -0
- package/dist/skill/reference/components/input/COMPONENT.md +39 -9
- package/dist/skill/reference/components/input/examples/affixes.tsx +4 -2
- package/dist/skill/reference/components/input/examples/dismiss.tsx +29 -0
- package/dist/skill/reference/components/input/examples/suggestions.tsx +26 -0
- package/dist/skill/reference/components/input/examples/time.tsx +24 -0
- package/dist/skill/reference/components/input/examples/with-select.tsx +44 -0
- package/dist/skill/reference/components/kanban/COMPONENT.md +12 -8
- package/dist/skill/reference/components/kanban/examples/columns.tsx +4 -2
- package/dist/skill/reference/components/kanban/examples/states.tsx +7 -5
- package/dist/skill/reference/components/list/COMPONENT.md +39 -13
- package/dist/skill/reference/components/list/examples/reorder.tsx +42 -7
- package/dist/skill/reference/components/list/examples/row-controls.tsx +80 -0
- package/dist/skill/reference/components/list/examples/with-icon.tsx +23 -2
- package/dist/skill/reference/components/login-form/COMPONENT.md +8 -7
- package/dist/skill/reference/components/login-form/examples/states.tsx +12 -14
- package/dist/skill/reference/components/message/COMPONENT.md +30 -9
- package/dist/skill/reference/components/message/examples/preview.tsx +28 -0
- package/dist/skill/reference/components/message/examples/sticker.tsx +35 -0
- package/dist/skill/reference/components/modal/COMPONENT.md +35 -10
- package/dist/skill/reference/components/modal/examples/long-content.tsx +37 -18
- package/dist/skill/reference/components/native-select/COMPONENT.md +1 -0
- package/dist/skill/reference/components/notification/COMPONENT.md +1 -1
- package/dist/skill/reference/components/radio/COMPONENT.md +2 -0
- package/dist/skill/reference/components/rich-text/COMPONENT.md +93 -0
- package/dist/skill/reference/components/rich-text/examples/overview.tsx +19 -0
- package/dist/skill/reference/components/scroll-container/COMPONENT.md +8 -5
- package/dist/skill/reference/components/segmented-control/COMPONENT.md +4 -2
- package/dist/skill/reference/components/segmented-control/examples/in-form.tsx +1 -1
- package/dist/skill/reference/components/select/COMPONENT.md +7 -3
- package/dist/skill/reference/components/sheet/COMPONENT.md +18 -7
- package/dist/skill/reference/components/slider/COMPONENT.md +1 -0
- package/dist/skill/reference/components/slider/examples/controlled.tsx +1 -1
- package/dist/skill/reference/components/switch/COMPONENT.md +1 -0
- package/dist/skill/reference/components/tag-select/COMPONENT.md +1 -0
- package/dist/skill/reference/components/textarea/COMPONENT.md +1 -0
- package/dist/skill/reference/components/timeline/COMPONENT.md +3 -3
- package/dist/skill/reference/components/timeline/examples/structure.tsx +2 -1
- package/dist/skill/reference/layout/app-shell/COMPONENT.md +2 -2
- package/dist/skill/reference/layout/bottom-nav/COMPONENT.md +1 -0
- package/dist/skill/reference/layout/page/COMPONENT.md +42 -20
- package/dist/skill/reference/layout/page/examples/examples.module.css +7 -0
- package/dist/skill/reference/layout/page/examples/guard.tsx +87 -0
- package/dist/skill/reference/layout/page/examples/loading.tsx +57 -0
- 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/reference/layout/sidebar/COMPONENT.md +1 -0
- package/dist/skill/responsive.md +19 -12
- package/dist/skill/ux.md +5 -3
- package/dist/tokens/semantic.d.ts +3 -1
- package/dist/tokens/themes/dark.d.ts +1 -1
- package/package.json +2 -2
- package/src/components/badge/COMPONENT.md +14 -1
- package/src/components/badge/examples/examples.module.css +7 -0
- package/src/components/badge/examples/tag-row.tsx +34 -0
- package/src/components/breadcrumb/COMPONENT.md +9 -4
- package/src/components/breadcrumb/examples/router.tsx +17 -0
- package/src/components/button/COMPONENT.md +1 -1
- package/src/components/button-group/COMPONENT.md +1 -0
- package/src/components/card/COMPONENT.md +7 -1
- package/src/components/card/examples/states.tsx +59 -0
- package/src/components/chat/COMPONENT.md +4 -1
- package/src/components/chat/examples/time-zone.tsx +83 -0
- package/src/components/chat-list/COMPONENT.md +12 -6
- package/src/components/chat-list/examples/links.tsx +1 -1
- package/src/components/chat-list/examples/router.tsx +63 -0
- package/src/components/checkbox/COMPONENT.md +1 -0
- package/src/components/color-field/COMPONENT.md +2 -1
- package/src/components/color-picker/COMPONENT.md +14 -5
- package/src/components/color-picker/examples/presets-custom.tsx +31 -0
- package/src/components/color-swatches/COMPONENT.md +1 -0
- package/src/components/confirm-dialog/COMPONENT.md +1 -1
- package/src/components/crossfade/COMPONENT.md +1 -1
- package/src/components/data-table/COMPONENT.md +46 -41
- package/src/components/data-table/examples/actions-column.tsx +154 -0
- package/src/components/data-table/examples/columns-visibility.tsx +3 -12
- package/src/components/data-table/examples/controlled.tsx +1 -1
- package/src/components/data-table/examples/narrow.tsx +4 -11
- package/src/components/data-table/examples/numeric.tsx +9 -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/toolbar.tsx +26 -32
- package/src/components/datepicker/COMPONENT.md +3 -1
- package/src/components/datepicker/examples/deadline.tsx +33 -0
- package/src/components/digit-input/COMPONENT.md +1 -0
- package/src/components/dnd/COMPONENT.md +4 -3
- 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.tsx +6 -6
- package/src/components/drawer/COMPONENT.md +38 -9
- package/src/components/drawer/examples/client-card.tsx +32 -8
- 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 +40 -24
- 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/reorder.tsx +1 -1
- package/src/components/field-list/examples/saving.tsx +83 -0
- package/src/components/field-list/examples/screen.module.css +1 -1
- package/src/components/field-list/examples/screen.tsx +168 -162
- package/src/components/field-list/examples/totals.tsx +83 -0
- package/src/components/file-upload/COMPONENT.md +1 -0
- package/src/components/hint/COMPONENT.md +16 -2
- package/src/components/hint/examples/variants.tsx +48 -0
- package/src/components/input/COMPONENT.md +39 -9
- package/src/components/input/examples/affixes.tsx +4 -2
- package/src/components/input/examples/dismiss.tsx +29 -0
- package/src/components/input/examples/suggestions.tsx +26 -0
- package/src/components/input/examples/time.tsx +24 -0
- package/src/components/input/examples/with-select.tsx +44 -0
- package/src/components/kanban/COMPONENT.md +12 -8
- package/src/components/kanban/examples/columns.tsx +4 -2
- package/src/components/kanban/examples/states.tsx +7 -5
- package/src/components/list/COMPONENT.md +39 -13
- package/src/components/list/examples/reorder.tsx +42 -7
- package/src/components/list/examples/row-controls.tsx +80 -0
- package/src/components/list/examples/with-icon.tsx +23 -2
- package/src/components/login-form/COMPONENT.md +8 -7
- package/src/components/login-form/examples/states.tsx +12 -14
- package/src/components/message/COMPONENT.md +30 -9
- package/src/components/message/examples/preview.tsx +28 -0
- package/src/components/message/examples/sticker.tsx +35 -0
- package/src/components/modal/COMPONENT.md +35 -10
- package/src/components/modal/examples/long-content.tsx +37 -18
- package/src/components/native-select/COMPONENT.md +1 -0
- package/src/components/notification/COMPONENT.md +1 -1
- package/src/components/radio/COMPONENT.md +2 -0
- package/src/components/rich-text/COMPONENT.md +93 -0
- package/src/components/rich-text/examples/overview.tsx +19 -0
- package/src/components/scroll-container/COMPONENT.md +8 -5
- package/src/components/segmented-control/COMPONENT.md +4 -2
- package/src/components/segmented-control/examples/in-form.tsx +1 -1
- package/src/components/select/COMPONENT.md +7 -3
- package/src/components/sheet/COMPONENT.md +18 -7
- package/src/components/slider/COMPONENT.md +1 -0
- package/src/components/slider/examples/controlled.tsx +1 -1
- package/src/components/switch/COMPONENT.md +1 -0
- package/src/components/tag-select/COMPONENT.md +1 -0
- package/src/components/textarea/COMPONENT.md +1 -0
- package/src/components/timeline/COMPONENT.md +3 -3
- package/src/components/timeline/examples/structure.tsx +2 -1
- package/src/layout/app-shell/COMPONENT.md +2 -2
- package/src/layout/bottom-nav/COMPONENT.md +1 -0
- package/src/layout/page/COMPONENT.md +42 -20
- package/src/layout/page/examples/examples.module.css +7 -0
- package/src/layout/page/examples/guard.tsx +87 -0
- package/src/layout/page/examples/loading.tsx +57 -0
- 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/layout/sidebar/COMPONENT.md +1 -0
- package/src/styles/theme-dark.css +1 -1
- package/src/styles/theme-light.css +2 -1
- package/dist/components/data-table/context.d.ts +0 -14
- package/dist/components/scroll-container/useWheelToInline.d.ts +0 -10
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
## When not to use
|
|
14
14
|
- The color comes from a short fixed palette and the choice should be visible at once → use [ColorSwatches](../color-swatches/COMPONENT.md).
|
|
15
|
-
- A compact color next to a field or in a dense list row → use [ColorPresets](../color-picker/COMPONENT.md) (square trigger + palette).
|
|
15
|
+
- A compact color next to a field or in a dense list row → use [ColorPresets](../color-picker/COMPONENT.md) (square trigger + palette; `allowCustom` adds a hex field for any other color).
|
|
16
16
|
- The picker panel itself is the screen (a design tool, an inline editor) → compose [ColorPicker](../color-picker/COMPONENT.md) parts.
|
|
17
17
|
- A plain text field for a hex code → use [Input](../input/COMPONENT.md).
|
|
18
18
|
|
|
@@ -55,6 +55,7 @@ ColorField field frame: label · field button · hint | er
|
|
|
55
55
|
| `required` | `boolean` | `false` | Red `*` after the label; the field button is described by `labels.required` (a button takes no `aria-required`). |
|
|
56
56
|
| `optional` | `boolean` | — | Muted marker right after the label text (`labels.optional`). |
|
|
57
57
|
| `hint` | `ReactNode` | — | Help text under the field. Hidden while `error` is shown. |
|
|
58
|
+
| `hintTone` | `"neutral" \| "success" \| "warning" \| "danger"` | `"neutral"` | Status color of `hint` («Осталось 12 дней» in `warning`). The words carry the status, the color repeats it; an `error` replaces the hint and its tone. A validation error is `error`, never a `danger` hint. |
|
|
58
59
|
| `error` | `ReactNode` | — | Error message in the hint slot; implies `invalid`. |
|
|
59
60
|
| `invalid` | `boolean` | — | Danger ring and `aria-invalid` without a message. A non-empty `error` implies it. |
|
|
60
61
|
| `disabled` | `boolean` | `false` | Disables the field: it shows the color and does not open. |
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
## When to use
|
|
9
9
|
- `ColorPicker` — any color is allowed and the picker parts are laid out by hand: an inline panel, a design tool, a hex field with a custom trigger.
|
|
10
|
-
- `ColorPresets` — a color from a fixed palette with an optional «no color»: label, project or calendar colors, one trigger per row.
|
|
10
|
+
- `ColorPresets` — a color from a fixed palette with an optional «no color»: label, project or calendar colors, one trigger per row. With `allowCustom` the palette is a shortcut, not a limit: any hex is typed under it (a spec color on a site, a brand color in a dense list row).
|
|
11
11
|
- `parseColor` — turning a CSS string into a `Color` for a controlled `ColorPicker`.
|
|
12
12
|
|
|
13
13
|
## When not to use
|
|
@@ -49,6 +49,7 @@ ColorPresets.Root value, open, presets (no DOM)
|
|
|
49
49
|
├─ ColorPresets.Trigger slot around one element
|
|
50
50
|
│ └─ ColorPresets.SwatchButton square swatch button (or your Button with ColorPresets.Swatch)
|
|
51
51
|
└─ ColorPresets.Content popover with the swatch grid (listbox)
|
|
52
|
+
└─ Input hex field with the typed color's chip (`allowCustom`)
|
|
52
53
|
```
|
|
53
54
|
Helpers: `parseColor(value)` (throws on invalid input; back to text with `color.toString("hex" | "hexa" | "css")`), `COLOR_PRESETS` (16 colors: step 500 and step 700 of eight hues), types `ColorPickerColorValue`, `ColorValueFormat`, `ColorPreset`.
|
|
54
55
|
|
|
@@ -86,6 +87,7 @@ No DOM. Holds the color (React Aria `ColorPicker`) and the value format for ever
|
|
|
86
87
|
|---|---|---|---|
|
|
87
88
|
| `label` | `ReactNode` | — | Field label; defaults to `labels.hex`. |
|
|
88
89
|
| `hint` | `ReactNode` | — | Help text under the field. Hidden while `error` is shown. |
|
|
90
|
+
| `hintTone` | `"neutral" \| "success" \| "warning" \| "danger"` | `"neutral"` | Status color of `hint` («Осталось 12 дней» in `warning`). The words carry the status, the color repeats it; an `error` replaces the hint and its tone. A validation error is `error`, never a `danger` hint. |
|
|
89
91
|
| `error` | `ReactNode` | — | Error message in the hint slot; marks the field invalid. |
|
|
90
92
|
| `focusRing` | `boolean` | `true` | `false` hides only the visual focus ring of the fields (`data-focus-ring="false"`); focus, keyboard and ARIA stay. |
|
|
91
93
|
| `children` | `ReactNode` | — | End segments of the field box after the value: `ColorPicker.SwatchButton` (in a `Popover.Trigger`), so the hex and its swatch read as one field. |
|
|
@@ -164,7 +166,7 @@ No DOM. Holds the color (React Aria `ColorPicker`) and the value format for ever
|
|
|
164
166
|
| Prop | Type | Default | Description |
|
|
165
167
|
|---|---|---|---|
|
|
166
168
|
| `presets` | `readonly ColorPreset[]` | `COLOR_PRESETS` | Swatches `{ value, label }`; the label names the swatch. |
|
|
167
|
-
| `label · hint · error · invalid · required · optional · disabled · size · id · labels · aria-label · aria-labelledby · aria-describedby` | `ColorSwatchesProps` | — | As on `ColorSwatches`. |
|
|
169
|
+
| `label · hint · hintTone · error · invalid · required · optional · disabled · size · id · labels · aria-label · aria-labelledby · aria-describedby` | `ColorSwatchesProps` | — | As on `ColorSwatches`. |
|
|
168
170
|
| `…rest` | `Omit<ColorSwatchesProps, "value" \| "defaultValue" \| "onValueChange" \| "allowEmpty" \| "name">` | — | `className` and the other attributes of the field frame. |
|
|
169
171
|
|
|
170
172
|
### ColorPicker.EyeDropperButton
|
|
@@ -194,6 +196,7 @@ No DOM and no ref, except a field frame in a FieldList cell (the column heading
|
|
|
194
196
|
| `size` | `"xs" \| "s" \| "m" \| "l" \| "xl"` | host tier, else `"m"` | Tier of the trigger, the swatches and the panel. Without it the tier of its host, else `m`. |
|
|
195
197
|
| `disabled` | `boolean` | `false` | The trigger is disabled and does not open the panel. A disabled `Fieldset` around it sets it too. |
|
|
196
198
|
| `allowEmpty` | `boolean` | `false` | Adds the «no color» swatch after the presets (value `null`). |
|
|
199
|
+
| `allowCustom` | `boolean` | `false` | Any color beyond the palette: a hex field under the swatches (`labels.custom`) shows the typed color, Enter picks it as `#rrggbb`; invalid text gets `labels.customInvalid`. |
|
|
197
200
|
| `closeOnSelect` | `boolean` | `true` | Close the panel after a pick (focus returns to the trigger). |
|
|
198
201
|
| `labels` | `Partial<ColorPresetsLabels>` | — | Built-in strings, see Labels. |
|
|
199
202
|
| `children` | `ReactNode` | — (required) | `ColorPresets.Trigger` and `ColorPresets.Content`. |
|
|
@@ -260,6 +263,7 @@ No `variant` / `tone` / `color`.
|
|
|
260
263
|
| Value | Looks like | Use when | Default |
|
|
261
264
|
|---|---|---|---|
|
|
262
265
|
| `allowEmpty` (ColorPresets) | checkerboard «Без цвета» swatch at the end | the color is optional | `false` |
|
|
266
|
+
| `allowCustom` (ColorPresets) | a «Свой цвет» hex field under the swatches, its chip showing the typed color | any color is valid, the palette only speeds the common ones | `false` |
|
|
263
267
|
| `closeOnSelect={false}` (ColorPresets) | panel stays open after a pick | trying several colors in a row | `true` |
|
|
264
268
|
| `closeOnOutsideClick={false}` (ColorPresets) | a press beside the panel keeps it open | comparing presets with the page | `true` |
|
|
265
269
|
| `closeOnEscape={false}` (ColorPresets) | Escape leaves the panel open | the panel closes only by a pick or the trigger | `true` |
|
|
@@ -280,6 +284,7 @@ No `variant` / `tone` / `color`.
|
|
|
280
284
|
| eyedropper unsupported | no `window.EyeDropper` | button `disabled`, `aria-hidden` |
|
|
281
285
|
| selected swatch | the color | `data-state="checked"`; a check mark that contrasts with the color draws in — no ring, the check is the selection |
|
|
282
286
|
| ColorPresets open | `open` / click / ArrowDown · ArrowUp on the trigger | popover `data-state`; focus on the selected swatch |
|
|
287
|
+
| ColorPresets custom color | `allowCustom` + a value that is no preset, or Enter in the hex field | no swatch is checked; the hex field holds the value; the trigger is named «`labels.trigger`: #rrggbb»; invalid text on Enter shows `labels.customInvalid` as the field's error (the error drops in, the field shakes once) |
|
|
283
288
|
| ColorPresets empty | value `null` | the trigger shows the checkerboard fill and is named «`labels.trigger`: `labels.empty`» |
|
|
284
289
|
|
|
285
290
|
There is no `disabled` on `ColorPicker.Root` — disable parts individually. Controlled: `value` + `onValueChange` (both components), `open` + `onOpenChange` (ColorPresets). Uncontrolled: `defaultValue`, `defaultOpen`.
|
|
@@ -301,8 +306,8 @@ There is no `disabled` on `ColorPicker.Root` — disable parts individually. Con
|
|
|
301
306
|
| `ArrowLeft` · `ArrowRight` · `ArrowUp` · `ArrowDown` | Move the area thumb or a slider; in the ColorPresets grid, move between swatches. |
|
|
302
307
|
| `PageUp` · `PageDown` | Larger steps on the area and the sliders. |
|
|
303
308
|
| `Home` · `End` | Slider ends; the first / last swatch in the ColorPresets grid. |
|
|
304
|
-
| `Enter` · `Space` | Commit a field; pick the focused preset swatch and close. |
|
|
305
|
-
| `Tab` | Moves through the parts; inside the ColorPresets grid returns to the trigger and closes. |
|
|
309
|
+
| `Enter` · `Space` | Commit a field; pick the focused preset swatch and close. In the ColorPresets hex field (`allowCustom`) Enter picks the typed color. |
|
|
310
|
+
| `Tab` | Moves through the parts; inside the ColorPresets grid returns to the trigger and closes. With `allowCustom` Tab goes from the grid to the hex field; past it the panel closes and focus goes on from the trigger. |
|
|
306
311
|
| `Escape` | Closes the ColorPresets panel. |
|
|
307
312
|
|
|
308
313
|
### ARIA
|
|
@@ -355,6 +360,8 @@ There is no `disabled` on `ColorPicker.Root` — disable parts individually. Con
|
|
|
355
360
|
| `trigger` | `"Цвет"` | ColorPresets trigger name prefix: «<trigger>: <color name>»; in a FieldList cell the column heading. |
|
|
356
361
|
| `list` | `"Цвета"` | ColorPresets swatch list name when `Content` has no `label`. |
|
|
357
362
|
| `empty` | `"Без цвета"` | ColorPresets «no color» swatch and the trigger name for an empty value. |
|
|
363
|
+
| `custom` | `"Свой цвет"` | Label of the ColorPresets hex field (`allowCustom`). |
|
|
364
|
+
| `customInvalid` | `"Введите цвет в формате #RRGGBB"` | Error of the ColorPresets hex field when Enter finds no hex color. |
|
|
358
365
|
|
|
359
366
|
## Examples
|
|
360
367
|
| Example | Shows |
|
|
@@ -366,12 +373,14 @@ There is no `disabled` on `ColorPicker.Root` — disable parts individually. Con
|
|
|
366
373
|
| [panel.tsx](examples/panel.tsx) | The full raised panel and its part order: format, area, hue and alpha sliders, channels, brand swatches — `ColorPicker.Panel`, `surface`, `ColorPicker.Swatches`. |
|
|
367
374
|
| [formats.tsx](examples/formats.tsx) | The channel strip in each value format; three pickers edit one color — `defaultFormat`, `ColorPicker.ChannelStrip`. |
|
|
368
375
|
| [presets.tsx](examples/presets.tsx) | A quick color from the palette: a square trigger with «no color» and a Button trigger whose grid of four columns stays open after a pick — `ColorPresets`, `allowEmpty`, `ColorPresets.Trigger`, `columns`, `closeOnSelect`. |
|
|
376
|
+
| [presets-custom.tsx](examples/presets-custom.tsx) | A spec's color on the site: the brand palette one click away and any hex typed under it — `ColorPresets`, `allowCustom`. |
|
|
369
377
|
| [presets-sizes.tsx](examples/presets-sizes.tsx) | The preset trigger in every size, a square of the control height next to an input of the same tier — `ColorPresets`, `size`. |
|
|
370
378
|
| [controlled.tsx](examples/controlled.tsx) | The parent owns the color and its format: brand swatches and the channels edit it, the format stays as picked, a button resets both — `value`, `onValueChange`, `format`, `onFormatChange`. |
|
|
371
379
|
| [controlled-open.tsx](examples/controlled-open.tsx) | The parent opens the preset palette from its own button and keeps the chosen color — `open`, `onOpenChange`, `value`, `onValueChange`. |
|
|
372
380
|
| [in-form.tsx](examples/in-form.tsx) | Theme settings: the color goes with the form, a too light color shakes in an error on save that leaves once the color changes — `value`, `error`. |
|
|
373
381
|
|
|
374
382
|
## Mistakes
|
|
383
|
+
- A ColorPresets palette padded with dozens of colors so that «any» color fits, or a ColorField beside it for the rest → `allowCustom`: the palette stays short, any hex is typed under it.
|
|
375
384
|
- Trigger in one `ColorPicker.Root` and panel in another → they will not share the color; wrap both in one Root.
|
|
376
385
|
- `isDisabled` on Area / Slider → use `disabled`.
|
|
377
386
|
- `onChange` on `ColorPicker.Root` → use `onValueChange`.
|
|
@@ -383,5 +392,5 @@ There is no `disabled` on `ColorPicker.Root` — disable parts individually. Con
|
|
|
383
392
|
- `<ColorPresets.Trigger />` with no child → put `ColorPresets.SwatchButton` (or your Button) inside it.
|
|
384
393
|
|
|
385
394
|
## Related
|
|
386
|
-
- **Built from:** [Input](../input/COMPONENT.md) (`HexInput`; its field action segment for `SwatchButton`), [Tooltip](../tooltip/COMPONENT.md) (`SwatchButton`), [Label](../label/COMPONENT.md) and [Hint](../hint/COMPONENT.md) (the `HexInput` label, hint and error), [Select](../select/COMPONENT.md) (`FormatSelect`), [Button](../button/COMPONENT.md) (`EyeDropperButton`), [ColorSwatches](../color-swatches/COMPONENT.md) (`Swatches`), [Popover](../popover/COMPONENT.md) (`ColorPresets.Root`, `ColorPresets.Content`), `Icon` (pipette), [VisuallyHidden](../visually-hidden/COMPONENT.md)
|
|
395
|
+
- **Built from:** [Input](../input/COMPONENT.md) (`HexInput`; its field action segment for `SwatchButton`; the hex field of `ColorPresets allowCustom`), [Tooltip](../tooltip/COMPONENT.md) (`SwatchButton`), [Label](../label/COMPONENT.md) and [Hint](../hint/COMPONENT.md) (the `HexInput` label, hint and error), [Select](../select/COMPONENT.md) (`FormatSelect`), [Button](../button/COMPONENT.md) (`EyeDropperButton`), [ColorSwatches](../color-swatches/COMPONENT.md) (`Swatches`), [Popover](../popover/COMPONENT.md) (`ColorPresets.Root`, `ColorPresets.Content`), `Icon` (pipette), [VisuallyHidden](../visually-hidden/COMPONENT.md)
|
|
387
396
|
- **See also:** [ColorField](../color-field/COMPONENT.md), [ColorSwatches](../color-swatches/COMPONENT.md), [TagSelect](../tag-select/COMPONENT.md)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** A spec's color on the site: the brand palette one click away and any hex typed under it — `ColorPresets`, `allowCustom`. */
|
|
2
|
+
import { ColorPresets } from "prime-ui-kit";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
|
|
5
|
+
const BRAND_COLORS = [
|
|
6
|
+
{ value: "#5b5bd6", label: "Индиго" },
|
|
7
|
+
{ value: "#0090ff", label: "Синий" },
|
|
8
|
+
{ value: "#12a594", label: "Бирюзовый" },
|
|
9
|
+
{ value: "#30a46c", label: "Зелёный" },
|
|
10
|
+
{ value: "#f76b15", label: "Оранжевый" },
|
|
11
|
+
{ value: "#e5484d", label: "Красный" },
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
export default function ColorPickerPresetsCustomExample() {
|
|
15
|
+
const [color, setColor] = React.useState<string | null>("#8e4ec6");
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<ColorPresets.Root
|
|
19
|
+
presets={BRAND_COLORS}
|
|
20
|
+
allowCustom
|
|
21
|
+
value={color}
|
|
22
|
+
onValueChange={setColor}
|
|
23
|
+
labels={{ trigger: "Цвет характеристики" }}
|
|
24
|
+
>
|
|
25
|
+
<ColorPresets.Trigger>
|
|
26
|
+
<ColorPresets.SwatchButton />
|
|
27
|
+
</ColorPresets.Trigger>
|
|
28
|
+
<ColorPresets.Content label="Цвет характеристики" />
|
|
29
|
+
</ColorPresets.Root>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
@@ -49,6 +49,7 @@ ColorSwatches field frame: label → swatches → hint | error
|
|
|
49
49
|
| `required` | `boolean` | — | Red `*` after the label and `aria-required` on the group. |
|
|
50
50
|
| `optional` | `boolean` | — | Muted marker right after the label text (`labels.optional`). |
|
|
51
51
|
| `hint` | `ReactNode` | — | Help text under the swatches. Hidden while `error` is shown. |
|
|
52
|
+
| `hintTone` | `"neutral" \| "success" \| "warning" \| "danger"` | `"neutral"` | Status color of `hint` («Осталось 12 дней» in `warning`). The words carry the status, the color repeats it; an `error` replaces the hint and its tone. A validation error is `error`, never a `danger` hint. |
|
|
52
53
|
| `error` | `ReactNode` | — | Error message in the hint slot; implies `invalid`. |
|
|
53
54
|
| `invalid` | `boolean` | — | Danger inner edge on every swatch and `aria-invalid`. A non-empty `error` implies it. |
|
|
54
55
|
| `disabled` | `boolean` | `false` | Disables every swatch (grey, half transparent). |
|
|
@@ -134,5 +134,5 @@ The dialog is a Modal `s` with the floating surface, a header and a footer; ther
|
|
|
134
134
|
- `tone="accent"` for a delete → destructive is always `danger`.
|
|
135
135
|
|
|
136
136
|
## Related
|
|
137
|
-
- **Built from:** the dialog Modal stands on (`internal/overlay/ModalDialog` at `s`, the header, body and footer of `internal/overlay/DialogParts`), [ScrollContainer](../scroll-container/COMPONENT.md) (the body), [Avatar](../avatar/COMPONENT.md) and [Thumbnail](../thumbnail/COMPONENT.md) (pictures the shared icon slot recognises), [Button](../button/COMPONENT.md) (Cancel, the confirm with `loading`), [Banner](../banner/COMPONENT.md) (the failure message), `Icon` (`status.danger` in the Banner)
|
|
137
|
+
- **Built from:** the dialog Modal stands on (`internal/overlay/ModalDialog` at `s`, the header, body and footer of `internal/overlay/DialogParts`), [ScrollContainer](../scroll-container/COMPONENT.md) (the body), [Avatar](../avatar/COMPONENT.md) and [Thumbnail](../thumbnail/COMPONENT.md) (pictures the shared icon slot recognises), [Skeleton](../skeleton/COMPONENT.md) (the shared description's loading line), [Button](../button/COMPONENT.md) (Cancel, the confirm with `loading`), [Banner](../banner/COMPONENT.md) (the failure message), `Icon` (`status.danger` in the Banner)
|
|
138
138
|
- **See also:** [Modal](../modal/COMPONENT.md), [Drawer](../drawer/COMPONENT.md), [Notification](../notification/COMPONENT.md)
|
|
@@ -45,7 +45,7 @@ Crossfade <div>; holds the region's height while it changes
|
|
|
45
45
|
| Prop | Type | Default | Description |
|
|
46
46
|
|---|---|---|---|
|
|
47
47
|
| `state` | `string \| number` | — (required) | Key of what the region shows: `"loading"`, `"ready"`, `"empty"`, `"error"` or a record id. A new value cross-fades the old content into the new one; the same value updates in place. |
|
|
48
|
-
| `fill` | `boolean` | `false` | The region takes its parent's height (a flex or grid item, or a sized block) and every state stretches to it; the height never glides. |
|
|
48
|
+
| `fill` | `boolean` | `false` | The region takes its parent's height (a flex or grid item, or a sized block) and every state stretches to it; the height never glides. A `Crossfade` that is the child of a `Page.Cell` fills it unless `fill` is set. |
|
|
49
49
|
| `children` | `ReactNode` | — | Content of the current `state`. Nothing (`null`, `false`) leaves no box once the old state has faded: no gap in a grid or a flex column. |
|
|
50
50
|
| `…rest` | `HTMLAttributes<HTMLDivElement>` | — | `className`, `aria-busy`, `aria-live`, `role` and the other div attributes. |
|
|
51
51
|
|
|
@@ -7,14 +7,14 @@
|
|
|
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
14
|
- Records whose order is data the user sets: pipeline stages, a price list, priorities (`onReorder`).
|
|
15
15
|
- Hierarchical rows (`getRowChildren`) or rows with a detail panel (`renderExpanded`).
|
|
16
16
|
- Wide numeric reports with a sticky head and first column.
|
|
17
|
-
- Wide records on narrow screens: let people choose the columns (`
|
|
17
|
+
- Wide records on narrow screens: let people choose the columns (`columnsMenu`) instead of dropping them.
|
|
18
18
|
- A log or a register that takes the rest of the page height (`scrollHeight="fill"`).
|
|
19
19
|
|
|
20
20
|
## When not to use
|
|
@@ -30,22 +30,22 @@
|
|
|
30
30
|
```tsx
|
|
31
31
|
import { DataTable, type DataTableColumn } from "prime-ui-kit";
|
|
32
32
|
```
|
|
33
|
-
Exported types: `DataTableColumn<Row>`, `DataTableProps<Row>`, `DataTableSortState`, `DataTableOrder`, `DataTableGroup<Row>`, `DataTableRowClickEvent`, `
|
|
33
|
+
Exported types: `DataTableColumn<Row>`, `DataTableProps<Row>`, `DataTableSortState`, `DataTableOrder`, `DataTableGroup<Row>`, `DataTableRowClickEvent`, `DataTableLabels`.
|
|
34
34
|
|
|
35
35
|
## Anatomy
|
|
36
36
|
```
|
|
37
37
|
DataTable card-fill block, radius 12, clips its content
|
|
38
|
-
├── toolbar optional panel
|
|
39
|
-
│ └── DataTable.ColumnsMenu the column chooser: a Button and a Dropdown of check items
|
|
38
|
+
├── toolbar optional panel for several table controls (bulk actions, own search + filters)
|
|
40
39
|
├── scroll viewport ScrollContainer, both axes, in a frame that holds the edge shadows
|
|
41
40
|
│ └── table
|
|
42
|
-
│ ├── thead [handle] [select all] [toggle] head cells; sortable heads hold a button
|
|
41
|
+
│ ├── thead [handle] [select all] [toggle] head cells [column chooser]; sortable heads hold a button
|
|
42
|
+
│ │ columnsMenu: an icon Button + Dropdown in the row-actions head cell, else a trailing cell
|
|
43
43
|
│ └── tbody rows · sub-rows · detail rows · skeleton / empty / error row
|
|
44
44
|
│ (one per group) with getRowGroup: a <th scope="rowgroup"> header row, then its rows
|
|
45
45
|
│ with onReorder: a Dnd.Sortable tbody, each row led by a Dnd.Handle
|
|
46
46
|
└── footer range «Показано 1–5 из 23» · Pagination · infinite-scroll status
|
|
47
47
|
```
|
|
48
|
-
Columns are data (`DataTableColumn<Row>[]`), not child parts. The
|
|
48
|
+
Columns are data (`DataTableColumn<Row>[]`), not child parts; the table has no parts. The column chooser is the `columnsMenu` flag: it lives in the header row, never in `toolbar`.
|
|
49
49
|
|
|
50
50
|
## API
|
|
51
51
|
|
|
@@ -57,9 +57,10 @@ Generic `DataTable<Row>`; `ref` → `HTMLDivElement`. A card-fill block with an
|
|
|
57
57
|
| Prop | Type | Default | Description |
|
|
58
58
|
|---|---|---|---|
|
|
59
59
|
| `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.
|
|
60
|
+
| `hiddenColumns` | `string[]` | — | Ids of columns that are not rendered, controlled. A column with `hideable: false` stays. The column chooser (`columnsMenu`) changes it. |
|
|
61
61
|
| `defaultHiddenColumns` | `string[]` | `[]` | Initially hidden column ids, uncontrolled. |
|
|
62
|
-
| `onHiddenColumnsChange` | `(hiddenColumns: string[]) => void` | — | The hidden ids changed (`
|
|
62
|
+
| `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. |
|
|
63
|
+
| `columnsMenu` | `boolean` | `false` | The column chooser at the end of the header row: in the head cell of a trailing row-actions column (`hideHeader`), else in a cell of its own; sticks with `stickyLastColumn`. Needs `showHeader`. |
|
|
63
64
|
| `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
65
|
| `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
66
|
| `rowCount` | `number` | `rows.length` | Total rows on the server (`source="server"`): the page count and «Показано {from}–{to} из {total}». |
|
|
@@ -78,7 +79,7 @@ Generic `DataTable<Row>`; `ref` → `HTMLDivElement`. A card-fill block with an
|
|
|
78
79
|
| `loadingRows` | `number` | `min(pageSize, 5)` | Number of skeleton rows. |
|
|
79
80
|
| `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
81
|
| `loadError` | `ReactNode` | — | Load error: replaces the body with the message in `role="alert"`. |
|
|
81
|
-
| `toolbar` | `ReactNode` | — | Panel above the table (
|
|
82
|
+
| `toolbar` | `ReactNode` | — | Panel above the table for several controls of the table itself (bulk actions on the selected rows, a table-local search with filters); stacks below 30rem of table width. |
|
|
82
83
|
| `selectable` | `boolean` | `false` | Leading checkbox column with «select all», Shift range, press-and-drag and Space. |
|
|
83
84
|
| `selected` | `Key[]` | — | Selected row ids, controlled. |
|
|
84
85
|
| `defaultSelected` | `Key[]` | `[]` | Initially selected ids, uncontrolled. |
|
|
@@ -97,6 +98,7 @@ Generic `DataTable<Row>`; `ref` → `HTMLDivElement`. A card-fill block with an
|
|
|
97
98
|
| `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
99
|
| `stickyHeader` | `boolean` | `false` | The head sticks while the body scrolls (with `scrollHeight`); on screens lower than 480px it scrolls with the rows. |
|
|
99
100
|
| `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. |
|
|
101
|
+
| `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
102
|
| `showHeader` | `boolean` | `true` | Render `<thead>`. |
|
|
101
103
|
| `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
104
|
| `rowDividers` | `boolean` | `true` | Hairlines between rows. |
|
|
@@ -117,15 +119,6 @@ Generic `DataTable<Row>`; `ref` → `HTMLDivElement`. A card-fill block with an
|
|
|
117
119
|
| `className` | `string` | — | Class on the root `<div>`. |
|
|
118
120
|
| `…rest` | `Omit<HTMLAttributes<HTMLDivElement>, "children">` | — | The other attributes of the root `<div>`. |
|
|
119
121
|
|
|
120
|
-
### DataTable.ColumnsMenu
|
|
121
|
-
`ref` → `HTMLButtonElement` (the trigger). The column chooser of the table it sits in: a Button opening a Dropdown with a check item per column. Writes the table's hidden columns; throws outside a DataTable `toolbar`.
|
|
122
|
-
|
|
123
|
-
| Prop | Type | Default | Description |
|
|
124
|
-
|---|---|---|---|
|
|
125
|
-
| `side` | `"top" \| "right" \| "bottom" \| "left"` | `"bottom"` | Side of the trigger the menu opens on. |
|
|
126
|
-
| `align` | `"auto" \| "start" \| "center" \| "end"` | `"auto"` | Alignment to the trigger. `auto` lines the panel up with the trigger edge that has more room beyond it; `start`, `center` or `end` fix it. |
|
|
127
|
-
| `…rest` | `Omit<ButtonHTMLAttributes<HTMLButtonElement>, "type" \| "children">` | — | `className`, `aria-label` and the other attributes of the trigger button. |
|
|
128
|
-
|
|
129
122
|
### Types
|
|
130
123
|
|
|
131
124
|
#### `DataTableColumn<Row>`
|
|
@@ -143,10 +136,11 @@ One column of `columns`: data, not a part.
|
|
|
143
136
|
| `align` | `"start" \| "center" \| "end"` | `"start"` (`"end"` with `numeric`) | Cell alignment; heads do not follow it. |
|
|
144
137
|
| `headerAlign` | `"start" \| "center" \| "end"` | `"start"` | Head alignment; the sort icon stays at the end edge. |
|
|
145
138
|
| `hideHeader` | `boolean` | `false` | `header` names the column for assistive tech only (an action column): the head cell looks empty. |
|
|
139
|
+
| `description` | `string` | — | What the column means: an info glyph after the header opens it as a tooltip; the header cell is described by it (`aria-describedby`). |
|
|
146
140
|
| `numeric` | `boolean` | — | Tabular figures, no wrapping, end alignment unless `align` is set. |
|
|
147
141
|
| `truncate` | `boolean` | — | One line with an ellipsis; width from `maxWidth` (or `width`); string values get a `title`. |
|
|
148
142
|
| `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. |
|
|
149
|
-
| `hideable` | `boolean` | `true` | The column can be hidden through `hiddenColumns` and `
|
|
143
|
+
| `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. |
|
|
150
144
|
| `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. |
|
|
151
145
|
| `width · minWidth · maxWidth` | `string` | — | CSS sizes of the column (`"14rem"`). |
|
|
152
146
|
|
|
@@ -222,13 +216,16 @@ Heads keep `start` whatever the cell alignment, with the sort icon at the end ed
|
|
|
222
216
|
| `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` |
|
|
223
217
|
| `highlightColumnOnHover` | `fill-subtle-active` wash on the hovered column | comparison tables | `false` |
|
|
224
218
|
| `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` |
|
|
219
|
+
| `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` |
|
|
225
220
|
| `stickyGroupHeaders` | group header rows stick under the head while their rows scroll | long grouped tables in a `scrollHeight` window | `false` |
|
|
226
221
|
| `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 |
|
|
227
|
-
|
|
|
222
|
+
| `columnsMenu` | an icon-only ghost Button (`view.columns`) at the end of the header row: in the head cell of a trailing row-actions column (`hideHeader`), else in a narrow cell of its own; it opens the column chooser | every table with more columns than a narrow screen holds; the default home of the chooser | `false` |
|
|
223
|
+
| 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` |
|
|
228
224
|
| `showHeader` | head row shown | off only for self-explanatory key/value tables | `true` |
|
|
229
225
|
| `fullWidth` | spans the container; `false` = content width | `false` for short lookup tables in wide layouts | `true` |
|
|
230
226
|
| column `numeric` | tabular figures, end-aligned, no wrap | numbers, money | — |
|
|
231
227
|
| column `truncate` | one line with an ellipsis and a `title` | long names in narrow columns | — |
|
|
228
|
+
| column `description` | an info glyph after the header; its tooltip holds the text, the header cell is described by it | a header that needs a word more («Маржа», an event type) | — |
|
|
232
229
|
| column `scale` | each cell shaded by its value on the five-step chart scale, the value kept in the cell | a heatmap: counts by person × month, load by day | — |
|
|
233
230
|
|
|
234
231
|
`scale: true` gives each column its own range (its minimum to maximum over all rows), so the same value can take different shades in two columns. Several columns that read as one heatmap (one column per month) share a scale when each gets the same fixed `{ min, max }` — both ends, since an open end is still the column's own: `scale: { min: 0, max: 25 }` on every month column ([heatmap.tsx](examples/heatmap.tsx)).
|
|
@@ -247,8 +244,8 @@ Heads keep `start` whatever the cell alignment, with the sort icon at the end ed
|
|
|
247
244
|
| expanded | `expanded` / `defaultExpanded` | `data-expanded` on the parent row (one step darker); toggle `aria-expanded`, chevron turns 90° |
|
|
248
245
|
| new rows | rows new in `rows` (by `getRowKey`) | `data-animate`: top-level cells drop in from above (`enterMotion`) |
|
|
249
246
|
| 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 |
|
|
250
|
-
| 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` |
|
|
251
|
-
| hidden columns | `hiddenColumns` / `defaultHiddenColumns`, `
|
|
247
|
+
| 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` |
|
|
248
|
+
| hidden columns | `hiddenColumns` / `defaultHiddenColumns`, `columnsMenu` | 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 |
|
|
252
249
|
| 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 |
|
|
253
250
|
| 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` |
|
|
254
251
|
| 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 |
|
|
@@ -259,25 +256,26 @@ Heads keep `start` whatever the cell alignment, with the sort icon at the end ed
|
|
|
259
256
|
| filling the parent | `scrollHeight="fill"` | `data-scroll-height="fill"` on the root; the viewport takes the free height |
|
|
260
257
|
| 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 |
|
|
261
258
|
|
|
262
|
-
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`.
|
|
259
|
+
Root attributes: `data-size`, `data-row-dividers`, `data-column-dividers`, `data-sticky-header`, `data-sticky-first-column`, `data-sticky-last-column`, `data-menu-cell` (the column chooser in a trailing cell of its own), `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`.
|
|
263
260
|
|
|
264
261
|
## Layout & spacing
|
|
265
262
|
- 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.
|
|
263
|
+
- `toolbar` holds several controls of the table itself: bulk actions on the selected rows, or the search and filters of a table that is not the page's main region (a section of a record, a Drawer). One control never gets a bar: the column chooser is `columnsMenu` in the header row; the page's search, filters, period, view, figures and actions go to its top bar (`Page.Tools`, `Page.Actions`, `Page.Description`).
|
|
266
264
|
- Toolbar padding `--prime-space-3` × cell padding, items `gap: --prime-space-2`; below 30rem of table width toolbar and footer stack.
|
|
267
265
|
- 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.
|
|
268
|
-
- Columns scroll sideways inside the table, never the page; pin the identifying column with `stickyFirstColumn
|
|
269
|
-
- 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.
|
|
270
|
-
- Fewer columns, less scrolling:
|
|
271
|
-
-
|
|
266
|
+
- 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.
|
|
267
|
+
- 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.
|
|
268
|
+
- Fewer columns, less scrolling: turn on `columnsMenu` (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.
|
|
269
|
+
- The column chooser is an icon-only ghost neutral Button one tier below the table (the `view.columns` icon; `labels.columns` is its name and its Tooltip) at the end of the header row. With a trailing row-actions column (the last visible column has `hideHeader`) it stands in that column's head cell, lined up with the ⋯ buttons under it; otherwise it takes a narrow trailing cell (the trigger plus the end padding, no column divider) that every row repeats empty. With `stickyLastColumn` it sticks: in the actions head cell with that column, or its own cell at the end edge with the last column pinned right before it. Its Dropdown opens below, lined up with the trigger's end edge, lists every column and ends with `labels.showAllColumns`; a `hideable: false` column stays checked and disabled, and the last visible column cannot be hidden.
|
|
272
270
|
- 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.
|
|
273
271
|
- 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`.
|
|
274
272
|
- 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.
|
|
275
273
|
- 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.
|
|
276
274
|
- 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.
|
|
277
|
-
- 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
|
|
275
|
+
- 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`).
|
|
278
276
|
- `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.
|
|
279
277
|
- The sticky head stops sticking on screens lower than 480px (landscape phones), so it never takes a large share of the height.
|
|
280
|
-
- 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). Toolbar controls use `s` in an `m` table.
|
|
278
|
+
- 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). Toolbar controls and the column chooser use `s` in an `m` table.
|
|
281
279
|
- Column widths: `width` / `minWidth` / `maxWidth` strings; never size cells with custom CSS.
|
|
282
280
|
- Sub-rows indent by `--dt-indent` per level (avatar of the tier + gap); override it on the root for other leading content.
|
|
283
281
|
|
|
@@ -288,7 +286,7 @@ Root attributes: `data-size`, `data-row-dividers`, `data-column-dividers`, `data
|
|
|
288
286
|
|
|
289
287
|
| Key | Action |
|
|
290
288
|
|---|---|
|
|
291
|
-
| `Tab` | Moves through the toolbar (`
|
|
289
|
+
| `Tab` | Moves through the toolbar, sort buttons, the column chooser (`columnsMenu`), row handles, checkboxes, expand toggles, row links, rows that open in place and Pagination. |
|
|
292
290
|
| `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. |
|
|
293
291
|
| `Space` | Toggles the focused row checkbox. |
|
|
294
292
|
| `Shift + Space` | Selects the range from the last toggled row. |
|
|
@@ -302,12 +300,13 @@ Root attributes: `data-size`, `data-row-dividers`, `data-column-dividers`, `data
|
|
|
302
300
|
- 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.
|
|
303
301
|
- 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).
|
|
304
302
|
- A group header is a `<th scope="rowgroup">` across every column, first in its own `<tbody>`.
|
|
305
|
-
- `
|
|
303
|
+
- The column chooser (`columnsMenu`) is a menu button named by `labels.columns` (its tooltip says the same): `menuitemcheckbox` items with `aria-checked`; the key column is `aria-disabled`. In the row-actions head cell the column keeps its own name (`aria-labelledby`); its own trailing cell is a `<td>`.
|
|
306
304
|
- 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.
|
|
307
305
|
- After a selection change a polite live region announces `labels.selectedCount`; selected rows carry `aria-selected`.
|
|
308
306
|
- 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`.
|
|
309
307
|
- The expand toggle is a button with `aria-expanded`, `aria-controls` (detail row or sub-rows) and `labels.expand` / `labels.collapse`.
|
|
310
308
|
- 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}`.
|
|
309
|
+
- 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.
|
|
311
310
|
- Loading sets `aria-busy` and a `labels.loading` status; the error is `role="alert"`; the default empty state is `role="status"`.
|
|
312
311
|
|
|
313
312
|
### Labels
|
|
@@ -325,44 +324,47 @@ Root attributes: `data-size`, `data-row-dividers`, `data-column-dividers`, `data
|
|
|
325
324
|
| `selectedCount` | `"Выбрано: {count}"` | Polite announcement after the selection changes. |
|
|
326
325
|
| `expand` | `"Развернуть строку {label}"` | Name of the toggle of a collapsed row. |
|
|
327
326
|
| `collapse` | `"Свернуть строку {label}"` | Name of the toggle of an expanded row. |
|
|
328
|
-
| `columns` | `"Колонки"` |
|
|
329
|
-
| `showAllColumns` | `"Показать все"` | The
|
|
327
|
+
| `columns` | `"Колонки"` | Name and tooltip of the column chooser trigger (`columnsMenu`); `{shown}` and `{total}` are column counts. |
|
|
328
|
+
| `showAllColumns` | `"Показать все"` | The column chooser item that shows every column again. |
|
|
330
329
|
| `reorderRow` | `"Переместить строку {label}"` | `aria-label` of a row's drag handle (`onReorder`); `{label}` is `getRowLabel(row)`. |
|
|
331
330
|
| `reorderSorted` | `"Порядок задан сортировкой. Сбросьте её, чтобы перемещать строки"` | Tooltip of the disabled handles while the table is sorted by a column. |
|
|
332
331
|
| `expandGroup` | `"Развернуть группу {group}"` | Name of the toggle of a collapsed group; `{group}` is the group key. |
|
|
333
332
|
| `collapseGroup` | `"Свернуть группу {group}"` | Name of the toggle of an expanded group; `{group}` is the group key. |
|
|
333
|
+
| `columnInfo` | `"Пояснение"` | Name of the info glyph of a column with a `description`; the tooltip holds the text. |
|
|
334
334
|
|
|
335
335
|
## Examples
|
|
336
336
|
| Example | Shows |
|
|
337
337
|
|---|---|
|
|
338
338
|
| [overview.tsx](examples/overview.tsx) | Recent orders: sortable columns, a status Badge, numeric sums and five rows per page — `columns`, `getRowKey`, `pageSize`. |
|
|
339
339
|
| [sizes.tsx](examples/sizes.tsx) | Every density: rows from 36 to 52 px, the head at the control height of the tier — `size`. |
|
|
340
|
-
| [numeric.tsx](examples/numeric.tsx) | An inventory report: number columns align to the end in tabular figures, a long name stays on one line with a title, formatted cells sort by their raw number
|
|
340
|
+
| [numeric.tsx](examples/numeric.tsx) | An inventory report: number columns align to the end in tabular figures, a long name stays on one line with a title, formatted cells sort by their raw number article numbers in natural order and a header that needs a word more explains itself in a tooltip — `numeric`, `truncate`, `maxWidth`, `sortAccessor`, `sortComparator`, `description`. |
|
|
341
341
|
| [heatmap.tsx](examples/heatmap.tsx) | Deals closed per manager and month as a heatmap: each count shades its cell on the chart scale and stays readable in it — `scale`, `numeric`. |
|
|
342
342
|
| [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`. |
|
|
343
343
|
| [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`. |
|
|
344
344
|
| [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`. |
|
|
345
|
-
| [toolbar.tsx](examples/toolbar.tsx) | A campaign
|
|
345
|
+
| [toolbar.tsx](examples/toolbar.tsx) | A campaign table with its own search and status filter above it — two table-scoped controls; the empty text when nothing matches — `toolbar`, `empty`. |
|
|
346
346
|
| [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`. |
|
|
347
347
|
| [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`. |
|
|
348
348
|
| [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`. |
|
|
349
349
|
| [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`. |
|
|
350
|
+
| [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`. |
|
|
350
351
|
| [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`. |
|
|
351
352
|
| [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`. |
|
|
352
353
|
| [reorder.tsx](examples/reorder.tsx) | Pipeline stages put in order by the handle or Alt + ↑ / ↓; each move is saved with a spinner in its handle, and sorting by a column turns the handles off — `onReorder`, `getRowLabel`. |
|
|
353
354
|
| [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`. |
|
|
354
|
-
| [columns-visibility.tsx](examples/columns-visibility.tsx) | Orders with the column chooser
|
|
355
|
+
| [columns-visibility.tsx](examples/columns-visibility.tsx) | Orders with the column chooser at the end of the header row; the choice outlives a reload in local storage, the order number always stays — `columnsMenu`, `hiddenColumns`, `onHiddenColumnsChange`, `hideable`. |
|
|
355
356
|
| [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`. |
|
|
356
357
|
| [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`. |
|
|
357
358
|
| [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`. |
|
|
358
359
|
| [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`. |
|
|
359
360
|
| [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`. |
|
|
360
|
-
| [narrow.tsx](examples/narrow.tsx) | A 320 px support queue: columns scroll inside the table with the first one pinned, the
|
|
361
|
+
| [narrow.tsx](examples/narrow.tsx) | A 320 px support queue: columns scroll inside the table with the first one pinned, the column chooser stays at the end of the header row, the footer reflows and the pager turns compact — `stickyFirstColumn`, `columnsMenu`, `size`. |
|
|
361
362
|
| [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`. |
|
|
362
363
|
|
|
363
364
|
## Mistakes
|
|
364
365
|
- No `getRowKey` with `selectable`, expansion or sorting → selection follows positions, not records.
|
|
365
366
|
- Numbers in a plain column → set `numeric` (alignment and tabular figures).
|
|
367
|
+
- An explanation squeezed into the header text, or a hand-made icon with a Tooltip inside `header` → `description`.
|
|
366
368
|
- A custom «Ничего не найдено» row inside `rows` → use `empty`.
|
|
367
369
|
- A spinner instead of rows → use `loading` (the skeleton keeps the head and the layout).
|
|
368
370
|
- Wrapping the table in a Card for a border → the table is already a bounded block.
|
|
@@ -371,10 +373,13 @@ Root attributes: `data-size`, `data-row-dividers`, `data-column-dividers`, `data
|
|
|
371
373
|
- 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.
|
|
372
374
|
- A long table in a `scrollHeight` window without `stickyHeader` → the head scrolls away.
|
|
373
375
|
- `paging="none"` for hundreds of rows → use `pages` or `infinite`.
|
|
374
|
-
- Dropping columns below a breakpoint → people lose data without knowing it;
|
|
375
|
-
- A hand-built column chooser from Dropdown items → `
|
|
376
|
+
- Dropping columns below a breakpoint → people lose data without knowing it; turn on `columnsMenu`.
|
|
377
|
+
- A hand-built column chooser from Dropdown items → `columnsMenu` (key column, last visible column, «Показать все» built in).
|
|
378
|
+
- A toolbar with one button (the column chooser, «Экспорт», «Создать») → a whole bar above the table for one control; the chooser is `columnsMenu` in the header row, the page's actions go to `Page.Actions`.
|
|
379
|
+
- The page's search, filters, period, view or figures in `toolbar` → they belong to the page's top bar (`Page.Tools`, `Page.Actions`, `Page.Description`); `toolbar` keeps several controls of the table itself (bulk actions, the search and filters of a table in a section or a Drawer).
|
|
376
380
|
- Letting the key column be hidden → set `hideable: false` on it, so every row keeps its name.
|
|
377
381
|
- Wrapping the table in an `overflow-x` box of your own → it already scrolls inside and shows the edge shadows.
|
|
382
|
+
- 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`.
|
|
378
383
|
- `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()`.
|
|
379
384
|
- 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`.
|
|
380
385
|
- A totals row that opens like a record → `isRowClickable`.
|
|
@@ -388,5 +393,5 @@ Root attributes: `data-size`, `data-row-dividers`, `data-column-dividers`, `data
|
|
|
388
393
|
- A new search that keeps the current page → set `page` to 1 together with the search.
|
|
389
394
|
|
|
390
395
|
## Related
|
|
391
|
-
- **Built from:** [Checkbox](../checkbox/COMPONENT.md), [Button](../button/COMPONENT.md), [Dropdown](../dropdown/COMPONENT.md) (
|
|
396
|
+
- **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`), [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)
|
|
392
397
|
- **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)
|