@acronis-platform/ui-react 2.0.0 → 4.0.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.
Files changed (243) hide show
  1. package/dist/components/ui/accordion-container/accordion-container.js +144 -0
  2. package/dist/components/ui/accordion-container/accordion-container.js.map +1 -0
  3. package/dist/components/ui/app-shell-chat/app-shell-chat.js.map +1 -1
  4. package/dist/components/ui/area-chart/area-chart.js +141 -139
  5. package/dist/components/ui/area-chart/area-chart.js.map +1 -1
  6. package/dist/components/ui/avatar/avatar.js +33 -22
  7. package/dist/components/ui/avatar/avatar.js.map +1 -1
  8. package/dist/components/ui/bar-chart/bar-chart.js +295 -293
  9. package/dist/components/ui/bar-chart/bar-chart.js.map +1 -1
  10. package/dist/components/ui/card/card.js +150 -74
  11. package/dist/components/ui/card/card.js.map +1 -1
  12. package/dist/components/ui/card-section/card-section.js +111 -0
  13. package/dist/components/ui/card-section/card-section.js.map +1 -0
  14. package/dist/components/ui/category-bar/category-bar.js +109 -93
  15. package/dist/components/ui/category-bar/category-bar.js.map +1 -1
  16. package/dist/components/ui/chart/chart-palette.js +113 -0
  17. package/dist/components/ui/chart/chart-palette.js.map +1 -0
  18. package/dist/components/ui/chart/chart.js +176 -129
  19. package/dist/components/ui/chart/chart.js.map +1 -1
  20. package/dist/components/ui/chart-state/chart-state-illustrations.js +310 -0
  21. package/dist/components/ui/chart-state/chart-state-illustrations.js.map +1 -0
  22. package/dist/components/ui/chart-state/chart-state.js +48 -34
  23. package/dist/components/ui/chart-state/chart-state.js.map +1 -1
  24. package/dist/components/ui/chart-widget/chart-widget.js +87 -0
  25. package/dist/components/ui/chart-widget/chart-widget.js.map +1 -0
  26. package/dist/components/ui/composed-chart/composed-chart.js +117 -115
  27. package/dist/components/ui/composed-chart/composed-chart.js.map +1 -1
  28. package/dist/components/ui/confidence-cone/confidence-cone.js +166 -158
  29. package/dist/components/ui/confidence-cone/confidence-cone.js.map +1 -1
  30. package/dist/components/ui/data-table/data-table.js +4 -2
  31. package/dist/components/ui/data-table/data-table.js.map +1 -1
  32. package/dist/components/ui/empty-overlay/empty-overlay.js +49 -0
  33. package/dist/components/ui/empty-overlay/empty-overlay.js.map +1 -0
  34. package/dist/components/ui/funnel-chart/funnel-chart.js +162 -161
  35. package/dist/components/ui/funnel-chart/funnel-chart.js.map +1 -1
  36. package/dist/components/ui/histogram/histogram.js +94 -92
  37. package/dist/components/ui/histogram/histogram.js.map +1 -1
  38. package/dist/components/ui/input/input.js.map +1 -1
  39. package/dist/components/ui/label/label.js +2 -9
  40. package/dist/components/ui/label/label.js.map +1 -1
  41. package/dist/components/ui/line-chart/line-chart.js +143 -141
  42. package/dist/components/ui/line-chart/line-chart.js.map +1 -1
  43. package/dist/components/ui/metric/metric.js +74 -185
  44. package/dist/components/ui/metric/metric.js.map +1 -1
  45. package/dist/components/ui/page-content/page-content.js.map +1 -1
  46. package/dist/components/ui/pie-chart/pie-chart.js +201 -195
  47. package/dist/components/ui/pie-chart/pie-chart.js.map +1 -1
  48. package/dist/components/ui/radar-chart/radar-chart.js +133 -131
  49. package/dist/components/ui/radar-chart/radar-chart.js.map +1 -1
  50. package/dist/components/ui/radial-bar-chart/radial-bar-chart.js +297 -265
  51. package/dist/components/ui/radial-bar-chart/radial-bar-chart.js.map +1 -1
  52. package/dist/components/ui/sankey-chart/sankey-chart.js +123 -101
  53. package/dist/components/ui/sankey-chart/sankey-chart.js.map +1 -1
  54. package/dist/components/ui/scatter-chart/scatter-chart.js +76 -74
  55. package/dist/components/ui/scatter-chart/scatter-chart.js.map +1 -1
  56. package/dist/components/ui/section/section.js +157 -31
  57. package/dist/components/ui/section/section.js.map +1 -1
  58. package/dist/components/ui/stepper/stepper.js +24 -24
  59. package/dist/components/ui/stepper/stepper.js.map +1 -1
  60. package/dist/components/ui/stepper-item/stepper-item.js +43 -24
  61. package/dist/components/ui/stepper-item/stepper-item.js.map +1 -1
  62. package/dist/components/ui/table/table.js +27 -27
  63. package/dist/components/ui/table/table.js.map +1 -1
  64. package/dist/components/ui/treemap/treemap.js +133 -124
  65. package/dist/components/ui/treemap/treemap.js.map +1 -1
  66. package/dist/components/ui/trend-indicator/trend-indicator.js +34 -69
  67. package/dist/components/ui/trend-indicator/trend-indicator.js.map +1 -1
  68. package/dist/components/ui/wizard/wizard.js +59 -0
  69. package/dist/components/ui/wizard/wizard.js.map +1 -0
  70. package/dist/hooks/use-wizard.js +75 -0
  71. package/dist/hooks/use-wizard.js.map +1 -0
  72. package/dist/index.js +540 -525
  73. package/dist/index.js.map +1 -1
  74. package/dist/llms/accordion-container.md +181 -0
  75. package/dist/llms/accordion.md +124 -0
  76. package/dist/llms/alert.md +225 -0
  77. package/dist/llms/app-shell-chat.md +415 -0
  78. package/dist/llms/area-chart.md +355 -0
  79. package/dist/llms/avatar.md +208 -0
  80. package/dist/llms/bar-chart.md +406 -0
  81. package/dist/llms/breadcrumb.md +326 -0
  82. package/dist/llms/button-group.md +298 -0
  83. package/dist/llms/button-icon-input.md +142 -0
  84. package/dist/llms/button-icon-menu.md +209 -0
  85. package/dist/llms/button-icon.md +128 -0
  86. package/dist/llms/button-menu.md +172 -0
  87. package/dist/llms/button.md +185 -0
  88. package/dist/llms/calendar-panel.md +733 -0
  89. package/dist/llms/calendar.md +188 -0
  90. package/dist/llms/card-filter.md +214 -0
  91. package/dist/llms/card-section.md +293 -0
  92. package/dist/llms/card.md +447 -0
  93. package/dist/llms/carousel-dialog.md +156 -0
  94. package/dist/llms/category-bar.md +193 -0
  95. package/dist/llms/chart-state.md +190 -0
  96. package/dist/llms/chart-widget.md +209 -0
  97. package/dist/llms/chart.md +182 -0
  98. package/dist/llms/checkbox.md +257 -0
  99. package/dist/llms/chip.md +195 -0
  100. package/dist/llms/combobox.md +164 -0
  101. package/dist/llms/composed-chart.md +508 -0
  102. package/dist/llms/confidence-cone.md +277 -0
  103. package/dist/llms/data-table.md +474 -0
  104. package/dist/llms/date-range-picker.md +272 -0
  105. package/dist/llms/description-list.md +131 -0
  106. package/dist/llms/dialog-footer-carousel.md +147 -0
  107. package/dist/llms/dialog-footer-default.md +142 -0
  108. package/dist/llms/dialog-root.md +246 -0
  109. package/dist/llms/dialog-welcome.md +223 -0
  110. package/dist/llms/dialog.md +403 -0
  111. package/dist/llms/dropdown-menu.md +193 -0
  112. package/dist/llms/empty-overlay.md +146 -0
  113. package/dist/llms/empty.md +156 -0
  114. package/dist/llms/field.md +185 -0
  115. package/dist/llms/filter-cards.md +157 -0
  116. package/dist/llms/filter-chips.md +323 -0
  117. package/dist/llms/filter-search.md +512 -0
  118. package/dist/llms/form.md +154 -0
  119. package/dist/llms/funnel-chart.md +333 -0
  120. package/dist/llms/grid.md +80 -0
  121. package/dist/llms/histogram.md +190 -0
  122. package/dist/llms/input-date-picker.md +203 -0
  123. package/dist/llms/input-otp.md +173 -0
  124. package/dist/llms/input-password.md +197 -0
  125. package/dist/llms/input-search.md +170 -0
  126. package/dist/llms/input-select.md +278 -0
  127. package/dist/llms/input-text-area.md +271 -0
  128. package/dist/llms/input-text.md +192 -0
  129. package/dist/llms/line-chart.md +369 -0
  130. package/dist/llms/link.md +209 -0
  131. package/dist/llms/loading.md +130 -0
  132. package/dist/llms/meter.md +177 -0
  133. package/dist/llms/metric.md +204 -0
  134. package/dist/llms/number-field.md +122 -0
  135. package/dist/llms/page-content.md +69 -0
  136. package/dist/llms/page-header.md +182 -0
  137. package/dist/llms/pagination.md +133 -0
  138. package/dist/llms/pie-chart.md +307 -0
  139. package/dist/llms/popover.md +252 -0
  140. package/dist/llms/progress-circle.md +126 -0
  141. package/dist/llms/progress.md +111 -0
  142. package/dist/llms/radar-chart.md +316 -0
  143. package/dist/llms/radial-bar-chart.md +319 -0
  144. package/dist/llms/radio.md +255 -0
  145. package/dist/llms/resizable.md +195 -0
  146. package/dist/llms/sankey-chart.md +208 -0
  147. package/dist/llms/scatter-chart.md +239 -0
  148. package/dist/llms/scroll-area.md +183 -0
  149. package/dist/llms/section.md +401 -0
  150. package/dist/llms/select.md +210 -0
  151. package/dist/llms/separator.md +87 -0
  152. package/dist/llms/sheet.md +202 -0
  153. package/dist/llms/sidebar-primary.md +360 -0
  154. package/dist/llms/sidebar-secondary.md +417 -0
  155. package/dist/llms/skeleton.md +81 -0
  156. package/dist/llms/slider.md +97 -0
  157. package/dist/llms/spinner.md +100 -0
  158. package/dist/llms/stack.md +80 -0
  159. package/dist/llms/stepper-item.md +309 -0
  160. package/dist/llms/stepper.md +251 -0
  161. package/dist/llms/switch.md +140 -0
  162. package/dist/llms/table.md +436 -0
  163. package/dist/llms/tabs.md +197 -0
  164. package/dist/llms/tag.md +139 -0
  165. package/dist/llms/timeline.md +361 -0
  166. package/dist/llms/timer.md +259 -0
  167. package/dist/llms/toast.md +241 -0
  168. package/dist/llms/toggle-group.md +121 -0
  169. package/dist/llms/toolbar.md +453 -0
  170. package/dist/llms/tooltip.md +164 -0
  171. package/dist/llms/treemap.md +254 -0
  172. package/dist/llms/trend-indicator.md +132 -0
  173. package/dist/llms/widget-placeholder.md +169 -0
  174. package/dist/llms/wizard.md +412 -0
  175. package/dist/llms.txt +142 -0
  176. package/dist/react.js +540 -525
  177. package/dist/react.js.map +1 -1
  178. package/dist/src/components/ui/accordion-container/accordion-container.d.ts +44 -0
  179. package/dist/src/components/ui/accordion-container/index.d.ts +1 -0
  180. package/dist/src/components/ui/area-chart/area-chart.d.ts +9 -4
  181. package/dist/src/components/ui/avatar/avatar.d.ts +27 -8
  182. package/dist/src/components/ui/bar-chart/bar-chart.d.ts +9 -4
  183. package/dist/src/components/ui/button/button.d.ts +1 -1
  184. package/dist/src/components/ui/card/card.d.ts +69 -8
  185. package/dist/src/components/ui/card/index.d.ts +1 -1
  186. package/dist/src/components/ui/card-section/card-section.d.ts +50 -0
  187. package/dist/src/components/ui/card-section/index.d.ts +1 -0
  188. package/dist/src/components/ui/category-bar/category-bar.d.ts +10 -4
  189. package/dist/src/components/ui/chart/__stories__/palette-control.d.ts +48 -0
  190. package/dist/src/components/ui/chart/__tests__/chart-palette.test.d.ts +1 -0
  191. package/dist/src/components/ui/chart/chart-palette.d.ts +128 -0
  192. package/dist/src/components/ui/chart/chart.d.ts +66 -15
  193. package/dist/src/components/ui/chart/index.d.ts +4 -2
  194. package/dist/src/components/ui/chart-state/chart-state-illustrations.d.ts +6 -0
  195. package/dist/src/components/ui/chart-state/chart-state.d.ts +13 -2
  196. package/dist/src/components/ui/chart-state/index.d.ts +1 -0
  197. package/dist/src/components/ui/chart-widget/chart-widget.d.ts +64 -0
  198. package/dist/src/components/ui/chart-widget/index.d.ts +1 -0
  199. package/dist/src/components/ui/composed-chart/composed-chart.d.ts +12 -7
  200. package/dist/src/components/ui/confidence-cone/confidence-cone.d.ts +10 -5
  201. package/dist/src/components/ui/dialog/dialog.d.ts +1 -1
  202. package/dist/src/components/ui/empty-overlay/empty-overlay.d.ts +20 -0
  203. package/dist/src/components/ui/empty-overlay/index.d.ts +2 -0
  204. package/dist/src/components/ui/funnel-chart/funnel-chart.d.ts +11 -5
  205. package/dist/src/components/ui/grid/grid.d.ts +1 -1
  206. package/dist/src/components/ui/histogram/histogram.d.ts +10 -4
  207. package/dist/src/components/ui/label/index.d.ts +1 -1
  208. package/dist/src/components/ui/label/label.d.ts +1 -5
  209. package/dist/src/components/ui/line-chart/line-chart.d.ts +9 -4
  210. package/dist/src/components/ui/metric/metric.d.ts +13 -14
  211. package/dist/src/components/ui/pie-chart/pie-chart.d.ts +17 -8
  212. package/dist/src/components/ui/radar-chart/radar-chart.d.ts +10 -5
  213. package/dist/src/components/ui/radial-bar-chart/radial-bar-chart.d.ts +17 -6
  214. package/dist/src/components/ui/sankey-chart/sankey-chart.d.ts +10 -5
  215. package/dist/src/components/ui/scatter-chart/scatter-chart.d.ts +10 -5
  216. package/dist/src/components/ui/section/index.d.ts +1 -1
  217. package/dist/src/components/ui/section/section.d.ts +75 -6
  218. package/dist/src/components/ui/sheet/sheet.d.ts +1 -1
  219. package/dist/src/components/ui/stack/stack.d.ts +1 -1
  220. package/dist/src/components/ui/stepper-item/stepper-item.d.ts +6 -5
  221. package/dist/src/components/ui/tag/tag.d.ts +1 -1
  222. package/dist/src/components/ui/treemap/treemap.d.ts +11 -5
  223. package/dist/src/components/ui/trend-indicator/trend-indicator.d.ts +3 -7
  224. package/dist/src/components/ui/wizard/index.d.ts +1 -0
  225. package/dist/src/components/ui/wizard/wizard.d.ts +6 -0
  226. package/dist/src/hooks/index.d.ts +1 -0
  227. package/dist/src/hooks/use-wizard.d.ts +80 -0
  228. package/dist/src/index.d.ts +5 -3
  229. package/dist/ui-react.css +1 -1
  230. package/package.json +12 -6
  231. package/dist/components/ui/app-shell/app-shell.js +0 -75
  232. package/dist/components/ui/app-shell/app-shell.js.map +0 -1
  233. package/dist/components/ui/auth-layout/auth-layout.js +0 -56
  234. package/dist/components/ui/auth-layout/auth-layout.js.map +0 -1
  235. package/dist/components/ui/collapsible/collapsible.js +0 -22
  236. package/dist/components/ui/collapsible/collapsible.js.map +0 -1
  237. package/dist/src/components/ui/app-shell/app-shell.d.ts +0 -8
  238. package/dist/src/components/ui/app-shell/index.d.ts +0 -1
  239. package/dist/src/components/ui/auth-layout/auth-layout.d.ts +0 -6
  240. package/dist/src/components/ui/auth-layout/index.d.ts +0 -1
  241. package/dist/src/components/ui/collapsible/collapsible.d.ts +0 -5
  242. package/dist/src/components/ui/collapsible/index.d.ts +0 -1
  243. package/dist/src/components/ui/label/label.docs.d.ts +0 -10
