@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,146 @@
1
+ # EmptyOverlay
2
+
3
+ > A full-bleed empty-state overlay — a colored icon badge over a centered title/description, on a fade-to-solid backdrop. Meant to sit over other content (e.g. a frozen/blurred widget preview); the developer sizes it (typically `absolute inset-0` over a positioned parent).
4
+
5
+ **Status:** ready · **Category:** data-display · **Since:** v2.1.0
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { EmptyOverlay } from '@acronis-platform/ui-react'
11
+ ```
12
+
13
+ ## Quick example
14
+
15
+ ```tsx
16
+ <div className="relative h-96">
17
+ <EmptyOverlay
18
+ icon={<InboxIcon />}
19
+ title="No object yet"
20
+ description="Short description."
21
+ />
22
+ </div>
23
+ ```
24
+
25
+ A full-bleed empty-state overlay: a colored icon badge over a centered
26
+ title/description, on a fade-to-solid backdrop.
27
+
28
+ ## When to use
29
+
30
+ - Overlay a "no data yet" message on top of other content — e.g. a
31
+ frozen/blurred widget preview behind the message.
32
+ - As a standalone empty state that should fill its container edge-to-edge.
33
+
34
+ ## When not to use
35
+
36
+ - For a plain, non-overlay empty state with no background treatment — use
37
+ `Empty`'s composable parts instead.
38
+ - For a bordered dashboard-widget card with a header/footer — use
39
+ `WidgetPlaceholder`.
40
+
41
+ ## Sizing
42
+
43
+ `EmptyOverlay` always fills its parent (`size-full`) — the developer is
44
+ responsible for sizing and positioning the parent, typically
45
+ `relative` + `absolute inset-0`.
46
+
47
+ ## Examples
48
+
49
+ ```tsx
50
+ import { EmptyOverlay } from '@acronis-platform/ui-react';
51
+ import { InboxIcon } from '@acronis-platform/icons-react/stroke-mono';
52
+
53
+ <div className="relative h-96">
54
+ <EmptyOverlay
55
+ icon={<InboxIcon />}
56
+ title="No object yet"
57
+ description="Short description."
58
+ />
59
+ </div>;
60
+ ```
61
+
62
+ ## Parts
63
+
64
+ | Part | Element | Purpose |
65
+ | ------------- | ------- | -------------------------------------------- |
66
+ | root | `div` | Fills the parent; fade-to-solid backdrop. |
67
+ | `icon` | `div` | Optional 24px glyph in a 64px colored badge. |
68
+ | `title` | `h3` | The empty-state headline. |
69
+ | `description` | `p` | Optional supporting copy under the title. |
70
+
71
+ ## Props
72
+
73
+ | Prop | Type | Default | Required | Description |
74
+ |------|------|---------|----------|-------------|
75
+ | `icon` | `ReactNode` | — | no | Icon rendered in the colored badge (e.g. an `icons-react` glyph at 24px). Omitting it omits the badge entirely. |
76
+ | `title` | `ReactNode` | — | yes | The empty-state headline, rendered as an `<h3>`. |
77
+ | `description` | `ReactNode` | — | no | Optional supporting copy shown under the title. |
78
+ | `color` | `'teal' | 'violet' | 'red' | 'yellow' | 'orange' | 'blue' | 'gray' | 'green'` | `green` | no | Icon badge color scheme, from the shared avatar palette. Maps to `--ui-avatar-color-<scheme>` (badge fill) and `--ui-avatar-label-color-<scheme>` (icon color). |
79
+
80
+ ## Behavior
81
+
82
+ ### Fills its container
83
+
84
+ **Given** an `EmptyOverlay`
85
+ **When** it renders
86
+ **Then** it fills the width and height of its parent (`size-full`) and centers
87
+ its content — the developer is responsible for sizing/positioning the parent
88
+ (e.g. `relative` + `absolute inset-0` to overlay other content).
89
+
90
+ ### Icon badge
91
+
92
+ **Given** an `icon`
93
+ **When** it renders
94
+ **Then** a 64px circular badge shows above the title, holding the icon at
95
+ 24px; the badge's fill/icon color come from the `color` prop (default
96
+ `green`).
97
+ **Given** no `icon`
98
+ **Then** the badge is omitted entirely — only the title/description center.
99
+
100
+ ### Color
101
+
102
+ **Given** `color` set to one of the eight avatar palette values (`teal`,
103
+ `violet`, `red`, `yellow`, `orange`, `blue`, `gray`, `green`)
104
+ **When** it renders
105
+ **Then** the badge's fill and icon color resolve from that color's
106
+ `--ui-avatar-color-<color>` / `--ui-avatar-label-color-<color>` tokens
107
+ **And** with no `color` it defaults to `green`.
108
+
109
+ ### Title / description
110
+
111
+ **Given** a `title`
112
+ **When** it renders
113
+ **Then** it shows as an `<h3>` headline below the badge.
114
+ **Given** a `description`
115
+ **When** it renders
116
+ **Then** it shows as supporting copy below the title.
117
+ **Given** no `description`
118
+ **Then** only the title renders.
119
+
120
+ ### Non-interactive
121
+
122
+ **Given** an `EmptyOverlay`
123
+ **When** the user hovers or clicks it
124
+ **Then** nothing happens — it is a presentational placeholder, not a control.
125
+
126
+ ## Accessibility
127
+
128
+ ## Semantics
129
+
130
+ - The root is a plain, non-interactive `<div>` — no role, not a live region.
131
+ If the overlay replaces content that a screen reader user was tracking
132
+ (e.g. it appears after a failed load), the consumer is responsible for any
133
+ live-region announcement at the point where the overlay is mounted.
134
+ - `title` renders as an `<h3>`, so it participates in the page's heading
135
+ outline — pick a container level that keeps that hierarchy sensible.
136
+ - The icon badge is decorative (the title/description already carry the
137
+ meaning); it needs no accessible name of its own.
138
+
139
+ ## Keyboard & focus
140
+
141
+ - Not focusable and not in the tab order — there is nothing to activate.
142
+
143
+ ## Contrast
144
+
145
+ - Each badge color's fill/icon pair, and the title/description text colors,
146
+ resolve from tokens that meet contrast in both light and dark themes.
@@ -0,0 +1,156 @@
1
+ # Empty
2
+
3
+ > A centered empty-state placeholder shown when there is no data or content. A set of composable parts (icon, header, title, description, actions, links). Ported from the legacy shadcn-uikit `Empty`; themed by the shared semantic text tokens.
4
+
5
+ **Status:** draft · **Category:** data-display · **Since:** v0.13.0
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { Empty, EmptyIcon, EmptyHeader, EmptyTitle, EmptyDescription, EmptyActions, EmptyLinks } from '@acronis-platform/ui-react'
11
+ ```
12
+
13
+ ## Quick example
14
+
15
+ ```tsx
16
+ <Empty>
17
+ <EmptyIcon>
18
+ <InboxIcon />
19
+ </EmptyIcon>
20
+ <EmptyHeader>
21
+ <EmptyTitle>No backups found</EmptyTitle>
22
+ <EmptyDescription>Create your first backup plan.</EmptyDescription>
23
+ </EmptyHeader>
24
+ <EmptyActions>
25
+ <Button>Create backup plan</Button>
26
+ </EmptyActions>
27
+ </Empty>
28
+ ```
29
+
30
+ A centered empty-state placeholder shown when there is no data or content.
31
+ Composable from parts; no variants.
32
+
33
+ > **Status: draft (design-pending v1).** Ported from the legacy
34
+ > `@acronis-platform/shadcn-uikit` `Empty`. No `--ui-empty-*` token tier yet, so
35
+ > it themes from the shared semantic text tokens (title `text-foreground`,
36
+ > description/icon `text-muted-foreground`). Reconcile with
37
+ > `/figma-component Empty <url> --update` once a mockup lands.
38
+
39
+ ## When to use
40
+
41
+ - A list, table, or panel that has no items yet (or none match a filter).
42
+ - A first-run state inviting the user to create the first item.
43
+
44
+ ## When not to use
45
+
46
+ - For a loading state — use a spinner/skeleton, not Empty.
47
+ - For an error state — show an error with a retry, not a neutral empty.
48
+ - For a blocking message — use a Dialog.
49
+
50
+ ## Parts
51
+
52
+ | Part | Element | Purpose |
53
+ | ------------------ | ------- | -------------------------------------- |
54
+ | `Empty` | `div` | Centered container (max 448px), muted. |
55
+ | `EmptyIcon` | `div` | Optional 72px illustration/glyph slot. |
56
+ | `EmptyHeader` | `div` | Groups the title + description. |
57
+ | `EmptyTitle` | `h3` | The heading (foreground color). |
58
+ | `EmptyDescription` | `p` | Supporting copy (muted). |
59
+ | `EmptyActions` | `div` | Primary action(s), e.g. a Button. |
60
+ | `EmptyLinks` | `div` | Secondary supporting link(s). |
61
+
62
+ ## Example
63
+
64
+ ```tsx
65
+ import {
66
+ Empty,
67
+ EmptyIcon,
68
+ EmptyHeader,
69
+ EmptyTitle,
70
+ EmptyDescription,
71
+ EmptyActions,
72
+ Button,
73
+ } from '@acronis-platform/ui-react';
74
+ import { InboxIcon } from '@acronis-platform/icons-react/stroke-mono';
75
+
76
+ <Empty>
77
+ <EmptyIcon>
78
+ <InboxIcon />
79
+ </EmptyIcon>
80
+ <EmptyHeader>
81
+ <EmptyTitle>No backups found</EmptyTitle>
82
+ <EmptyDescription>Create your first backup plan.</EmptyDescription>
83
+ </EmptyHeader>
84
+ <EmptyActions>
85
+ <Button>Create backup plan</Button>
86
+ </EmptyActions>
87
+ </Empty>;
88
+ ```
89
+
90
+ ## Content slots
91
+
92
+ | Slot | Description |
93
+ |------|-------------|
94
+ | `default` | The composed empty state. Author it from the parts: an optional icon, a header (title + description), and optional actions / links. All parts are optional and may be combined as needed. |
95
+
96
+ ## Behavior
97
+
98
+ Empty is a presentational placeholder assembled from composable parts. It has no
99
+ props, no variants, and no interaction state — it is a pure function of its
100
+ composition.
101
+
102
+ ### Composition
103
+
104
+ ```gherkin
105
+ Scenario: A full empty state
106
+ Given an Empty wrapping an EmptyIcon, an EmptyHeader (EmptyTitle +
107
+ EmptyDescription), and EmptyActions
108
+ When it renders
109
+ Then the icon, title, description, and actions stack centered in source order
110
+ ```
111
+
112
+ ```gherkin
113
+ Scenario: Parts are optional
114
+ Given an Empty wrapping only an EmptyHeader with an EmptyTitle
115
+ When it renders
116
+ Then just the title shows, centered — no icon or actions space is reserved
117
+ ```
118
+
119
+ ### Usage
120
+
121
+ ```gherkin
122
+ Scenario: Filling a region
123
+ Given a list or table with no rows
124
+ When the consumer renders an Empty in its place
125
+ Then the empty state is centered within that region (the consumer sizes it)
126
+ ```
127
+
128
+ ## Accessibility
129
+
130
+ Empty is presentational; accessibility is mostly about the heading and the icon.
131
+
132
+ ## Roles & semantics
133
+
134
+ - `EmptyTitle` renders an `<h3>`. Make sure that level fits the surrounding
135
+ document outline — if the empty state replaces a section whose heading was a
136
+ different level, set the heading appropriately (override via `className`/markup
137
+ as needed). Don't skip levels.
138
+ - `EmptyDescription` is a `<p>` associated with the title by proximity.
139
+ - The `EmptyIcon` is decorative — mark its SVG `aria-hidden="true"` so it isn't
140
+ announced (the title carries the meaning).
141
+ - When the empty state appears **in response to an async action** (e.g. a search
142
+ returned nothing, or data finished loading empty), wrap it (or a status region)
143
+ with `role="status"` / `aria-live="polite"` so screen-reader users are told the
144
+ result. Empty itself does not impose a role.
145
+
146
+ ## Keyboard
147
+
148
+ - Empty has no interactive behavior. Any controls placed in `EmptyActions` /
149
+ `EmptyLinks` (Buttons, Links) keep their own focus and keyboard behavior.
150
+
151
+ ## Contrast
152
+
153
+ - The title uses `--ui-text-on-surface-primary`; the description and icon use
154
+ `--ui-text-on-surface-secondary` — both meet WCAG AA against the page surface in
155
+ light and dark. Re-verify against the final palette once a `--ui-empty-*` tier
156
+ and Figma reference exist.
@@ -0,0 +1,185 @@
1
+ # Field
2
+
3
+ > A form-field wrapper that ties a control to its label, description, and error, built on Base UI's Field primitive so those associations (and the validity state) are wired automatically. Ships structural parts (fieldset, legend, group, content, separator) for composing and grouping fields. Ported from the legacy shadcn-uikit `field`.
4
+
5
+ **Status:** draft · **Category:** forms · **Since:** v0.47.0
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { Field, FieldLabel, FieldControl, FieldDescription, FieldError } from '@acronis-platform/ui-react'
11
+ ```
12
+
13
+ ## Quick example
14
+
15
+ ```tsx
16
+ <Field>
17
+ <FieldLabel>Email</FieldLabel>
18
+ <FieldControl render={<InputBox />} />
19
+ <FieldDescription>We'll never share it.</FieldDescription>
20
+ </Field>
21
+ ```
22
+
23
+ A form-field wrapper that ties a control to its label, description, and error.
24
+ Built on Base UI's Field primitive, so the `for` / `id` / `aria-describedby` /
25
+ `aria-invalid` associations and the validity state are wired automatically — no
26
+ manual plumbing. Structural parts (`FieldSet`, `FieldLegend`, `FieldGroup`,
27
+ `FieldContent`, `FieldSeparator`) compose and group fields.
28
+
29
+ > **Design-pending v1**, ported from the legacy shadcn-uikit `field` and rebuilt
30
+ > on Base UI Field. Reconcile with Figma later.
31
+
32
+ ## When to use
33
+
34
+ - Labelling a **bare** control with a description and/or validation error — the
35
+ primary case is a text field via `FieldControl render={<InputBox />}`.
36
+ - Grouping related controls under a heading (`FieldSet` + `FieldLegend`).
37
+
38
+ ## When not to use
39
+
40
+ - A standalone text field with built-in furniture — use `InputText` /
41
+ `InputSearch` / `InputSelect`, which already include label/description/error.
42
+ - Naming a single `Checkbox` / `Switch` — they self-label via their own `label`
43
+ prop. Use `Field`/`FieldSet` only to **group** them.
44
+
45
+ ## Parts
46
+
47
+ | Export | Purpose |
48
+ | ------------------ | --------------------------------------------------------------------------------- |
49
+ | `Field` | The field wrapper (Base UI Field.Root). `orientation` lays out label vs. control. |
50
+ | `FieldLabel` | The caption — auto-associated with the control. |
51
+ | `FieldControl` | Wires a bare control; use its `render` prop (e.g. `render={<InputBox />}`). |
52
+ | `FieldDescription` | Helper text — auto-linked via `aria-describedby`. |
53
+ | `FieldError` | Validation message — shown by validity, or forced with `match`. |
54
+ | `FieldContent` | Stacks a label + description beside a control (e.g. a toggle row). |
55
+ | `FieldTitle` | A non-label heading for a field with no single associated control. |
56
+ | `FieldSet` | Native `<fieldset>` grouping related fields. |
57
+ | `FieldLegend` | The fieldset heading — `legend` (large) or `label` (small) `variant`. |
58
+ | `FieldGroup` | A vertical stack of fields / nested groups (container-query context). |
59
+ | `FieldSeparator` | A divider between fields, with an optional centered label. |
60
+
61
+ > `FieldLabel` / `FieldControl` / `FieldDescription` / `FieldError` are Base UI
62
+ > Field parts — they must be rendered **inside a `Field`** (they throw without the
63
+ > Field context). For a group-level heading use `FieldLegend` in a `FieldSet`.
64
+
65
+ ## Example
66
+
67
+ ```tsx
68
+ import {
69
+ Field,
70
+ FieldLabel,
71
+ FieldControl,
72
+ FieldDescription,
73
+ FieldError,
74
+ InputBox,
75
+ } from '@acronis-platform/ui-react';
76
+
77
+ <Field invalid={hasError}>
78
+ <FieldLabel>Email</FieldLabel>
79
+ <FieldControl render={<InputBox type="email" />} />
80
+ <FieldDescription>We'll never share your email.</FieldDescription>
81
+ <FieldError match>Please enter a valid email address.</FieldError>
82
+ </Field>;
83
+ ```
84
+
85
+ Group self-labeling controls:
86
+
87
+ ```tsx
88
+ <FieldSet>
89
+ <FieldLegend>Notifications</FieldLegend>
90
+ <FieldGroup>
91
+ <Checkbox label="Product updates" />
92
+ <Checkbox label="Security alerts" />
93
+ </FieldGroup>
94
+ </FieldSet>
95
+ ```
96
+
97
+ ## Props
98
+
99
+ | Prop | Type | Default | Required | Description |
100
+ |------|------|---------|----------|-------------|
101
+ | `orientation` | `'vertical' | 'horizontal' | 'responsive'` | `'vertical'` | no | Label/control layout — stacked, inline, or stacked-then-inline at the @md container width. |
102
+ | `invalid` | `boolean` | — | no | Marks the field invalid (sets data-invalid + the control's aria-invalid). Useful when validation is controlled externally. |
103
+ | `disabled` | `boolean` | `false` | no | Disables the field and its control. |
104
+ | `name` | `string` | — | no | Identifies the field when a form is submitted. |
105
+ | `validate` | `(value, formValues) => string | string[] | null | Promise<…>` | — | no | Custom validation; returns error message(s) or null. |
106
+ | `validationMode` | `'onSubmit' | 'onBlur' | 'onChange'` | `'onSubmit'` | no | When the field validates. |
107
+ | `match` | `boolean | keyof ValidityState` | — | no | On FieldError — which ValidityState shows the message; `true` always shows it (for externally controlled validation). |
108
+ | `variant` | `'legend' | 'label'` | `'legend'` | no | On FieldLegend — large legend text or small label text. |
109
+
110
+ ## Behavior
111
+
112
+ Field is built on Base UI's Field primitive. It wires a control to its label,
113
+ description, and error automatically, and pairs with the _bare_ controls
114
+ (`InputBox`, plus the self-labeling `Checkbox` / `Switch` / `RadioGroup` for
115
+ grouping) — not the self-contained `InputText` / `InputSearch` fields.
116
+
117
+ ```gherkin
118
+ Scenario: Label associates with the control
119
+ Given a Field with a FieldLabel and a FieldControl render={<InputBox />}
120
+ Then the label's htmlFor matches the control's id (no manual wiring)
121
+ And clicking the label focuses the control
122
+ ```
123
+
124
+ ```gherkin
125
+ Scenario: Description is announced
126
+ Given a Field with a FieldDescription
127
+ Then the control's aria-describedby references the description
128
+ ```
129
+
130
+ ```gherkin
131
+ Scenario: Error on invalid
132
+ Given a Field marked invalid (or failing validation)
133
+ Then data-invalid is set, the control gets aria-invalid
134
+ And a FieldError message is shown (always, when match is forced on)
135
+ ```
136
+
137
+ ```gherkin
138
+ Scenario: Orientation
139
+ Given orientation="horizontal"
140
+ Then the label and control lay out in a row
141
+ And orientation="responsive" stacks until the @md container width, then rows
142
+ ```
143
+
144
+ ```gherkin
145
+ Scenario: Group related fields
146
+ Given a FieldSet with a FieldLegend and a FieldGroup of fields
147
+ Then the legend names the group and the fields stack with consistent spacing
148
+ ```
149
+
150
+ ```gherkin
151
+ Scenario: Group self-labeling controls
152
+ Given a FieldSet of Checkboxes that each carry their own label
153
+ Then the set provides the legend + spacing and each control names itself
154
+ ```
155
+
156
+ ```gherkin
157
+ Scenario: Separate fields
158
+ Given a FieldSeparator with text between two fields
159
+ Then a divider renders with the text centered over the rule
160
+ ```
161
+
162
+ ## Accessibility
163
+
164
+ Field's purpose is accessibility: it removes the manual wiring that's easy to get
165
+ wrong.
166
+
167
+ - **Label association** is automatic — `FieldLabel` (Base UI `Field.Label`) links
168
+ to the control rendered through `FieldControl`, so no `htmlFor`/`id` plumbing.
169
+ - **Description** is exposed via `aria-describedby` on the control automatically.
170
+ - **Error / invalid:** an invalid field sets `data-invalid` and the control's
171
+ `aria-invalid`; `FieldError` carries `role="alert"` semantics so the message is
172
+ announced. Don't rely on color alone — the message text states the problem.
173
+ - **Grouping:** `FieldSet` is a native `<fieldset>` and `FieldLegend` a
174
+ `<legend>`, so a group of related fields (e.g. a set of checkboxes or radios)
175
+ is named for assistive tech. The field root carries `role="group"`.
176
+ - Pair Field with the **bare** controls. `Checkbox` / `Switch` already self-label
177
+ (their own `label` prop) — let them name themselves inside a `FieldSet`; don't
178
+ double-label them with a `FieldLabel`.
179
+
180
+ ## Contrast
181
+
182
+ Error/invalid text uses `--ui-text-on-status-danger` (a readable red on the page
183
+ surface in both themes) — not the bridged `text-destructive`, which resolves to
184
+ the pale danger _surface_. Description text uses the muted
185
+ `--ui-text-on-surface-secondary`; both meet contrast in light and dark.
@@ -0,0 +1,157 @@
1
+ # FilterCards
2
+
3
+ > A horizontal row container (the Figma `FilterCards` component) that lays out a set of `CardFilter` items, stretching each to an equal share of the available width. Pure layout — it owns no visual styling of its own besides the inter-card gap. Figma's nested `ListCards` slot maps to `children`.
4
+
5
+ **Status:** ready · **Category:** data-display · **Since:** v0.62.0
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { FilterCards, CardFilter } from '@acronis-platform/ui-react'
11
+ ```
12
+
13
+ ## Quick example
14
+
15
+ ```tsx
16
+ <FilterCards>
17
+ <CardFilter label="Total assets" value="125" />
18
+ <CardFilter label="Active filters" value="3" variant="clickable" />
19
+ <CardFilter label="Pending" variant="static-empty" />
20
+ </FilterCards>
21
+ ```
22
+
23
+ A horizontal row container (the Figma `FilterCards` component) for
24
+ `CardFilter` items — Figma's nested `ListCards` slot maps to the `children`
25
+ you pass in. It stretches each child to an equal share of the available width
26
+ and owns the 16px gap between them — pure layout, no visual styling of its
27
+ own.
28
+
29
+ ## When to use
30
+
31
+ - A row of stat/filter cards summarizing counts across a dashboard (e.g.
32
+ "Total assets", "Active filters", "Pending").
33
+ - Any number of `CardFilter` children — the row redistributes width evenly as
34
+ the count changes.
35
+
36
+ ## When not to use
37
+
38
+ - For a single metric with no siblings — render a bare `CardFilter` instead.
39
+ - For a wrapping grid of cards — `FilterCards` is a single row, not a grid;
40
+ use `Grid`/`Stack` for a wrapping layout.
41
+
42
+ ## Examples
43
+
44
+ ```tsx
45
+ import { FilterCards, CardFilter } from '@acronis-platform/ui-react';
46
+ import { SquareDashedIcon } from '@acronis-platform/icons-react/stroke-mono';
47
+
48
+ <FilterCards>
49
+ <CardFilter label="Total assets" value="125" icon={<SquareDashedIcon />} />
50
+ <CardFilter
51
+ variant="clickable"
52
+ label="Active filters"
53
+ value="3"
54
+ icon={<SquareDashedIcon />}
55
+ />
56
+ <CardFilter variant="static-empty" label="Pending" />
57
+ </FilterCards>;
58
+ ```
59
+
60
+ ## Overflow
61
+
62
+ Cards shrink to fill the row, but never below their own content's natural
63
+ width — a card's label/value is never clipped. If there are enough cards that
64
+ they no longer fit at that natural width, the row overflows its container.
65
+ `FilterCards` adds no scroll or wrap of its own — wrap the row in a
66
+ horizontally scrollable container if that's the desired behavior:
67
+
68
+ ```tsx
69
+ <div className="overflow-x-auto">
70
+ <FilterCards>{/* many cards */}</FilterCards>
71
+ </div>
72
+ ```
73
+
74
+ ## Parts
75
+
76
+ | Part | Element | Description |
77
+ | ------ | ------- | ------------------------------------------------------------------------------------------------- |
78
+ | `root` | `<div>` | The row itself — flex, 16px gap, equal-width children. |
79
+ | `card` | (any) | Consumer-supplied children (typically `CardFilter`), stretched to fill an equal share of the row. |
80
+
81
+ ## Props
82
+
83
+ | Prop | Type | Default | Required | Description |
84
+ |------|------|---------|----------|-------------|
85
+ | `render` | `RenderProp` | `undefined` | no | Base UI composition prop on the root — replaces the rendered `<div>` with another element or component while merging props and classes. React-only; other frameworks use their own polymorphism. |
86
+
87
+ ## Content slots
88
+
89
+ | Slot | Description |
90
+ |------|-------------|
91
+ | `default` | The cards to lay out in the row — typically a list of `CardFilter` elements. Each child is stretched to an equal share of the available width (flex-1), regardless of how many are passed in. |
92
+
93
+ ## Behavior
94
+
95
+ ### Layout
96
+
97
+ **Given** a `FilterCards` with two or more children
98
+ **When** it renders
99
+ **Then** the children lay out in a single horizontal row with a 16px gap
100
+ (`--ui-gap-16`) and each child stretches to an equal share of the row's
101
+ width via `flex: 1 1 0%` — except a child whose own content exceeds that
102
+ share, which takes more (see the min-content overflow scenario below).
103
+
104
+ **Given** a single `FilterCards` child
105
+ **When** it renders
106
+ **Then** that child fills the entire row width (equal share of one).
107
+
108
+ **Given** a `CardFilter` child with its own fixed 224px width
109
+ **When** it is composed inside `FilterCards`
110
+ **Then** the row's `flex-1` stretching overrides that fixed width — matching
111
+ the "fill container" sizing Figma applies to each `CardFilter` instance inside
112
+ this composition.
113
+
114
+ **Given** enough children that their combined natural (min-content) width
115
+ exceeds the row
116
+ **When** `FilterCards` renders
117
+ **Then** each card only shrinks down to its own content's natural width — no
118
+ card's label/value is ever clipped — and the row overflows its container
119
+ instead. `FilterCards` adds no scroll or wrap of its own; the consumer is
120
+ responsible for giving the row a scrollable container (e.g.
121
+ `overflow-x-auto`) when that degradation is undesired. There is no design
122
+ spec for this case — Figma only documents the exact-fit composition.
123
+
124
+ **Constraint:** `FilterCards` owns no state of its own — it is a pure function
125
+ of its `children`. Any interaction state (hover, selected, …) lives entirely
126
+ on the child (see `CardFilter`'s own spec).
127
+
128
+ ### Composition
129
+
130
+ **Given** a `render` prop (e.g. `<section />`)
131
+ **When** `FilterCards` renders
132
+ **Then** it renders as that element with the row's classes and props merged
133
+ on.
134
+
135
+ **Given** children other than `CardFilter`
136
+ **When** `FilterCards` renders
137
+ **Then** they lay out identically — `FilterCards` does not constrain the
138
+ child type, only its layout.
139
+
140
+ ## Accessibility
141
+
142
+ - **Role:** a plain `<div>` (`role="group"` is a reasonable authoring choice,
143
+ not enforced by the component) — pure layout, not a landmark or a list. The
144
+ `render` prop can swap the element.
145
+ - **No component-owned interaction:** `FilterCards` renders no interactive
146
+ element itself. All keyboard/focus/ARIA behavior belongs to its children
147
+ (e.g. `CardFilter`'s `clickable` variant) — see that component's own
148
+ accessibility spec.
149
+ - **Accessible name:** none required on the row itself; if the group of cards
150
+ needs an accessible label (e.g. "Filter summary"), pass `aria-label` — it
151
+ passes through as a native `<div>` attribute.
152
+ - **Reading order:** children read in DOM order, left-to-right in `ltr`,
153
+ mirrored in `rtl` via the browser's default flex-row bidi behavior — no
154
+ logical-vs-physical utility is involved since the row uses `flex` with no
155
+ directional margin/padding.
156
+ - **WCAG:** no component-specific requirements beyond what its children
157
+ contribute (1.3.1 structure is satisfied by DOM order).