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
|
@@ -47,6 +47,7 @@ Card.Root asChild <a> or <button> (the only child) holding the pa
|
|
|
47
47
|
|---|---|---|---|
|
|
48
48
|
| `variant` | `"panel" \| "mini" \| "stat-trend" \| "split" \| "cta" \| "list" \| "cover"` | `"panel"` | Structural template: titled block with zones (`panel`), KPI tiles, a call to action, a list or a cover tile. |
|
|
49
49
|
| `flat` | `boolean` | `false` | No raised shadow: a flat tile for dense grids. |
|
|
50
|
+
| `loading` | `boolean` | `false` | The KPI is loading: `Card.Value`, `Card.Delta` and `Card.Meta` show a Skeleton in their own geometry and the root sets `aria-busy`; the data fades in when it arrives. Labels and titles stay. |
|
|
50
51
|
| `asChild` | `boolean` | `false` | The whole card is one link or button: pass that element as the only child with the parts inside it; it gets hover, press and the focus ring. Nothing interactive may sit inside it. |
|
|
51
52
|
| `…rest` | `HTMLAttributes<HTMLDivElement>` | — | `className`, `role` + `aria-labelledby` for a landmark block, and the other div attributes. |
|
|
52
53
|
|
|
@@ -154,6 +155,7 @@ Card.Root asChild <a> or <button> (the only child) holding the pa
|
|
|
154
155
|
| Value | Looks like | Use when | Default |
|
|
155
156
|
|---|---|---|---|
|
|
156
157
|
| `flat` | same fill, no shadow | dense grids of tiles | `false` |
|
|
158
|
+
| `loading` | `Card.Value`, `Card.Delta` and `Card.Meta` hold a Skeleton in their own geometry (the value a bar one line of its role high); the data fades in under the same element | a KPI waits for its report | `false` |
|
|
157
159
|
| `asChild` | the card is the link or button it wraps: lifts on hover (raised → overlay shadow), presses, focus ring | the whole tile opens its details | `false` |
|
|
158
160
|
|
|
159
161
|
## States
|
|
@@ -161,6 +163,7 @@ Card.Root asChild <a> or <button> (the only child) holding the pa
|
|
|
161
163
|
|---|---|---|
|
|
162
164
|
| template | `variant` | `data-variant` |
|
|
163
165
|
| flat | `flat` | `data-flat` |
|
|
166
|
+
| loading | `loading` | `aria-busy` on the root; `data-loading` on `Card.Value`, `Card.Delta`, `Card.Meta`, each holding a `Skeleton`; on `false` the data fades in (`useSwapIn`, foundation §1 rule 7) |
|
|
164
167
|
| depth | nesting: one above the nearest surface (the page and the AppShell panel are 0) | `data-depth` (`1`–`4`, `floating-1`/`floating-2` inside a floating layer); the fill is `--prime-color-layer-current`, the shadow only at depth 1 |
|
|
165
168
|
| card width | container queries | `split` stacks below 22rem, `Header` wraps below 22rem (a header control under its description), the `stat-trend` value changes at 20rem / 36rem |
|
|
166
169
|
| hover | `asChild`, a fine pointer | the fill stays (a whole surface never changes its fill, foundation §8); the shadow lifts to `--prime-shadow-overlay` over `fast` |
|
|
@@ -195,6 +198,7 @@ Without `asChild` a card is static: no hover, focus or press of its own. With it
|
|
|
195
198
|
- `Card.Root` is a plain `<div>`; give it `role="region"` + `aria-labelledby` only when it is a landmark-worthy block.
|
|
196
199
|
- `Card.Title` renders `<h3>`; directly under the page title pass `as="h2"`.
|
|
197
200
|
- Decorative icons in `Card.Icon` and cover images in `Card.Media` get `aria-hidden`; controls in `Card.Header` need their own names.
|
|
201
|
+
- A `loading` card sets `aria-busy` on its root; the Skeletons are decorative (`aria-hidden`).
|
|
198
202
|
|
|
199
203
|
### Labels
|
|
200
204
|
<!-- Generated from api.ts by `bun run docs:build`. Edit api.ts, not this section. -->
|
|
@@ -211,6 +215,7 @@ No `labels`.
|
|
|
211
215
|
| [interactive.tsx](examples/interactive.tsx) | Whole cards as links to their reports: one tab stop each, a lift on hover, a press and the focus ring — `asChild`. |
|
|
212
216
|
| [content-templates.tsx](examples/content-templates.tsx) | Content templates: a call to action, an events list and a campaign tile with a cover — `Card.Footer`, `Card.List`, `Card.Media`. |
|
|
213
217
|
| [flat.tsx](examples/flat.tsx) | A flat tile without the raised shadow next to the default one, for dense grids — `flat`. |
|
|
218
|
+
| [states.tsx](examples/states.tsx) | A KPI tile while its report loads next to the loaded one, in the `stat-trend` and `mini` templates — `loading`. |
|
|
214
219
|
| [narrow.tsx](examples/narrow.tsx) | The card is a size container: the split template stacks its cells below 22rem and the trend value shrinks below 20rem — `variant`. |
|
|
215
220
|
| [screen.tsx](examples/screen.tsx) | A dashboard: the title and a line of data in the page flow, the period switch and the report in the top bar that keeps the title once it scrolls away; one grid of KPI tiles that cross-fade to the new period, a revenue trend, invoiced against paid beside two panels, and the latest payments with a link to the list — `collapse`, `Page.Grid`. |
|
|
216
221
|
|
|
@@ -225,7 +230,8 @@ No `labels`.
|
|
|
225
230
|
- A clickable `<div>` card with `onClick` → `asChild` with a real `<a href>` (Cmd-click, a new tab) or a `<button>`.
|
|
226
231
|
- Buttons or links inside an `asChild` card → nested interactive elements; move them out of the card.
|
|
227
232
|
- The reference figures written into `Card.Delta` or `Card.Label` → `Card.Meta`.
|
|
233
|
+
- Skeletons placed by hand inside `Card.Value` → `Card.Root loading`; keep the parts mounted while loading so each holds its place.
|
|
228
234
|
|
|
229
235
|
## Related
|
|
230
|
-
- **Built from:**
|
|
236
|
+
- **Built from:** [Skeleton](../skeleton/COMPONENT.md)
|
|
231
237
|
- **See also:** [Page](../../layout/page/COMPONENT.md), [DescriptionList](../description-list/COMPONENT.md) (record details inside a `Card.Body`), [Fieldset](../fieldset/COMPONENT.md) (groups of fields inside a settings card), [DataTable](../data-table/COMPONENT.md), [Badge](../badge/COMPONENT.md), [ProgressBar](../progress-bar/COMPONENT.md), [SegmentedControl](../segmented-control/COMPONENT.md), [Sparkline](../sparkline/COMPONENT.md) (a trend with its total inside a `panel`), [ChartFrame](../chart-frame/COMPONENT.md) (a full chart with legend and states)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/** A KPI tile while its report loads next to the loaded one, in the `stat-trend` and `mini` templates — `loading`. */
|
|
2
|
+
import { Card, Icon, Typography } from "prime-ui-kit";
|
|
3
|
+
|
|
4
|
+
export default function CardStatesExample() {
|
|
5
|
+
return (
|
|
6
|
+
<>
|
|
7
|
+
<div>
|
|
8
|
+
<div>
|
|
9
|
+
<Card.Root variant="stat-trend" loading>
|
|
10
|
+
<Card.Label>Выручка за месяц</Card.Label>
|
|
11
|
+
<Card.Value />
|
|
12
|
+
<Card.Delta />
|
|
13
|
+
<Card.Meta />
|
|
14
|
+
</Card.Root>
|
|
15
|
+
<Typography as="span" variant="caption" tone="muted">
|
|
16
|
+
stat-trend · loading
|
|
17
|
+
</Typography>
|
|
18
|
+
</div>
|
|
19
|
+
<div>
|
|
20
|
+
<Card.Root variant="stat-trend">
|
|
21
|
+
<Card.Label>Выручка за месяц</Card.Label>
|
|
22
|
+
<Card.Value>4,2 млн ₽</Card.Value>
|
|
23
|
+
<Card.Delta tone="success">+18% к сентябрю</Card.Delta>
|
|
24
|
+
<Card.Meta>Лидов 1 240 · сделок 186</Card.Meta>
|
|
25
|
+
</Card.Root>
|
|
26
|
+
<Typography as="span" variant="caption" tone="muted">
|
|
27
|
+
stat-trend
|
|
28
|
+
</Typography>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
<div>
|
|
32
|
+
<div>
|
|
33
|
+
<Card.Root variant="mini" loading>
|
|
34
|
+
<Card.Icon>
|
|
35
|
+
<Icon name="object.users" />
|
|
36
|
+
</Card.Icon>
|
|
37
|
+
<Card.Label>Активные сессии</Card.Label>
|
|
38
|
+
<Card.Value />
|
|
39
|
+
</Card.Root>
|
|
40
|
+
<Typography as="span" variant="caption" tone="muted">
|
|
41
|
+
mini · loading
|
|
42
|
+
</Typography>
|
|
43
|
+
</div>
|
|
44
|
+
<div>
|
|
45
|
+
<Card.Root variant="mini">
|
|
46
|
+
<Card.Icon>
|
|
47
|
+
<Icon name="object.users" />
|
|
48
|
+
</Card.Icon>
|
|
49
|
+
<Card.Label>Активные сессии</Card.Label>
|
|
50
|
+
<Card.Value>1 248</Card.Value>
|
|
51
|
+
</Card.Root>
|
|
52
|
+
<Typography as="span" variant="caption" tone="muted">
|
|
53
|
+
mini
|
|
54
|
+
</Typography>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
</>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
@@ -81,6 +81,7 @@ Chat.Root <div> column, fills its host; owns selection,
|
|
|
81
81
|
- `renderMessage` may be an inline function: an item renders again only when it or its place changes, so whatever a row shows lives in its item (an edit, a reaction, a pin). Another message (a reply's original) comes from `entry.find(key)`.
|
|
82
82
|
- `onRead` reports an incoming message once at least half of it, or half the view, has been on screen while the page is visible (`IntersectionObserver`); batched per frame, each `value` once per mount.
|
|
83
83
|
- One sound at a time on the page: a `VoicePlayer`, a `VideoNote` and a video in `Message.Media` pause each other; nothing to wire.
|
|
84
|
+
- Times in a profile's zone: `timeZone` (an IANA name) on `Chat.Messages` moves the date separators, the runs and every message's time to it; without it they follow the browser.
|
|
84
85
|
|
|
85
86
|
## API
|
|
86
87
|
|
|
@@ -174,7 +175,8 @@ Chat.Root <div> column, fills its host; owns selection,
|
|
|
174
175
|
| `unread` | `string` | — | The key of the first unread item: the «Непрочитанные сообщения» band stands above it. |
|
|
175
176
|
| `groupWindow` | `number` | `5` | Messages of one author further apart than this many minutes start a new run. |
|
|
176
177
|
| `now` | `Date` | today | «Today» for the dates. |
|
|
177
|
-
| `
|
|
178
|
+
| `timeZone` | `string` | the browser's zone | The IANA zone of the date separators, the runs and every message time (`"Asia/Vladivostok"`): a profile's zone, not the browser's. |
|
|
179
|
+
| `formatDate` | `(date: Date, now: Date, timeZone?: string) => string` | `formatMessageDate` | The label of a date; gets the `timeZone`. |
|
|
178
180
|
| `loading` | `boolean` | `false` | The first load: bubble-shaped `Skeleton`s on both sides stand in the list's place (`aria-busy`, `labels.loading` announced), then cross-fade into the messages; none of them counts as new. |
|
|
179
181
|
| `hasOlder` | `boolean` | `false` | Older history exists: a bubble-shaped placeholder stands above the first message and `onLoadOlder` runs when the reader reaches the top. |
|
|
180
182
|
| `onLoadOlder` | `() => void \| Promise<void>` | — | Load older messages and prepend them (while `hasOlder`); the reader's place is kept. |
|
|
@@ -334,6 +336,7 @@ Chat.Root <div> column, fills its host; owns selection,
|
|
|
334
336
|
| [reactions.tsx](examples/reactions.tsx) | A team's own reactions for approvals: a double tap or `L` puts the approval mark, a long press or `R` opens the team's set, and a chip toggles them back — `quickReaction`, `reactionOptions`, `onReactionToggle`. |
|
|
335
337
|
| [live.tsx](examples/live.tsx) | A live support chat: the client types — the header and the end of the list say so — then answers; new messages enter at the end, read receipts come from what is on screen, and scrolled up the round button counts what arrived — `typing`, `onNewMessage`, `onRead`. |
|
|
336
338
|
| [search.tsx](examples/search.tsx) | Search and pinned messages: the search bar marks every match in the texts and transcripts, counts them and steps between them while the others step back; a pinned message's press jumps to it and blinks it — `Chat.SearchButton`, `Chat.Search`, `defaultSearch`, `Chat.Pinned`. |
|
|
339
|
+
| [time-zone.tsx](examples/time-zone.tsx) | The conversation in the zone of the manager's profile, not the browser's: the date separators, the runs and every time follow it — `timeZone`, `items`, `renderMessage`. |
|
|
337
340
|
| [states.tsx](examples/states.tsx) | The first load of a conversation: bubble-shaped placeholders on both sides stand in the list's place, then cross-fade into the messages — `loading`. |
|
|
338
341
|
| [controlled.tsx](examples/controlled.tsx) | Selection mode owned by the screen: the Select item of a message's menu starts it, a check stands beside every message, a press toggles one while the others step back, the bar counts and acts, Escape leaves — `selected`, `onSelectedChange`, `Chat.SelectionBar`. |
|
|
339
342
|
| [narrow.tsx](examples/narrow.tsx) | At phone width the header keeps its actions and lets the title ellipsize, bubbles take up to 85% of the chat, long links wrap and an album keeps its layout — `Chat.Root`, `Chat.Header`, `Chat.Messages`, `Chat.Footer`. |
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/** The conversation in the zone of the manager's profile, not the browser's: the date separators, the runs and every time follow it — `timeZone`, `items`, `renderMessage`. */
|
|
2
|
+
import { Card, Chat, Message, SegmentedControl } from "prime-ui-kit";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
|
|
5
|
+
import styles from "./examples.module.css";
|
|
6
|
+
|
|
7
|
+
const ZONES = [
|
|
8
|
+
{ value: "Europe/Moscow", label: "Москва" },
|
|
9
|
+
{ value: "Asia/Vladivostok", label: "Владивосток" },
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
const NOW = new Date(Date.UTC(2026, 9, 15, 4, 0));
|
|
13
|
+
const utc = (day: number, hour: number, minute: number) =>
|
|
14
|
+
new Date(Date.UTC(2026, 9, day, hour, minute));
|
|
15
|
+
|
|
16
|
+
const MESSAGES = [
|
|
17
|
+
{
|
|
18
|
+
id: "tz-1",
|
|
19
|
+
author: "client",
|
|
20
|
+
sentAt: utc(14, 12, 40),
|
|
21
|
+
text: "Добрый вечер! Машина с заказом № 4821 уже вышла?",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: "tz-2",
|
|
25
|
+
author: "manager",
|
|
26
|
+
sentAt: utc(14, 13, 5),
|
|
27
|
+
text: "Вышла в 18:00, будет у вас завтра до обеда.",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: "tz-3",
|
|
31
|
+
author: "client",
|
|
32
|
+
sentAt: utc(14, 14, 30),
|
|
33
|
+
text: "Спасибо, предупрежу склад.",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: "tz-4",
|
|
37
|
+
author: "manager",
|
|
38
|
+
sentAt: utc(15, 0, 10),
|
|
39
|
+
text: "Водитель на месте, выгрузка через 10 минут.",
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
type ChatMessage = (typeof MESSAGES)[number];
|
|
44
|
+
|
|
45
|
+
export default function ChatTimeZoneExample() {
|
|
46
|
+
const [zone, setZone] = React.useState("Asia/Vladivostok");
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<div className={styles.live}>
|
|
50
|
+
<div className={styles.liveBar}>
|
|
51
|
+
<SegmentedControl.Root value={zone} onValueChange={setZone} aria-label="Пояс профиля">
|
|
52
|
+
{ZONES.map((item) => (
|
|
53
|
+
<SegmentedControl.Item key={item.value} value={item.value}>
|
|
54
|
+
{item.label}
|
|
55
|
+
</SegmentedControl.Item>
|
|
56
|
+
))}
|
|
57
|
+
</SegmentedControl.Root>
|
|
58
|
+
</div>
|
|
59
|
+
<Card.Root className={styles.short}>
|
|
60
|
+
<Chat.Root>
|
|
61
|
+
<Chat.Messages
|
|
62
|
+
aria-label="Переписка по заказу № 4821"
|
|
63
|
+
timeZone={zone}
|
|
64
|
+
now={NOW}
|
|
65
|
+
items={MESSAGES}
|
|
66
|
+
getKey={(message: ChatMessage) => message.id}
|
|
67
|
+
getAuthor={(message: ChatMessage) => message.author}
|
|
68
|
+
getDate={(message: ChatMessage) => message.sentAt}
|
|
69
|
+
renderMessage={(message: ChatMessage) => (
|
|
70
|
+
<Message.Root
|
|
71
|
+
direction={message.author === "manager" ? "outgoing" : "incoming"}
|
|
72
|
+
time={message.sentAt}
|
|
73
|
+
status={message.author === "manager" ? "read" : undefined}
|
|
74
|
+
>
|
|
75
|
+
<Message.Text>{message.text}</Message.Text>
|
|
76
|
+
</Message.Root>
|
|
77
|
+
)}
|
|
78
|
+
/>
|
|
79
|
+
</Chat.Root>
|
|
80
|
+
</Card.Root>
|
|
81
|
+
</div>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
@@ -28,7 +28,7 @@ ChatList.Root <div> column filling its host (container `chat-lis
|
|
|
28
28
|
├─ ScrollContainer the list's own scroller; onReachEnd → onLoadMore while hasMore
|
|
29
29
|
│ └─ Crossfade loading (placeholder List rows) ⇄ empty (EmptyPage compact) ⇄ the list
|
|
30
30
|
│ └─ List.Root <ul> aria-label «Диалоги»; spacer <li aria-hidden> stand for rows out of view
|
|
31
|
-
│ └─ ChatList.Item List.Item <li> + <button> | <a href
|
|
31
|
+
│ └─ ChatList.Item List.Item <li> + <button> | <a href> | your element (asChild); current from value; one Tab stop
|
|
32
32
|
│ ├─ ChatList.ItemIcon before the name: avatar slot (aria-hidden); after it: a glyph
|
|
33
33
|
│ ├─ ChatList.ItemText the name; muted glyph after it
|
|
34
34
|
│ ├─ ChatList.ItemDescription author · media word · text — cross-fades with draft and «печатает…»
|
|
@@ -62,12 +62,13 @@ ChatList.Root <div> column filling its host (container `chat-lis
|
|
|
62
62
|
| `empty` | `ReactNode` | — | The empty state without a search (an `EmptyPage` with an action). Default: «Нет диалогов». |
|
|
63
63
|
| `size` | `"xs" \| "s" \| "m" \| "l" \| "xl"` | host tier, else `"m"` | Row tier: height, text, avatar, glyphs and the search field. Without it the tier of the host. |
|
|
64
64
|
| `now` | `Date` | — | «Now» for the times of the rows. Default: the moment of the render. |
|
|
65
|
-
| `
|
|
65
|
+
| `timeZone` | `string` | the browser's zone | The IANA zone the times of the rows are read in (`"Asia/Vladivostok"`): a profile's zone, not the browser's. |
|
|
66
|
+
| `formatTime` | `(date: Date, now: Date, timeZone?: string) => string` | `formatChatTime` | Display of a row's `Date` time: «14:32» today, «пн» this week, «12 мар», «12.03.2025»; gets the `timeZone`. |
|
|
66
67
|
| `labels` | `Partial<ChatListLabels>` | — | Built-in strings, see Labels. |
|
|
67
68
|
| `…rest` | `HTMLAttributes<HTMLDivElement>` | — | `className` and the other `div` attributes of the column. |
|
|
68
69
|
|
|
69
70
|
### ChatList.Item
|
|
70
|
-
`ref` → `HTMLElement` (the `<button>` or
|
|
71
|
+
`ref` → `HTMLElement` (the `<button>`, `<a>` or `asChild` element, not the `<li>`). A dialog: a `List.Item` row with the avatar, the name and the time over the preview and the counts. Its key and `current` come from the root.
|
|
71
72
|
|
|
72
73
|
| Prop | Type | Default | Description |
|
|
73
74
|
|---|---|---|---|
|
|
@@ -83,7 +84,8 @@ ChatList.Root <div> column filling its host (container `chat-lis
|
|
|
83
84
|
| `href` | `string` | — | Renders an `<a>` instead of a `<button>` (a dialog with its own URL). |
|
|
84
85
|
| `target` | `string` | — | Where the `<a>` opens (`href` only). |
|
|
85
86
|
| `rel` | `string` | — | Relationship of the `<a>` (`href` only). |
|
|
86
|
-
| `
|
|
87
|
+
| `asChild` | `boolean` | `false` | The one child element (a router `Link`) is the row; the parts go inside it. |
|
|
88
|
+
| `children` | `ReactNode` | — | `ChatList.ItemIcon`, `ChatList.ItemText`, `ChatList.ItemDescription`, `ChatList.ItemMenu` — inside the child element with `asChild`. |
|
|
87
89
|
| `…rest` | `ButtonHTMLAttributes<HTMLButtonElement>` | — | `className` and the native attributes of the row element. |
|
|
88
90
|
|
|
89
91
|
### ChatList.ItemIcon
|
|
@@ -150,6 +152,7 @@ The search field takes the tier too; counts are one tier down (the Badge's own r
|
|
|
150
152
|
| `muted` | a muted glyph after the name; the count soft gray | notifications are off | `false` |
|
|
151
153
|
| `mention` | a solid «@» before the count | the reader is mentioned | `false` |
|
|
152
154
|
| `pinned` | a pin under the time while nothing is unread | pinned by the reader — order pinned first in `items` | `false` |
|
|
155
|
+
| `asChild` | the same row, rendered as your one child element with the parts inside it | a router's `Link` opens the dialog without a reload | `false` |
|
|
153
156
|
| `status` | ✓ / ✓✓ in the accent / clock / failure mark before the time | the reader wrote the last message | — |
|
|
154
157
|
|
|
155
158
|
## States
|
|
@@ -195,7 +198,7 @@ Root attribute: `data-size`. Every motion honours reduced motion (durations coll
|
|
|
195
198
|
### ARIA
|
|
196
199
|
<!-- Generated from api.ts by `bun run docs:build`. Edit api.ts, not this section. -->
|
|
197
200
|
|
|
198
|
-
- The list is a `<ul>` named «Диалоги» (`labels.list`); each row an `<li>` with a button, or
|
|
201
|
+
- The list is a `<ul>` named «Диалоги» (`labels.list`); each row an `<li>` with a button, a link with `href`, or your link with `asChild`.
|
|
199
202
|
- The open dialog is `aria-current="true"` on a button, `"page"` on a link. Selection does not follow the focus: arrows only move it (a dialog may load a conversation); Enter, Space and a click open.
|
|
200
203
|
- The row is named by its content: the name, glyphs with a `label` («Без звука», a verified mark), the preview, the delivery mark («Прочитано»), the time, then «упоминание» and «непрочитанных: 3» instead of the bare badges; the avatar is `aria-hidden`.
|
|
201
204
|
- While the other side types, the preview is `aria-hidden` and «печатает…» is read; a draft reads «Черновик: …».
|
|
@@ -243,7 +246,8 @@ Root attribute: `data-size`. Every motion honours reduced motion (durations coll
|
|
|
243
246
|
| [search.tsx](examples/search.tsx) | The search field filters dialogs by name and by the last message, marks the match in both, says how many were found and shows a quiet state when none match — `defaultSearch`, `onSearchChange`. |
|
|
244
247
|
| [live.tsx](examples/live.tsx) | A live inbox: a client types, then writes — the preview turns into the typing line and back, the count rolls up and the dialog glides to the top; opening it clears the count — `typing`, `unread`, `items`. |
|
|
245
248
|
| [long-list.tsx](examples/long-list.tsx) | A sales inbox of a thousand dialogs: only the rows around the view render, arrows walk through all of them, and the next page loads as the end comes near — `hasMore`, `onLoadMore`. |
|
|
246
|
-
| [links.tsx](examples/links.tsx) | Dialogs with their own address: every row is a link the
|
|
249
|
+
| [links.tsx](examples/links.tsx) | Dialogs with their own address: every row is a link to the ticket's page, the time reads as how long ago, and the list is named for its queue — `href`, `formatTime`, `labels`. |
|
|
250
|
+
| [router.tsx](examples/router.tsx) | Router links as the dialogs, the times in the zone of the operator's profile; render it inside a router — `asChild`, `timeZone`. |
|
|
247
251
|
| [states.tsx](examples/states.tsx) | Loading and empty: placeholder rows in the rows' geometry cross-fade into the dialogs; a new workspace without dialogs shows its own empty state with an action — `loading`, `empty`. |
|
|
248
252
|
| [controlled.tsx](examples/controlled.tsx) | The open dialog lives in the screen: a row opens it beside the list, and a next-unread button opens the next one from outside — `value`, `onValueChange`. |
|
|
249
253
|
| [narrow.tsx](examples/narrow.tsx) | At phone width long names and previews truncate while the time and counts stay whole; a pane squeezed under 240px keeps only the names and the counts — `ChatList.Root`, `search`. |
|
|
@@ -256,6 +260,8 @@ Root attribute: `data-size`. Every motion honours reduced motion (durations coll
|
|
|
256
260
|
- An `Avatar.Root size="s"` to fit the row → leave `size` out; the slot sizes the avatar to the tier.
|
|
257
261
|
- A «⋯» button nested inside the row for the menu → `ChatList.ItemMenu`: it opens on right click, a long press and Shift+F10.
|
|
258
262
|
- Deleting from the menu without a question → open a `ConfirmDialog` from the menu item.
|
|
263
|
+
- `href` with an `onClick` that calls `preventDefault()` and the router's `navigate` → `asChild` with the router's `Link`, the parts inside it.
|
|
264
|
+
- Times shifted by hand to a profile's zone before `time` → `timeZone` on the root: «сегодня», the weekday and the clock are read in it.
|
|
259
265
|
|
|
260
266
|
## Related
|
|
261
267
|
- **Built from:** [List](../list/COMPONENT.md) (rows, current fill, focus, touch height), [Input](../input/COMPONENT.md) (search), [ScrollContainer](../scroll-container/COMPONENT.md), [Crossfade](../crossfade/COMPONENT.md), [Skeleton](../skeleton/COMPONENT.md), [EmptyPage](../empty-page/COMPONENT.md), [Badge](../badge/COMPONENT.md) (counts), [Dropdown](../dropdown/COMPONENT.md) (row menu), [VisuallyHidden](../visually-hidden/COMPONENT.md), `useFlipList` (the glide of a new order)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Dialogs with their own address: every row is a link the
|
|
1
|
+
/** Dialogs with their own address: every row is a link to the ticket's page, the time reads as how long ago, and the list is named for its queue — `href`, `formatTime`, `labels`. */
|
|
2
2
|
import { Avatar, Card, ChatList, hueOf } from "prime-ui-kit";
|
|
3
3
|
|
|
4
4
|
import styles from "./examples.module.css";
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/** Router links as the dialogs, the times in the zone of the operator's profile; render it inside a router — `asChild`, `timeZone`. */
|
|
2
|
+
import { Avatar, Card, ChatList, hueOf } from "prime-ui-kit";
|
|
3
|
+
import { Link } from "react-router-dom";
|
|
4
|
+
|
|
5
|
+
import styles from "./examples.module.css";
|
|
6
|
+
|
|
7
|
+
const NOW = new Date(Date.UTC(2026, 9, 15, 4, 0));
|
|
8
|
+
const utc = (day: number, hour: number, minute: number) =>
|
|
9
|
+
new Date(Date.UTC(2026, 9, day, hour, minute));
|
|
10
|
+
|
|
11
|
+
const DIALOGS = [
|
|
12
|
+
{
|
|
13
|
+
id: "c-311",
|
|
14
|
+
name: "ООО «Вектор»",
|
|
15
|
+
initials: "ВК",
|
|
16
|
+
preview: "Машина на месте, начинаем выгрузку",
|
|
17
|
+
at: utc(15, 0, 10),
|
|
18
|
+
unread: 1,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
id: "c-308",
|
|
22
|
+
name: "ООО «Гранит»",
|
|
23
|
+
initials: "ГР",
|
|
24
|
+
preview: "Счёт № 2041 оплачен",
|
|
25
|
+
at: utc(14, 14, 30),
|
|
26
|
+
unread: 0,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: "c-297",
|
|
30
|
+
name: "ИП Козлов",
|
|
31
|
+
initials: "ИК",
|
|
32
|
+
preview: "Пришлите, пожалуйста, акт сверки",
|
|
33
|
+
at: utc(12, 6, 15),
|
|
34
|
+
unread: 0,
|
|
35
|
+
},
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
export default function ChatListRouterExample() {
|
|
39
|
+
return (
|
|
40
|
+
<Card.Root className={styles.short}>
|
|
41
|
+
<ChatList.Root
|
|
42
|
+
items={DIALOGS}
|
|
43
|
+
getKey={(item) => item.id}
|
|
44
|
+
defaultValue="c-311"
|
|
45
|
+
now={NOW}
|
|
46
|
+
timeZone="Asia/Vladivostok"
|
|
47
|
+
renderItem={(item) => (
|
|
48
|
+
<ChatList.Item asChild time={item.at} unread={item.unread}>
|
|
49
|
+
<Link to={`/chats/${item.id}`}>
|
|
50
|
+
<ChatList.ItemIcon>
|
|
51
|
+
<Avatar.Root color={hueOf(item.id)}>
|
|
52
|
+
<Avatar.Fallback>{item.initials}</Avatar.Fallback>
|
|
53
|
+
</Avatar.Root>
|
|
54
|
+
</ChatList.ItemIcon>
|
|
55
|
+
<ChatList.ItemText>{item.name}</ChatList.ItemText>
|
|
56
|
+
<ChatList.ItemDescription>{item.preview}</ChatList.ItemDescription>
|
|
57
|
+
</Link>
|
|
58
|
+
</ChatList.Item>
|
|
59
|
+
)}
|
|
60
|
+
/>
|
|
61
|
+
</Card.Root>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
@@ -50,6 +50,7 @@ Checkbox.Indicator the box alone, no input — a mark inside option / menu r
|
|
|
50
50
|
| `optional` | `boolean` | `false` | Muted `labels.optional` after the label text; the field may stay off. |
|
|
51
51
|
| `labels` | `Partial<CheckboxLabels>` | — | Built-in strings, see Labels. |
|
|
52
52
|
| `hint` | `ReactNode` | — | Help text under the label text. Hidden while `error` is shown. |
|
|
53
|
+
| `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. |
|
|
53
54
|
| `error` | `ReactNode` | — | Error message in the hint slot; implies `invalid`. |
|
|
54
55
|
| `invalid` | `boolean` | `false` | Danger ring on the unchecked box and `aria-invalid`. A non-empty `error` implies it. |
|
|
55
56
|
| `disabled` | `boolean` | `false` | Disabled fill, dimmed label and hint, no toggling. |
|
|
@@ -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
|
|