@@ -0,0 +1,447 @@
1
+ # Card
2
+
3
+ > A surface that groups related content and actions. A set of composable parts (header, content, footer) on a bordered, rounded container. The header carries the interactive surface: an optional drag handle, toggle switch, avatar, rename button, extras, end-aligned actions, and an optional collapse trigger. Collapsibility is composed by wrapping the header and content/footer in `AccordionContainer`.
4
+
5
+ **Status:** ready · **Category:** layout · **Since:** v0.8.0
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { Card, CardHeader, CardContent, CardFooter } from '@acronis-platform/ui-react'
11
+ ```
12
+
13
+ ## Quick example
14
+
15
+ ```tsx
16
+ <Card>
17
+ <CardHeader title="Backup status" description="Last run 5 minutes ago" hasDescription />
18
+ <CardContent>All workloads protected.</CardContent>
19
+ <CardFooter>
20
+ <Button>View report</Button>
21
+ </CardFooter>
22
+ </Card>
23
+
24
+ // Collapsible: compose with AccordionContainer, and set
25
+ // CardHeader's isCollapsible to render the trigger.
26
+ <Card>
27
+ <AccordionContainer collapsible defaultOpen>
28
+ <CardHeader title="Backup policy" isCollapsible />
29
+ <AccordionContainer.Content>
30
+ <CardContent>Applies to 12 workloads.</CardContent>
31
+ <CardFooter>
32
+ <Button>Save</Button>
33
+ </CardFooter>
34
+ </AccordionContainer.Content>
35
+ </AccordionContainer>
36
+ </Card>
37
+ ```
38
+
39
+ A surface that groups related content and actions into a bordered, rounded
40
+ container. Composable from parts (`Card`, `CardHeader`, `CardContent`,
41
+ `CardFooter`); the header carries a rich, Figma-driven feature set.
42
+
43
+ > Figma node: `10012-195993`. The design's `isCollapsable` variant
44
+ > (expanded/collapsed) is implemented by composing `Card` with
45
+ > `AccordionContainer` — see "Collapsible" below.
46
+
47
+ ## When to use
48
+
49
+ - Grouping related information into a self-contained block (a stat, a
50
+ summary, a settings group, a reorderable list item).
51
+ - A header that needs any combination of: a drag handle (reorderable lists), a
52
+ toggle switch, an avatar, a title with an optional rename affordance, extra
53
+ inline content (tags/badges), and end-aligned actions (e.g. a menu button).
54
+ - Nesting cards (a "main" card containing one or more "secondary" cards as
55
+ content) — `Card` is the same component in both roles; there is no separate
56
+ primary/secondary variant.
57
+
58
+ ## When not to use
59
+
60
+ - For a compact single-stat tile with built-in variants, use **`CardFilter`**
61
+ instead.
62
+ - As a generic layout `<div>` with no visual surface — just use a styled
63
+ element.
64
+ - For modal/overlay surfaces — use the dialog/popover components.
65
+
66
+ ## Parts
67
+
68
+ | Part | Element (default) | Purpose |
69
+ | ------------- | ----------------- | ---------------------------------------------------------------------------------- |
70
+ | `Card` | `div` | The card surface (border, radius); `hasError` swaps the border to the error token. |
71
+ | `CardHeader` | `div` | Title/description + drag handle, switch, avatar, rename, extras, actions. |
72
+ | `CardContent` | `div` | Primary body region for arbitrary children. |
73
+ | `CardFooter` | `div` | Bottom region; horizontal action row. |
74
+
75
+ `Card` and `CardContent` accept a `render` prop for polymorphic composition.
76
+
77
+ ## Example
78
+
79
+ ```tsx
80
+ import {
81
+ Button,
82
+ Card,
83
+ CardContent,
84
+ CardFooter,
85
+ CardHeader,
86
+ } from '@acronis-platform/ui-react';
87
+
88
+ <Card className="w-[350px]">
89
+ <CardHeader
90
+ title="Backup status"
91
+ description="Last successful run 5 minutes ago."
92
+ hasDescription
93
+ />
94
+ <CardContent>All 24 workloads are protected.</CardContent>
95
+ <CardFooter className="gap-2">
96
+ <Button>View report</Button>
97
+ <Button variant="secondary">Run now</Button>
98
+ </CardFooter>
99
+ </Card>;
100
+ ```
101
+
102
+ ## Header features
103
+
104
+ ```tsx
105
+ <CardHeader
106
+ title="Backup policy"
107
+ isDraggable
108
+ isSwitchable
109
+ defaultSwitchChecked
110
+ hasAvatar
111
+ avatarLabel="SB"
112
+ hasRename
113
+ onRename={() => setRenaming(true)}
114
+ extras={<Badge>Beta</Badge>}
115
+ actions={
116
+ <ButtonIcon aria-label="More actions">
117
+ <EllipsisIcon size={24} />
118
+ </ButtonIcon>
119
+ }
120
+ />
121
+ ```
122
+
123
+ - `isDraggable` shows a grip handle for reorderable lists — wire your own
124
+ drag library (e.g. `@dnd-kit/sortable`) onto the header or handle.
125
+ - `isSwitchable` renders a real `Switch`; control it with `switchChecked` /
126
+ `defaultSwitchChecked` / `onSwitchCheckedChange`.
127
+ - `hasAvatar` defaults to an initials avatar (`avatarLabel`); pass `avatar`
128
+ to render a custom node (e.g. an image avatar) instead.
129
+ - `hasRename` renders a pencil icon button; wire `onRename` to open your own
130
+ rename UI (an inline input, a dialog, …) — Card does not manage rename
131
+ state itself.
132
+ - `hasError` (on `Card`, not `CardHeader`) only swaps the root border color.
133
+
134
+ ## Collapsible
135
+
136
+ Compose `Card` with `AccordionContainer` (the shared disclosure primitive):
137
+ wrap `CardContent`/`CardFooter` in `AccordionContainer.Content` and set
138
+ `CardHeader`'s `isCollapsible` to render the trigger — restyled to match the
139
+ Figma design's ghost `ButtonIcon` chrome rather than `AccordionContainer`'s
140
+ own neutral default.
141
+
142
+ ```tsx
143
+ import {
144
+ AccordionContainer,
145
+ Card,
146
+ CardContent,
147
+ CardFooter,
148
+ CardHeader,
149
+ } from '@acronis-platform/ui-react';
150
+
151
+ <Card className="w-[420px]">
152
+ <AccordionContainer collapsible defaultOpen>
153
+ <CardHeader
154
+ title="Backup policy"
155
+ description="Applies to 12 workloads."
156
+ hasDescription
157
+ isCollapsible
158
+ collapseLabel="Toggle backup policy"
159
+ />
160
+ <AccordionContainer.Content>
161
+ <CardContent>All 24 workloads are protected and up to date.</CardContent>
162
+ <CardFooter className="gap-2">
163
+ <Button>Save</Button>
164
+ <Button variant="secondary">Cancel</Button>
165
+ </CardFooter>
166
+ </AccordionContainer.Content>
167
+ </AccordionContainer>
168
+ </Card>;
169
+ ```
170
+
171
+ - `isCollapsible` on `CardHeader` only has an effect when the header renders
172
+ inside a collapsible `AccordionContainer` — it's a no-op otherwise.
173
+ - The header itself (title, drag handle, switch, avatar, actions, …) stays
174
+ visible in both the open and closed state; only content wrapped in
175
+ `AccordionContainer.Content` is hidden when closed.
176
+
177
+ ## Props
178
+
179
+ | Prop | Type | Default | Required | Description |
180
+ |------|------|---------|----------|-------------|
181
+ | `hasError` | `boolean` | `false` | no | Switches the root border to the error token. Set on the root (`Card`), not the header. |
182
+ | `render` | `RenderProp` | `undefined` | no | Base UI composition prop available on the root and every part — replaces the rendered element with another component (e.g. render the root as `<article>`) while merging props and classes. React-only; other frameworks use their own polymorphism. |
183
+ | `header.title` | `string` | `undefined` | no | The card's title text. Renders nothing when omitted. |
184
+ | `header.description` | `string` | `undefined` | no | Helper text shown under the title; only rendered when `header.hasDescription` is set. |
185
+ | `header.hasDescription` | `boolean` | `false` | no | Shows `header.description` below the title. |
186
+ | `header.isDraggable` | `boolean` | `false` | no | Shows a drag handle at the start of the header, for reorderable lists. |
187
+ | `header.dragHandleLabel` | `string` | `Reorder` | no | Accessible label for the drag handle. |
188
+ | `header.isSwitchable` | `boolean` | `false` | no | Shows a toggle switch at the start of the header. |
189
+ | `header.switchChecked` | `boolean` | `undefined` | no | Controlled checked state of the header switch. |
190
+ | `header.defaultSwitchChecked` | `boolean` | `undefined` | no | Uncontrolled initial checked state of the header switch. |
191
+ | `header.switchDisabled` | `boolean` | `undefined` | no | Disables the header switch. |
192
+ | `header.switchLabel` | `string` | `Toggle card` | no | Accessible label for the header switch. |
193
+ | `header.hasAvatar` | `boolean` | `false` | no | Shows an avatar before the title. |
194
+ | `header.avatarLabel` | `string` | `` | no | Initials shown in the default avatar; ignored if `header.avatar` is provided. |
195
+ | `header.avatar` | `ReactNode` | `undefined` | no | Replaces the default initials avatar with custom content. |
196
+ | `header.hasRename` | `boolean` | `false` | no | Shows a rename button next to the title. |
197
+ | `header.renameLabel` | `string` | `Rename` | no | Accessible label for the rename button. |
198
+ | `header.extras` | `ReactNode` | `undefined` | no | Extra content rendered inline next to the title (e.g. a tag or badge). |
199
+ | `header.actions` | `ReactNode` | `undefined` | no | Actions rendered at the end of the header (e.g. a menu button). |
200
+ | `header.isCollapsible` | `boolean` | `false` | no | Shows a disclosure trigger at the end of the header. Only has an effect when the header renders inside a collapsible `AccordionContainer` — see the collapsible composition example. |
201
+ | `header.collapseLabel` | `string` | `Collapse card` | no | Accessible label for the collapse trigger. |
202
+
203
+ ## Events
204
+
205
+ | Event | Payload | Description |
206
+ |-------|---------|-------------|
207
+ | `header.onSwitchCheckedChange` | `undefined` | Fires when the header switch is toggled. |
208
+ | `header.onRename` | `undefined` | Fires when the rename button is activated. |
209
+
210
+ ## Content slots
211
+
212
+ | Slot | Description |
213
+ |------|-------------|
214
+ | `default` | The composed card. Author it from the parts: an optional header (title, description, drag handle, switch, avatar, rename, extras, actions), a content region, and an optional footer for actions. All parts are optional and may be used in any combination. |
215
+
216
+ ## Behavior
217
+
218
+ Card is a compound component: `Card` (root) + `CardHeader` + `CardContent` +
219
+ `CardFooter`. Any part may be omitted; the root has no minimum composition.
220
+ `CardHeader` owns most of the interactive surface described below.
221
+
222
+ ### Composition
223
+
224
+ ```gherkin
225
+ Scenario: A fully composed card
226
+ Given a Card wrapping a CardHeader, a CardContent, and a CardFooter
227
+ When the card renders
228
+ Then the header, content, and footer appear in source order
229
+ And the root carries the rounded border and surface background
230
+ ```
231
+
232
+ ```gherkin
233
+ Scenario: Parts are optional
234
+ Given a Card wrapping only a CardContent
235
+ When the card renders
236
+ Then the card surface renders with just the content region
237
+ And no header or footer spacing is reserved
238
+ ```
239
+
240
+ ### Root — hasError
241
+
242
+ ```gherkin
243
+ Scenario: Default border
244
+ Given a Card with hasError unset (or false)
245
+ When the card renders
246
+ Then the root border uses the on-surface-border token
247
+
248
+ Scenario: Error border
249
+ Given a Card with hasError set to true
250
+ When the card renders
251
+ Then the root border uses the on-surface-border-error token
252
+ And the header divider and text colors are unchanged
253
+ ```
254
+
255
+ ### Header — title & description
256
+
257
+ ```gherkin
258
+ Scenario: Default title
259
+ Given a CardHeader with no title prop
260
+ When the header renders
261
+ Then the title reads "Title"
262
+
263
+ Scenario: Description hidden by default
264
+ Given a CardHeader with a description prop but hasDescription unset
265
+ When the header renders
266
+ Then the description text does not appear
267
+
268
+ Scenario: Description shown
269
+ Given a CardHeader with a description prop and hasDescription set to true
270
+ When the header renders
271
+ Then the description appears below the title
272
+ ```
273
+
274
+ ### Header — drag handle
275
+
276
+ ```gherkin
277
+ Scenario: Drag handle hidden by default
278
+ Given a CardHeader with isDraggable unset
279
+ When the header renders
280
+ Then no drag handle appears
281
+
282
+ Scenario: Drag handle shown
283
+ Given a CardHeader with isDraggable set to true
284
+ When the header renders
285
+ Then a grip icon appears at the start of the header
286
+ And it carries the accessible name from dragHandleLabel (default "Reorder")
287
+ ```
288
+
289
+ ### Header — switch
290
+
291
+ ```gherkin
292
+ Scenario: Switch shown and toggled
293
+ Given a CardHeader with isSwitchable set to true
294
+ When the user activates the switch
295
+ Then onSwitchCheckedChange fires with the new checked value
296
+ ```
297
+
298
+ ### Header — avatar
299
+
300
+ ```gherkin
301
+ Scenario: Default avatar
302
+ Given a CardHeader with hasAvatar set to true and no avatar override
303
+ When the header renders
304
+ Then an avatar with avatarLabel's initials appears before the title
305
+
306
+ Scenario: Custom avatar
307
+ Given a CardHeader with hasAvatar set to true and an avatar override
308
+ When the header renders
309
+ Then the provided avatar node renders instead of the default initials avatar
310
+ ```
311
+
312
+ ### Header — rename
313
+
314
+ ```gherkin
315
+ Scenario: Rename button shown and activated
316
+ Given a CardHeader with hasRename set to true and an onRename handler
317
+ When the user activates the rename button
318
+ Then onRename fires
319
+ ```
320
+
321
+ ### Header — extras & actions
322
+
323
+ ```gherkin
324
+ Scenario: Extras render next to the title
325
+ Given a CardHeader with an extras node
326
+ When the header renders
327
+ Then the extras node appears immediately after the title (and rename button, if shown)
328
+
329
+ Scenario: Actions render at the end of the header
330
+ Given a CardHeader with an actions node
331
+ When the header renders
332
+ Then the actions node appears at the end of the header row
333
+ ```
334
+
335
+ ### Header — collapsible
336
+
337
+ ```gherkin
338
+ Scenario: Collapse trigger hidden by default
339
+ Given a CardHeader with isCollapsible unset
340
+ When the header renders
341
+ Then no collapse trigger appears
342
+
343
+ Scenario: Collapse trigger has no effect outside a collapsible AccordionContainer
344
+ Given a CardHeader with isCollapsible set to true, rendered with no
345
+ ancestor AccordionContainer
346
+ When the header renders
347
+ Then no collapse trigger appears
348
+
349
+ Scenario: Collapse trigger shown and operated inside a collapsible AccordionContainer
350
+ Given a Card composed as: AccordionContainer(collapsible) wrapping a
351
+ CardHeader with isCollapsible set to true, and an AccordionContainer.Content
352
+ wrapping CardContent/CardFooter
353
+ When the user activates the collapse trigger
354
+ Then the AccordionContainer's onOpenChange fires with the new open value
355
+ And AccordionContainer.Content's children (CardContent, CardFooter) are
356
+ hidden when closed and shown when open
357
+ And the header itself remains visible in both states
358
+ ```
359
+
360
+ ### Pass-through
361
+
362
+ ```gherkin
363
+ Scenario: Native attributes pass through
364
+ Given a Card with an id, data-* attribute, and aria-label
365
+ When the card renders
366
+ Then those attributes appear on the root element
367
+ ```
368
+
369
+ ```gherkin
370
+ Scenario: A custom className is merged, not replaced
371
+ Given a Card with className="w-[350px]"
372
+ When the card renders
373
+ Then the root carries both "w-[350px]" and the card's base classes
374
+ ```
375
+
376
+ ### Polymorphism
377
+
378
+ ```gherkin
379
+ Scenario: Rendering the root as a semantic element
380
+ Given a Card with render={<article />}
381
+ When the card renders
382
+ Then it renders as an <article> element
383
+ And it keeps the card's surface classes
384
+ ```
385
+
386
+ ## Accessibility
387
+
388
+ Card is a presentational grouping container plus a header that composes real
389
+ interactive controls (switch, rename button). Accessibility is partly a
390
+ function of how the card is composed and partly built into `CardHeader`'s
391
+ own controls.
392
+
393
+ ## Roles & semantics
394
+
395
+ - The root is a generic `<div>` with no role by default. If the card
396
+ represents a meaningful standalone region, render it as a landmark/section
397
+ via the `render` prop (e.g. `render={<section aria-labelledby="…" />}`) so
398
+ assistive tech can navigate to it.
399
+ - `CardHeader`'s title renders as a `<p>` by default, which has **no heading
400
+ semantics**. When the title is the heading of a content region, wrap the
401
+ card in a landmark and label it via `aria-labelledby` pointing at an
402
+ external heading, or render the root itself with an appropriate
403
+ `aria-label`.
404
+ - The drag handle icon is decorative artwork with an accessible name (via the
405
+ icon's `title` prop, driven by `dragHandleLabel`) — it is not itself
406
+ operable; drag-and-drop keyboard/pointer behavior is the consumer's
407
+ responsibility (e.g. wiring `dnd-kit`/`@dnd-kit/sortable`'s listeners onto
408
+ the header or handle).
409
+
410
+ ## Keyboard
411
+
412
+ - Card itself is not interactive and is not in the tab order.
413
+ - The header switch (`isSwitchable`) is a real Base UI `Switch` — reachable by
414
+ Tab and toggled with Space, per its own component contract.
415
+ - The rename button (`hasRename`) is a real `ButtonIconInput` — reachable by
416
+ Tab and activated with Enter/Space.
417
+ - The collapse trigger (`isCollapsible`, composed with `AccordionContainer`)
418
+ is a real Base UI `Collapsible.Trigger` — reachable by Tab and activated
419
+ with Enter/Space; ARIA `aria-expanded`/`aria-controls` wiring is owned by
420
+ `AccordionContainer`, not Card.
421
+ - Interactive children placed in `content` or `footer` retain their own
422
+ keyboard behavior and focus order — Card does not trap, reorder, or
423
+ intercept focus.
424
+
425
+ ## Screen reader
426
+
427
+ - The switch, rename button, and collapse trigger each require an accessible
428
+ name: `switchLabel` (default `"Toggle card"`), `renameLabel` (default
429
+ `"Rename"`), and `collapseLabel` (default `"Collapse card"`) — override all
430
+ three with copy specific to what the card represents (e.g. `"Enable
431
+ policy"`, `"Rename policy"`, `"Toggle backup policy"`) so they read
432
+ distinctly when more than one appears in the same header.
433
+ - The default avatar (`hasAvatar`) renders initials as visible text
434
+ (`avatarLabel`); provide a full-word label via a wrapping `aria-label` if
435
+ the initials alone aren't a sufficient description.
436
+ - With no landmark role on the root, the card's children are announced inline
437
+ in reading order.
438
+
439
+ ## Contrast
440
+
441
+ - Title and body text use `--ui-text-on-surface-primary`; the description
442
+ uses `--ui-text-on-surface-secondary` — both against
443
+ `--ui-background-surface-primary`. These token pairings meet WCAG AA in
444
+ both light and dark themes.
445
+ - The 1px border uses `--ui-border-on-surface-border` (or
446
+ `--ui-border-on-surface-border-error` when `hasError` is set) — border
447
+ contrast is decorative, not a text-contrast requirement.
@@ -0,0 +1,156 @@
1
+ # CarouselDialog
2
+
3
+ > The control row inside a `DialogFooterCarousel`: a `Back` button (hidden on the first slide), a dot slide indicator, and a `Next`/call-to-action button. Pure controls — no Embla import; the slide count/index/callbacks are threaded down from `DialogWelcome`, which owns the carousel engine. Deliberately NOT exported from `@acronis-platform/ui-react`'s public entry point — it is an internal primitive consumed only by `DialogFooterCarousel`. Apps building a welcome/onboarding carousel dialog should use `DialogWelcome` instead.
4
+
5
+ **Status:** draft · **Category:** layout · **Since:** v0.58.0
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { CarouselDialog } from '@acronis-platform/ui-react'
11
+ ```
12
+
13
+ ## Quick example
14
+
15
+ ```tsx
16
+ <CarouselDialog
17
+ variant="middle"
18
+ slideCount={3}
19
+ selectedIndex={1}
20
+ onSelectIndex={setSelectedIndex}
21
+ onBack={() => embla.scrollPrev()}
22
+ onNext={() => embla.scrollNext()}
23
+ />
24
+ ```
25
+
26
+ The control row inside a `DialogFooterCarousel`: a `Back` button, a dot slide
27
+ indicator, and a `Next`/call-to-action button. Pure controls with no Embla
28
+ import of its own; the slide count/index/callbacks are threaded down from
29
+ `DialogWelcome`, which owns the carousel engine.
30
+
31
+ ## When to use
32
+
33
+ - Inside `DialogFooterCarousel`, which supplies the themed footer bar around
34
+ this row. Not meant to be used standalone.
35
+
36
+ ## When not to use
37
+
38
+ - A standalone content carousel with no dialog footer chrome.
39
+ - A dialog's ordinary action row (Cancel/Save) — use `DialogFooterDefault`.
40
+
41
+ ## Parts
42
+
43
+ | Part | Description |
44
+ | ------------- | --------------------------------------------------------------------- |
45
+ | boxLeft | `Back` button. Hidden on the first slide (`variant="first"`). |
46
+ | listIndicator | One dot per slide; clicking a dot jumps to that slide. |
47
+ | boxRight | `Next` (first/middle slide) or the call-to-action label (last slide). |
48
+
49
+ ## Example
50
+
51
+ ```tsx
52
+ import { CarouselDialog } from '@acronis-platform/ui-react';
53
+
54
+ <CarouselDialog
55
+ variant="middle"
56
+ slideCount={3}
57
+ selectedIndex={1}
58
+ onSelectIndex={setSelectedIndex}
59
+ onBack={() => embla.scrollPrev()}
60
+ onNext={() => embla.scrollNext()}
61
+ />;
62
+ ```
63
+
64
+ ## Props
65
+
66
+ | Prop | Type | Default | Required | Description |
67
+ |------|------|---------|----------|-------------|
68
+ | `variant` | `'first' | 'middle' | 'last'` | `'first'` | no | Which slide position this renders for. |
69
+ | `slideCount` | `number` | `1` | no | Total number of slides, used to render the dot indicator. |
70
+ | `selectedIndex` | `number` | `0` | no | The currently active slide index (0-based). |
71
+ | `backLabel` | `string` | `'Back'` | no | `Back` button label. |
72
+ | `nextLabel` | `string` | `'Next'` | no | `Next` button label (`variant="first" | "middle"`). |
73
+ | `primaryLabel` | `string` | `'Call to action'` | no | Call-to-action button label (`variant="last"`). |
74
+ | `goToSlideLabel` | `(index: number, count: number) => string` | — | no | Builds each dot's accessible name from its 0-based index and the slide count. |
75
+
76
+ ## Events
77
+
78
+ | Event | Payload | Description |
79
+ |-------|---------|-------------|
80
+ | `select-index` | `number` | Fired when a dot is activated, with its slide index (React `onSelectIndex`). |
81
+ | `back` | `undefined` | Fired when `Back` (hidden on `variant="first"`) is activated (React `onBack`). |
82
+ | `next` | `undefined` | Fired when `Next` (`variant="first" | "middle"`) is activated (React `onNext`). |
83
+ | `primary-action` | `undefined` | Fired when the call-to-action button (`variant="last"`) is activated (React `onPrimaryAction`). |
84
+
85
+ ## Behavior
86
+
87
+ CarouselDialog is a pure function of its props — no internal state. The
88
+ carousel engine (which slide is active, how to move between slides) lives in
89
+ the caller — typically `DialogWelcome`'s Embla instance, threaded through
90
+ `DialogFooterCarousel` — which passes `slideCount`/`selectedIndex` in and
91
+ receives `onSelectIndex`/`onBack`/`onNext`/`onPrimaryAction` back out.
92
+
93
+ ```gherkin
94
+ Scenario: First slide (variant="first")
95
+ Given a CarouselDialog with variant="first"
96
+ Then `Back` is not rendered
97
+ And `Next` is rendered in boxRight
98
+ And the dot indicator marks the first dot active
99
+ ```
100
+
101
+ ```gherkin
102
+ Scenario: A middle slide (variant="middle")
103
+ Given a CarouselDialog with variant="middle"
104
+ Then `Back` is rendered in boxLeft
105
+ And `Next` is rendered in boxRight
106
+ ```
107
+
108
+ ```gherkin
109
+ Scenario: The last slide (variant="last")
110
+ Given a CarouselDialog with variant="last"
111
+ Then `Back` is rendered in boxLeft
112
+ And the call-to-action label (default "Call to action") replaces `Next` in boxRight
113
+ ```
114
+
115
+ ```gherkin
116
+ Scenario: Jumping to an arbitrary slide
117
+ Given a CarouselDialog with slideCount=3
118
+ When a dot other than the active one is activated
119
+ Then onSelectIndex fires with that dot's 0-based index
120
+ And the caller is responsible for actually moving the carousel and passing
121
+ back an updated `variant`/`selectedIndex`
122
+ ```
123
+
124
+ ```gherkin
125
+ Scenario: A single-slide carousel
126
+ Given a CarouselDialog with slideCount=1
127
+ Then only one dot renders, always active
128
+ And the caller is responsible for choosing variant="last" for that single
129
+ slide (it is both the first and the last), so the call-to-action button
130
+ is reachable
131
+ ```
132
+
133
+ ## Accessibility
134
+
135
+ - `Back`, `Next`, and the call-to-action control render as real `Button`
136
+ elements — native focus, keyboard activation (Enter/Space), and the
137
+ Button's own accessible name (its label) come for free.
138
+ - Each dot in the indicator is a real `<button>` with an explicit
139
+ `aria-label` (default `"Go to slide N of M"`, overridable via
140
+ `goToSlideLabel`) — dots are never bare, unlabeled `<div>`s. The active dot
141
+ carries `aria-current="true"`. Dots have their own `focus-visible` ring
142
+ (`--ui-focus-primary`), matching the kit's other raw-`<button>` controls
143
+ (e.g. `Pagination`, `Tabs`).
144
+ - CarouselDialog is a plain layout container — no landmark role of its own.
145
+ It's meant to live inside `DialogFooterCarousel` inside a dialog (e.g.
146
+ `DialogWelcome`), which owns the `role="dialog"` / focus-trap semantics.
147
+ - Focus order follows DOM order: `Back` (when present) → dots → `Next`/
148
+ call-to-action.
149
+
150
+ ## Contrast
151
+
152
+ The active dot uses `--ui-glyph-on-surface-primary`; inactive dots use
153
+ `--ui-glyph-on-surface-disabled`. Both are guaranteed to meet contrast against
154
+ the footer's own background in both light and dark (shared semantic
155
+ glyph/surface pairing) — the same tokens `Breadcrumb`'s separator icon and
156
+ `Switch`'s track use for the equivalent idle/disabled distinction.