@acronis-platform/ui-react 3.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 (219) hide show
  1. package/dist/components/ui/accordion-container/accordion-container.js +14 -14
  2. package/dist/components/ui/accordion-container/accordion-container.js.map +1 -1
  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/bar-chart/bar-chart.js +295 -293
  7. package/dist/components/ui/bar-chart/bar-chart.js.map +1 -1
  8. package/dist/components/ui/category-bar/category-bar.js +109 -93
  9. package/dist/components/ui/category-bar/category-bar.js.map +1 -1
  10. package/dist/components/ui/chart/chart-palette.js +113 -0
  11. package/dist/components/ui/chart/chart-palette.js.map +1 -0
  12. package/dist/components/ui/chart/chart.js +176 -129
  13. package/dist/components/ui/chart/chart.js.map +1 -1
  14. package/dist/components/ui/chart-state/chart-state-illustrations.js +310 -0
  15. package/dist/components/ui/chart-state/chart-state-illustrations.js.map +1 -0
  16. package/dist/components/ui/chart-state/chart-state.js +48 -34
  17. package/dist/components/ui/chart-state/chart-state.js.map +1 -1
  18. package/dist/components/ui/chart-widget/chart-widget.js +87 -0
  19. package/dist/components/ui/chart-widget/chart-widget.js.map +1 -0
  20. package/dist/components/ui/composed-chart/composed-chart.js +117 -115
  21. package/dist/components/ui/composed-chart/composed-chart.js.map +1 -1
  22. package/dist/components/ui/confidence-cone/confidence-cone.js +166 -158
  23. package/dist/components/ui/confidence-cone/confidence-cone.js.map +1 -1
  24. package/dist/components/ui/funnel-chart/funnel-chart.js +162 -161
  25. package/dist/components/ui/funnel-chart/funnel-chart.js.map +1 -1
  26. package/dist/components/ui/histogram/histogram.js +94 -92
  27. package/dist/components/ui/histogram/histogram.js.map +1 -1
  28. package/dist/components/ui/input/input.js.map +1 -1
  29. package/dist/components/ui/label/label.js +2 -9
  30. package/dist/components/ui/label/label.js.map +1 -1
  31. package/dist/components/ui/line-chart/line-chart.js +143 -141
  32. package/dist/components/ui/line-chart/line-chart.js.map +1 -1
  33. package/dist/components/ui/metric/metric.js +74 -185
  34. package/dist/components/ui/metric/metric.js.map +1 -1
  35. package/dist/components/ui/page-content/page-content.js.map +1 -1
  36. package/dist/components/ui/pie-chart/pie-chart.js +201 -195
  37. package/dist/components/ui/pie-chart/pie-chart.js.map +1 -1
  38. package/dist/components/ui/radar-chart/radar-chart.js +133 -131
  39. package/dist/components/ui/radar-chart/radar-chart.js.map +1 -1
  40. package/dist/components/ui/radial-bar-chart/radial-bar-chart.js +297 -265
  41. package/dist/components/ui/radial-bar-chart/radial-bar-chart.js.map +1 -1
  42. package/dist/components/ui/sankey-chart/sankey-chart.js +123 -101
  43. package/dist/components/ui/sankey-chart/sankey-chart.js.map +1 -1
  44. package/dist/components/ui/scatter-chart/scatter-chart.js +76 -74
  45. package/dist/components/ui/scatter-chart/scatter-chart.js.map +1 -1
  46. package/dist/components/ui/section/section.js +157 -31
  47. package/dist/components/ui/section/section.js.map +1 -1
  48. package/dist/components/ui/stepper/stepper.js +24 -24
  49. package/dist/components/ui/stepper/stepper.js.map +1 -1
  50. package/dist/components/ui/stepper-item/stepper-item.js +43 -24
  51. package/dist/components/ui/stepper-item/stepper-item.js.map +1 -1
  52. package/dist/components/ui/treemap/treemap.js +133 -124
  53. package/dist/components/ui/treemap/treemap.js.map +1 -1
  54. package/dist/components/ui/trend-indicator/trend-indicator.js +34 -69
  55. package/dist/components/ui/trend-indicator/trend-indicator.js.map +1 -1
  56. package/dist/components/ui/wizard/wizard.js +59 -0
  57. package/dist/components/ui/wizard/wizard.js.map +1 -0
  58. package/dist/hooks/use-wizard.js +75 -0
  59. package/dist/hooks/use-wizard.js.map +1 -0
  60. package/dist/index.js +502 -497
  61. package/dist/index.js.map +1 -1
  62. package/dist/llms/accordion-container.md +181 -0
  63. package/dist/llms/accordion.md +124 -0
  64. package/dist/llms/alert.md +225 -0
  65. package/dist/llms/app-shell-chat.md +415 -0
  66. package/dist/llms/area-chart.md +355 -0
  67. package/dist/llms/avatar.md +208 -0
  68. package/dist/llms/bar-chart.md +406 -0
  69. package/dist/llms/breadcrumb.md +326 -0
  70. package/dist/llms/button-group.md +298 -0
  71. package/dist/llms/button-icon-input.md +142 -0
  72. package/dist/llms/button-icon-menu.md +209 -0
  73. package/dist/llms/button-icon.md +128 -0
  74. package/dist/llms/button-menu.md +172 -0
  75. package/dist/llms/button.md +185 -0
  76. package/dist/llms/calendar-panel.md +733 -0
  77. package/dist/llms/calendar.md +188 -0
  78. package/dist/llms/card-filter.md +214 -0
  79. package/dist/llms/card-section.md +293 -0
  80. package/dist/llms/card.md +447 -0
  81. package/dist/llms/carousel-dialog.md +156 -0
  82. package/dist/llms/category-bar.md +193 -0
  83. package/dist/llms/chart-state.md +190 -0
  84. package/dist/llms/chart-widget.md +209 -0
  85. package/dist/llms/chart.md +182 -0
  86. package/dist/llms/checkbox.md +257 -0
  87. package/dist/llms/chip.md +195 -0
  88. package/dist/llms/combobox.md +164 -0
  89. package/dist/llms/composed-chart.md +508 -0
  90. package/dist/llms/confidence-cone.md +277 -0
  91. package/dist/llms/data-table.md +474 -0
  92. package/dist/llms/date-range-picker.md +272 -0
  93. package/dist/llms/description-list.md +131 -0
  94. package/dist/llms/dialog-footer-carousel.md +147 -0
  95. package/dist/llms/dialog-footer-default.md +142 -0
  96. package/dist/llms/dialog-root.md +246 -0
  97. package/dist/llms/dialog-welcome.md +223 -0
  98. package/dist/llms/dialog.md +403 -0
  99. package/dist/llms/dropdown-menu.md +193 -0
  100. package/dist/llms/empty-overlay.md +146 -0
  101. package/dist/llms/empty.md +156 -0
  102. package/dist/llms/field.md +185 -0
  103. package/dist/llms/filter-cards.md +157 -0
  104. package/dist/llms/filter-chips.md +323 -0
  105. package/dist/llms/filter-search.md +512 -0
  106. package/dist/llms/form.md +154 -0
  107. package/dist/llms/funnel-chart.md +333 -0
  108. package/dist/llms/grid.md +80 -0
  109. package/dist/llms/histogram.md +190 -0
  110. package/dist/llms/input-date-picker.md +203 -0
  111. package/dist/llms/input-otp.md +173 -0
  112. package/dist/llms/input-password.md +197 -0
  113. package/dist/llms/input-search.md +170 -0
  114. package/dist/llms/input-select.md +278 -0
  115. package/dist/llms/input-text-area.md +271 -0
  116. package/dist/llms/input-text.md +192 -0
  117. package/dist/llms/line-chart.md +369 -0
  118. package/dist/llms/link.md +209 -0
  119. package/dist/llms/loading.md +130 -0
  120. package/dist/llms/meter.md +177 -0
  121. package/dist/llms/metric.md +204 -0
  122. package/dist/llms/number-field.md +122 -0
  123. package/dist/llms/page-content.md +69 -0
  124. package/dist/llms/page-header.md +182 -0
  125. package/dist/llms/pagination.md +133 -0
  126. package/dist/llms/pie-chart.md +307 -0
  127. package/dist/llms/popover.md +252 -0
  128. package/dist/llms/progress-circle.md +126 -0
  129. package/dist/llms/progress.md +111 -0
  130. package/dist/llms/radar-chart.md +316 -0
  131. package/dist/llms/radial-bar-chart.md +319 -0
  132. package/dist/llms/radio.md +255 -0
  133. package/dist/llms/resizable.md +195 -0
  134. package/dist/llms/sankey-chart.md +208 -0
  135. package/dist/llms/scatter-chart.md +239 -0
  136. package/dist/llms/scroll-area.md +183 -0
  137. package/dist/llms/section.md +401 -0
  138. package/dist/llms/select.md +210 -0
  139. package/dist/llms/separator.md +87 -0
  140. package/dist/llms/sheet.md +202 -0
  141. package/dist/llms/sidebar-primary.md +360 -0
  142. package/dist/llms/sidebar-secondary.md +417 -0
  143. package/dist/llms/skeleton.md +81 -0
  144. package/dist/llms/slider.md +97 -0
  145. package/dist/llms/spinner.md +100 -0
  146. package/dist/llms/stack.md +80 -0
  147. package/dist/llms/stepper-item.md +309 -0
  148. package/dist/llms/stepper.md +251 -0
  149. package/dist/llms/switch.md +140 -0
  150. package/dist/llms/table.md +436 -0
  151. package/dist/llms/tabs.md +197 -0
  152. package/dist/llms/tag.md +139 -0
  153. package/dist/llms/timeline.md +361 -0
  154. package/dist/llms/timer.md +259 -0
  155. package/dist/llms/toast.md +241 -0
  156. package/dist/llms/toggle-group.md +121 -0
  157. package/dist/llms/toolbar.md +453 -0
  158. package/dist/llms/tooltip.md +164 -0
  159. package/dist/llms/treemap.md +254 -0
  160. package/dist/llms/trend-indicator.md +132 -0
  161. package/dist/llms/widget-placeholder.md +169 -0
  162. package/dist/llms/wizard.md +412 -0
  163. package/dist/llms.txt +142 -0
  164. package/dist/react.js +502 -497
  165. package/dist/react.js.map +1 -1
  166. package/dist/src/components/ui/area-chart/area-chart.d.ts +9 -4
  167. package/dist/src/components/ui/avatar/avatar.d.ts +1 -1
  168. package/dist/src/components/ui/bar-chart/bar-chart.d.ts +9 -4
  169. package/dist/src/components/ui/category-bar/category-bar.d.ts +10 -4
  170. package/dist/src/components/ui/chart/__stories__/palette-control.d.ts +48 -0
  171. package/dist/src/components/ui/chart/__tests__/chart-palette.test.d.ts +1 -0
  172. package/dist/src/components/ui/chart/chart-palette.d.ts +128 -0
  173. package/dist/src/components/ui/chart/chart.d.ts +66 -15
  174. package/dist/src/components/ui/chart/index.d.ts +4 -2
  175. package/dist/src/components/ui/chart-state/chart-state-illustrations.d.ts +6 -0
  176. package/dist/src/components/ui/chart-state/chart-state.d.ts +13 -2
  177. package/dist/src/components/ui/chart-state/index.d.ts +1 -0
  178. package/dist/src/components/ui/chart-widget/chart-widget.d.ts +64 -0
  179. package/dist/src/components/ui/chart-widget/index.d.ts +1 -0
  180. package/dist/src/components/ui/composed-chart/composed-chart.d.ts +12 -7
  181. package/dist/src/components/ui/confidence-cone/confidence-cone.d.ts +10 -5
  182. package/dist/src/components/ui/empty-overlay/empty-overlay.d.ts +1 -1
  183. package/dist/src/components/ui/funnel-chart/funnel-chart.d.ts +11 -5
  184. package/dist/src/components/ui/histogram/histogram.d.ts +10 -4
  185. package/dist/src/components/ui/label/index.d.ts +1 -1
  186. package/dist/src/components/ui/label/label.d.ts +1 -5
  187. package/dist/src/components/ui/line-chart/line-chart.d.ts +9 -4
  188. package/dist/src/components/ui/metric/metric.d.ts +13 -14
  189. package/dist/src/components/ui/pie-chart/pie-chart.d.ts +17 -8
  190. package/dist/src/components/ui/radar-chart/radar-chart.d.ts +10 -5
  191. package/dist/src/components/ui/radial-bar-chart/radial-bar-chart.d.ts +17 -6
  192. package/dist/src/components/ui/sankey-chart/sankey-chart.d.ts +10 -5
  193. package/dist/src/components/ui/scatter-chart/scatter-chart.d.ts +10 -5
  194. package/dist/src/components/ui/section/index.d.ts +1 -1
  195. package/dist/src/components/ui/section/section.d.ts +75 -6
  196. package/dist/src/components/ui/stepper-item/stepper-item.d.ts +6 -5
  197. package/dist/src/components/ui/tag/tag.d.ts +1 -1
  198. package/dist/src/components/ui/treemap/treemap.d.ts +11 -5
  199. package/dist/src/components/ui/trend-indicator/trend-indicator.d.ts +3 -7
  200. package/dist/src/components/ui/wizard/index.d.ts +1 -0
  201. package/dist/src/components/ui/wizard/wizard.d.ts +6 -0
  202. package/dist/src/hooks/index.d.ts +1 -0
  203. package/dist/src/hooks/use-wizard.d.ts +80 -0
  204. package/dist/src/index.d.ts +2 -3
  205. package/dist/ui-react.css +1 -1
  206. package/package.json +9 -3
  207. package/dist/components/ui/app-shell/app-shell.js +0 -75
  208. package/dist/components/ui/app-shell/app-shell.js.map +0 -1
  209. package/dist/components/ui/auth-layout/auth-layout.js +0 -56
  210. package/dist/components/ui/auth-layout/auth-layout.js.map +0 -1
  211. package/dist/components/ui/collapsible/collapsible.js +0 -22
  212. package/dist/components/ui/collapsible/collapsible.js.map +0 -1
  213. package/dist/src/components/ui/app-shell/app-shell.d.ts +0 -8
  214. package/dist/src/components/ui/app-shell/index.d.ts +0 -1
  215. package/dist/src/components/ui/auth-layout/auth-layout.d.ts +0 -6
  216. package/dist/src/components/ui/auth-layout/index.d.ts +0 -1
  217. package/dist/src/components/ui/collapsible/collapsible.d.ts +0 -5
  218. package/dist/src/components/ui/collapsible/index.d.ts +0 -1
  219. package/dist/src/components/ui/label/label.docs.d.ts +0 -10
@@ -0,0 +1,195 @@
1
+ # Resizable
2
+
3
+ > A group of panels separated by draggable handles that let the user resize adjacent regions along one axis. Composable parts (panel group, panel, handle); the handle is a thin divider with an optional grab-bar grip and resizes its neighbouring panels on drag or arrow keys.
4
+
5
+ **Status:** ready · **Category:** layout · **Since:** v0.23.0
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from '@acronis-platform/ui-react'
11
+ ```
12
+
13
+ ## Quick example
14
+
15
+ ```tsx
16
+ <ResizablePanelGroup orientation="horizontal">
17
+ <ResizablePanel defaultSize={50}>One</ResizablePanel>
18
+ <ResizableHandle />
19
+ <ResizablePanel defaultSize={50}>Two</ResizablePanel>
20
+ </ResizablePanelGroup>
21
+ ```
22
+
23
+ A group of panels separated by draggable handles, letting users resize adjacent
24
+ regions along one axis. Composable from a panel group, panels, and handles — the
25
+ React adapter wraps [`react-resizable-panels`](https://github.com/bvaughn/react-resizable-panels).
26
+
27
+ ## When to use
28
+
29
+ - Split layouts the user should be able to re-proportion: a sidebar + content, a
30
+ list + detail (master/detail), an editor + preview.
31
+ - Any two-or-more-pane surface where a fixed split would be too rigid.
32
+
33
+ ## When not to use
34
+
35
+ - Fixed layout chrome that shouldn't move — use a plain sidebar/grid.
36
+ - Reordering or moving items — that's drag-and-drop, not resizing.
37
+ - A single scrollable region — resizing needs at least two panels.
38
+
39
+ ## Parts
40
+
41
+ | Part | Role |
42
+ | --------------------- | ------------------------------------------------------------ |
43
+ | `ResizablePanelGroup` | Container; sets the axis via `orientation` and tracks sizes. |
44
+ | `ResizablePanel` | A resizable region (`defaultSize` / `minSize` / `maxSize`). |
45
+ | `ResizableHandle` | The draggable separator (cursor + border change on hover). |
46
+
47
+ ## Examples
48
+
49
+ ```tsx
50
+ import {
51
+ ResizablePanelGroup,
52
+ ResizablePanel,
53
+ ResizableHandle,
54
+ } from '@acronis-platform/ui-react';
55
+
56
+ // Horizontal split
57
+ <ResizablePanelGroup orientation="horizontal" className="h-64 rounded border">
58
+ <ResizablePanel defaultSize={30} minSize={20}>
59
+ Sidebar
60
+ </ResizablePanel>
61
+ <ResizableHandle />
62
+ <ResizablePanel defaultSize={70}>Content</ResizablePanel>
63
+ </ResizablePanelGroup>;
64
+
65
+ // Vertical split (panels stacked)
66
+ <ResizablePanelGroup orientation="vertical" className="h-96">
67
+ <ResizablePanel defaultSize={60}>Editor</ResizablePanel>
68
+ <ResizableHandle />
69
+ <ResizablePanel defaultSize={40}>Preview</ResizablePanel>
70
+ </ResizablePanelGroup>;
71
+ ```
72
+
73
+ > The group needs a bounded height (or width, when vertical) from its container —
74
+ > set one on the group or its parent, as in the `h-64` / `h-96` above.
75
+
76
+ ## Theming
77
+
78
+ Colors, sizes, and the cursor come from the `--ui-resizable-*` token tier in
79
+ `@acronis-platform/tokens-pd` (generated from `@acronis-platform/design-tokens`)
80
+ and resolve per brand/theme — see `tokens.yaml`. Don't hard-code values.
81
+
82
+ ## Props
83
+
84
+ | Prop | Type | Default | Required | Description |
85
+ |------|------|---------|----------|-------------|
86
+ | `orientation` | `'horizontal' | 'vertical'` | `horizontal` | no | Resize axis of the group (panel-group part). `horizontal` arranges panels in a row with vertical handles; `vertical` stacks them with horizontal handles. |
87
+ | `defaultSize` | `number` | `undefined` | no | Initial size of a panel as a percentage of the group (panel part). Panels without one share the remaining space. |
88
+ | `minSize` | `number` | `undefined` | no | Minimum size of a panel, in percent of the group (panel part). |
89
+ | `maxSize` | `number` | `undefined` | no | Maximum size of a panel, in percent of the group (panel part). |
90
+ | `collapsible` | `boolean` | `false` | no | Whether the panel can collapse below its `minSize` to a collapsed size (panel part). |
91
+ | `disableResize` | `boolean` | `false` | no | Disable resizing through the handle or panel (`disabled` on the React `ResizableHandle` / `ResizablePanel`). Named `disableResize` here so it is not confused with a root-level disabled state — resizing is a per-part capability, the group is never globally "disabled". |
92
+
93
+ ## Events
94
+
95
+ | Event | Payload | Description |
96
+ |-------|---------|-------------|
97
+ | `resize` | `undefined` | Fired as a panel's size changes during a drag (panel part). The React adapter exposes this as the panel's `onResize` callback. |
98
+
99
+ ## Content slots
100
+
101
+ | Slot | Description |
102
+ |------|-------------|
103
+ | `default` | The composed group. Author it from the parts: a panel group wrapping panels, with a handle between each adjacent pair. |
104
+
105
+ ## Behavior
106
+
107
+ Given/When/Then scenarios for the panel group, its panels, and the drag handle.
108
+
109
+ ### Dragging a handle resizes its neighbours
110
+
111
+ - **Given** a horizontal panel group with two panels split 50/50 and a handle between them,
112
+ - **When** the user drags the handle to the right,
113
+ - **Then** the left panel grows and the right panel shrinks by the same amount,
114
+ staying within each panel's `minSize` / `maxSize`.
115
+
116
+ ### Sizes are clamped to min/max
117
+
118
+ - **Given** a panel with `minSize={20}`,
119
+ - **When** the user drags the handle past the point where that panel would fall below 20%,
120
+ - **Then** the panel stops at 20% and the handle does not move further in that direction.
121
+
122
+ ### Keyboard resizing
123
+
124
+ - **Given** keyboard focus on a handle,
125
+ - **When** the user presses the Arrow keys along the resize axis (Left/Right for a
126
+ horizontal group, Up/Down for a vertical group),
127
+ - **Then** the adjacent panels resize by a step, and **Home** / **End** jump to the
128
+ handle's min / max extent.
129
+
130
+ ### Orientation flips the axis
131
+
132
+ - **Given** a group with `orientation="vertical"`,
133
+ - **When** it renders,
134
+ - **Then** the panels stack in a column, the handle becomes a horizontal divider
135
+ (`aria-orientation="horizontal"`), and the cursor over it is `ns-resize`.
136
+
137
+ ### Disabled handles don't resize
138
+
139
+ - **Given** a handle (or its panels) is `disabled`,
140
+ - **When** the user drags or arrow-keys it,
141
+ - **Then** the panels do not resize through that handle.
142
+
143
+ ### Collapsible panels
144
+
145
+ - **Given** a `collapsible` panel with a `minSize`,
146
+ - **When** the user drags below that `minSize`,
147
+ - **Then** the panel collapses to its collapsed size, and dragging back out (or
148
+ calling the panel's `expand()` method) restores it.
149
+
150
+ ## Accessibility
151
+
152
+ ## Roles
153
+
154
+ - The **handle** is a `separator` (`role="separator"`) — a focusable, operable
155
+ window splitter, not a decorative one. It carries `aria-orientation`
156
+ (`vertical` for a horizontal group's vertical divider, `horizontal` for a
157
+ vertical group's horizontal divider).
158
+ - The **panel group** is a generic `group` container; **panels** are generic
159
+ regions. Give a panel a meaningful label (`aria-label` / `aria-labelledby`) when
160
+ its content isn't self-describing.
161
+
162
+ ## Keyboard
163
+
164
+ | Key | Action |
165
+ | ---------------------- | ------------------------------------------------------------- |
166
+ | `Tab` / `Shift+Tab` | Move focus to / from the handle. |
167
+ | `Arrow` along the axis | Resize the adjacent panels by a step (Left/Right or Up/Down). |
168
+ | `Home` / `End` | Resize to the handle's minimum / maximum extent. |
169
+ | `Enter` | Toggle a collapsible panel between collapsed and expanded. |
170
+
171
+ The handle is reachable and fully operable by keyboard — resizing never requires a
172
+ pointer.
173
+
174
+ ## Focus
175
+
176
+ - The handle shows a visible focus ring on `:focus-visible` (3px
177
+ `--ui-focus-primary`), distinct from hover, so keyboard users can see which
178
+ handle is active.
179
+ - Focus order follows the DOM: panel content, then the handle, then the next
180
+ panel.
181
+
182
+ ## Screen readers
183
+
184
+ - As a `separator` with `aria-orientation`, the handle is announced as a
185
+ resizable splitter. `aria-valuenow` / `aria-valuemin` / `aria-valuemax` are
186
+ managed by the underlying panel library to convey the current split.
187
+ - The handle has no decorative children — its visual affordance is the cursor
188
+ change and the border color shift on hover/active.
189
+
190
+ ## Contrast
191
+
192
+ - The divider line uses `--ui-border-on-surface-border` (idle) and
193
+ `--ui-resizable-border-color-hover` / `-active`, which resolve per brand/theme;
194
+ they must keep a visible contrast against the adjacent panel surfaces in both
195
+ light and dark schemes.
@@ -0,0 +1,208 @@
1
+ # SankeyChart
2
+
3
+ > A typed Sankey flow-diagram composition over the shared `Chart` primitives. Renders a graph of `nodes` + `links` where each link's width is proportional to its flow value, inside a `ChartContainer`, with token-themed node bars and link ribbons plus a tooltip. No axes or grid, and no variant axes; an optional count/% legend (`showLegend`) renders below the chart, and geometry (`nodePadding` / `nodeWidth` / `linkCurvature`) is plain props. Themed through custom node/link renderers (recharts' defaults paint one flat grey and have no token hooks). Built on recharts' `Sankey` primitive (no apps/demo playground existed).
4
+
5
+ **Status:** draft · **Category:** data-display · **Since:** v0.60.0
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { SankeyChart } from '@acronis-platform/ui-react'
11
+ ```
12
+
13
+ ## Quick example
14
+
15
+ ```tsx
16
+ <SankeyChart
17
+ config={config}
18
+ data={{ nodes, links }}
19
+ className="h-[360px] w-[620px]"
20
+ />
21
+ ```
22
+
23
+ A typed Sankey flow diagram built on the shared `Chart` primitives. Give it a
24
+ graph (`data.nodes` + `data.links`) and a per-node `config`; it renders a themed
25
+ recharts `Sankey` — node bars colored per name, link ribbons whose width is
26
+ proportional to the flow value and tinted by their target node — so you don't
27
+ hand-compose recharts children.
28
+
29
+ Node colors come from the `palette` prop — a dataviz palette resolving to the
30
+ `--ui-dataviz-*` tokens, `categorical` by default — not from `config`. Link
31
+ ribbons tint from their target node unless a link sets its own `color`.
32
+
33
+ > **Design-pending v1.** Built on recharts' `Sankey` primitive (no apps/demo
34
+ > playground existed). The chrome is reconciled with Figma later; Code Connect is
35
+ > deferred.
36
+
37
+ ## When to use
38
+
39
+ - Showing how a total **flows/breaks down** across stages where the width of each
40
+ flow matters (tenants → certification status, traffic → outcomes, budget → spend).
41
+ - A part-to-whole across two or more levels in one picture.
42
+
43
+ ## When not to use
44
+
45
+ - Precise value comparison — ribbon width is hard to judge; a bar chart reads better.
46
+ - A single-level part-to-whole — a pie/donut or a `CategoryBar` is clearer.
47
+ - Very dense graphs (many nodes/links) — ribbons overlap and labels collide.
48
+
49
+ ## Variants
50
+
51
+ None. SankeyChart has no CVA variant axes — everything is plain props: geometry
52
+ (`nodePadding` / `nodeWidth` / `linkCurvature`), `sort` (auto-order vs the given
53
+ node order), `showLabels` / `showLegend`, and a per-link `color` override
54
+ (rendered full-opacity; the default ribbon is the target color at 35%).
55
+
56
+ ## Example
57
+
58
+ ```tsx
59
+ import { SankeyChart } from '@acronis-platform/ui-react';
60
+ import type { ChartConfig } from '@acronis-platform/ui-react';
61
+
62
+ const data = {
63
+ nodes: [{ name: 'all' }, { name: 'certified' }, { name: 'expired' }],
64
+ links: [
65
+ { source: 0, target: 1, value: 209 },
66
+ { source: 0, target: 2, value: 31 },
67
+ ],
68
+ };
69
+
70
+ const config = {
71
+ all: {
72
+ label: 'All tenants',
73
+ color: 'var(--ui-background-status-strong-info)',
74
+ },
75
+ certified: {
76
+ label: 'Certified',
77
+ color: 'var(--ui-background-status-strong-info)',
78
+ },
79
+ expired: {
80
+ label: 'Expired',
81
+ color: 'var(--ui-background-status-strong-danger)',
82
+ },
83
+ } satisfies ChartConfig;
84
+
85
+ <SankeyChart config={config} data={data} className="h-[360px] w-[620px]" />;
86
+ ```
87
+
88
+ `showLegend` renders a built-in legend below the chart — a color dot + label per
89
+ node plus each node's value and its share of the largest node (the count + %
90
+ shown in the "Certification compliance" card). Pair it with `showLabels={false}`
91
+ to move naming off the chart. Give a link an explicit `color` to override its
92
+ default target tint (rendered full-opacity to match its node bar).
93
+
94
+ Node `name`s are the color keys, so they must be unique and CSS-safe;
95
+ `config[name].label` carries the human-readable text.
96
+
97
+ ## Props
98
+
99
+ | Prop | Type | Default | Required | Description |
100
+ |------|------|---------|----------|-------------|
101
+ | `data` | `{ nodes: ReadonlyArray<{ name: string }>; links: ReadonlyArray<{ source: number; target: number; value: number; color?: string }> }` | — | yes | The graph. `nodes` carry a CSS-safe `name` (the color/config key); `links` reference nodes by their index in `nodes` and carry the flow `value` that sizes the ribbon, plus an optional `color` (rendered at full opacity to match its node; omit for the target node's color at 35%). |
102
+ | `config` | `ChartConfig` | — | yes | Nodes take their colour from the container's `palette`; each entry, keyed by the node's `name`, maps that node to a `label` and an optional `tone`. Resolved into the `--color-<name>` custom properties the node bars fill from (and the link ribbons tint from). |
103
+ | `nodePadding` | `number` | `24` | no | Vertical gap between nodes in the same column. |
104
+ | `nodeWidth` | `number` | `12` | no | Thickness of each node bar. |
105
+ | `linkCurvature` | `number` | `0.5` | no | Curviness of the link ribbons (0 = straight, 1 = fully curved). |
106
+ | `sort` | `boolean` | `false` | no | Sort nodes vertically to minimize link crossings (recharts' relaxation). Defaults to false — nodes render in the given order per column, which keeps curated flows tidy; set true to auto-order. |
107
+ | `showLabels` | `boolean` | `true` | no | Render each node's `config` label beside its bar. |
108
+ | `showLegend` | `boolean` | `false` | no | Render a legend below the chart — a color dot + label per node, with its computed value (incoming flow) and share of the largest node. |
109
+ | `showTooltip` | `boolean` | `true` | no | Render the hover tooltip. |
110
+ | `tooltipContent` | `ReactElement | ((props) => ReactNode)` | — | no | Replace the default tooltip. Pass a configured ChartTooltipContent (from this library) — e.g. with a formatter / labelFormatter — to customize the tooltip content without composing recharts. Ignored when showTooltip is false. |
111
+
112
+ ## Behavior
113
+
114
+ `SankeyChart` is a typed [recharts](https://recharts.org) composition over the
115
+ shared `Chart` primitives. It renders a flow diagram from a `nodes` + `links`
116
+ graph inside a `ChartContainer`.
117
+
118
+ ```gherkin
119
+ Scenario: Render nodes and links from data and config
120
+ Given a graph with nodes (each a CSS-safe name) and links (source/target indices + value)
121
+ And a config mapping each node name to a label and color
122
+ Then one bar renders per node, filled from its --color-<name> custom property
123
+ And one ribbon renders per link, its width proportional to the link value
124
+ ```
125
+
126
+ ```gherkin
127
+ Scenario: Link ribbon color
128
+ Given a link with no explicit color
129
+ Then its ribbon is stroked in the target node's color at 35% opacity
130
+ Given a link with an explicit color
131
+ Then its ribbon is stroked in that color at full opacity (matching its node bar)
132
+ ```
133
+
134
+ ```gherkin
135
+ Scenario: Node labels
136
+ Given showLabels is true
137
+ Then each node shows its config label — to the right for nodes with outgoing
138
+ links, to the left for terminal (sink) nodes
139
+ And when showLabels is false no node labels render (e.g. an external legend names them)
140
+ ```
141
+
142
+ ```gherkin
143
+ Scenario: Legend
144
+ Given showLegend is true
145
+ Then a legend renders below the chart with a color dot + label per node
146
+ And each node's value (incoming flow, or outgoing for a source) plus its share
147
+ of the largest node as a percentage
148
+ ```
149
+
150
+ ```gherkin
151
+ Scenario: Node order
152
+ Given sort is false (the default)
153
+ Then nodes render in the order given by data.nodes within each column
154
+ Given sort is true
155
+ Then recharts reorders nodes vertically to minimize link crossings
156
+ ```
157
+
158
+ ```gherkin
159
+ Scenario: Geometry
160
+ Given nodePadding, nodeWidth, and linkCurvature
161
+ Then nodes are spaced/sized accordingly and ribbons curve by that amount
162
+ ```
163
+
164
+ ```gherkin
165
+ Scenario: Tooltip on hover
166
+ Given showTooltip is true
167
+ When the user hovers a node or link
168
+ Then a card shows a color dot matching the ribbon (its link color + opacity),
169
+ the source → target labels, and the value
170
+ ```
171
+
172
+ ```gherkin
173
+ Scenario: Minimal graph
174
+ Given a two-node, single-link graph
175
+ Then the chart renders one ribbon and does not throw
176
+ ```
177
+
178
+ ## Accessibility
179
+
180
+ - **recharts gives a Sankey no accessibility layer.** Unlike the cartesian charts,
181
+ recharts' `Sankey` (v3.8) implements no `accessibilityLayer`: it renders no
182
+ `role`, no `tabIndex`, and no generated description, so the plot is **not
183
+ keyboard-focusable** and its hover tooltip is pointer-only. Treat the chart as
184
+ an image and carry the numbers in accessible content next to it.
185
+ - A Sankey is inherently visual (ribbon width is a weak quantitative encoding).
186
+ **Pair it with a text alternative** — a caption, a summary, or an adjacent
187
+ legend/table carrying the same numbers (as the reference "Certification
188
+ compliance" usage does) — and give the chart an accessible name (`aria-label` /
189
+ `aria-labelledby` referencing a visible heading). The wrapper forwards native
190
+ `div` attributes, so `aria-*` pass through.
191
+ - Do **not** rely on color alone to distinguish nodes/flows. Keep `showLabels` on
192
+ (or supply an external legend) so each node is named, and keep `showTooltip` on
193
+ so values are recoverable on hover.
194
+ - Node labels use the `--ui-text-on-surface-primary` token (fill-foreground), so
195
+ they read on the themed surface in both modes. Node/link colors come from
196
+ `config` and are the caller's responsibility — keep adjacent nodes
197
+ distinguishable and flows legible at the low ribbon opacity (matched data-viz
198
+ colors are a design-pending item for the `--ui-chart-*` palette).
199
+ - Watch recharts issue [#4809](https://github.com/recharts/recharts/issues/4809)
200
+ on the a11y layer — if `Sankey` ever gains one, this component should adopt it
201
+ instead of relying purely on the caller's text alternative.
202
+
203
+ ## Contrast
204
+
205
+ Tooltip chrome and node labels meet contrast in both themes via the semantic
206
+ tokens. Node bar fills and link ribbon tints come from `config` and are the
207
+ caller's responsibility — pick node colors that stay distinguishable from each
208
+ other and legible as ~35%-opacity ribbons.
@@ -0,0 +1,239 @@
1
+ # ScatterChart
2
+
3
+ > A typed scatter-chart composition over the shared `Chart` primitives. Plots each `series[]` entry's points on numeric `xKey` / `yKey` axes inside a `ChartContainer`, with tooltip and legend chrome. Optionally maps a `zKey` to point size (a bubble chart). Scatter has no variant axes — its expressiveness comes from the data mapping, not a visual mode. Ported from the apps/demo `ScatterChartPlayground`.
4
+
5
+ **Status:** draft · **Category:** data-display · **Since:** v0.58.0
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { ScatterChart } from '@acronis-platform/ui-react'
11
+ ```
12
+
13
+ ## Quick example
14
+
15
+ ```tsx
16
+ <ScatterChart
17
+ config={config}
18
+ series={series}
19
+ xKey="hours"
20
+ yKey="score"
21
+ zKey="weight"
22
+ className="h-[360px] w-[520px]"
23
+ />
24
+ ```
25
+
26
+ A typed scatter-chart built on the shared `Chart` primitives. Give it a `series`
27
+ list (each `{ key, data }`), a per-series `config`, and the numeric axis fields
28
+ (`xKey` / `yKey`); it renders a themed recharts `ScatterChart` — tooltip, legend,
29
+ axes, and grid included — so you don't hand-compose recharts children. Add a
30
+ `zKey` to size points by a third field (a bubble chart).
31
+
32
+ Series colors come from the `palette` prop — a dataviz palette resolving to the
33
+ `--ui-dataviz-*` tokens, `categorical` by default — not from `config`.
34
+
35
+ > **Design-pending v1.** Ported from the apps/demo `ScatterChartPlayground`. The
36
+ > chrome is reconciled with Figma later; Code Connect is deferred.
37
+
38
+ ## When to use
39
+
40
+ - Showing the relationship/correlation between two numeric variables.
41
+ - Revealing clusters or outliers across groups (one `series` entry per group).
42
+ - Adding a third dimension via point size (`zKey` → bubble chart).
43
+
44
+ ## When not to use
45
+
46
+ - A trend over an ordered/continuous dimension — use a line or area chart.
47
+ - Comparing a quantity across discrete categories — use a bar chart.
48
+ - Part-to-whole — use a pie/donut chart.
49
+
50
+ ## Variants
51
+
52
+ None. ScatterChart has no CVA variant axes — its shape is fixed and its
53
+ expressiveness comes from the data mapping (`xKey` / `yKey` / `zKey` and the
54
+ number of `series`). Marker `shape` and bubble sizing are plain props.
55
+
56
+ ## Example
57
+
58
+ ```tsx
59
+ import { ScatterChart } from '@acronis-platform/ui-react';
60
+ import type { ChartConfig } from '@acronis-platform/ui-react';
61
+
62
+ const series = [
63
+ {
64
+ key: 'classA',
65
+ data: [
66
+ { hours: 2, score: 55 },
67
+ { hours: 6, score: 78 },
68
+ { hours: 8, score: 92 },
69
+ ],
70
+ },
71
+ {
72
+ key: 'classB',
73
+ data: [
74
+ { hours: 1, score: 70 },
75
+ { hours: 5, score: 82 },
76
+ { hours: 9, score: 95 },
77
+ ],
78
+ },
79
+ ];
80
+
81
+ const config = {
82
+ classA: { label: 'Class A', color: 'var(--ui-background-brand-secondary)' },
83
+ classB: {
84
+ label: 'Class B',
85
+ color: 'var(--ui-background-status-strong-danger)',
86
+ },
87
+ } satisfies ChartConfig;
88
+
89
+ <ScatterChart
90
+ config={config}
91
+ series={series}
92
+ xKey="hours"
93
+ yKey="score"
94
+ className="h-[360px] w-[520px]"
95
+ />;
96
+ ```
97
+
98
+ Series colors reference existing semantic `--ui-*` tokens. `--ui-background-status-strong-*`
99
+ is chromatic in every brand; `--ui-background-brand-secondary` is brand-dependent
100
+ (blue in `default`, neutral in some white-label brands), so it is not color-stable
101
+ across brands until the real data-viz palette lands.
102
+
103
+ ## Props
104
+
105
+ | Prop | Type | Default | Required | Description |
106
+ |------|------|---------|----------|-------------|
107
+ | `series` | `ScatterSeries[]` | — | yes | One `<Scatter>` per entry, each `{ key, data }` with its own point array. `key` matches a `config` entry and drives its `--color-<key>` fill. A single entry gives an ungrouped scatter. |
108
+ | `config` | `ChartConfig` | — | yes | Series take their colour from the container's `palette`; each entry, keyed by a `series[].key`, maps that series to a `label` and an optional `tone`. Resolved into the `--color-<key>` custom properties the points fill from. |
109
+ | `xKey` | `string` | — | yes | Numeric field for the horizontal axis. |
110
+ | `yKey` | `string` | — | yes | Numeric field for the vertical axis. |
111
+ | `xAxisLabel` | `string` | — | no | Title rendered beneath the horizontal (X) axis. |
112
+ | `yAxisLabel` | `string` | — | no | Title rendered beside the vertical (Y) axis (rotated). |
113
+ | `xUnit` | `string` | — | no | Unit suffix appended to X-axis tick values (recharts `unit`). |
114
+ | `yUnit` | `string` | — | no | Unit suffix appended to Y-axis tick values (recharts `unit`). |
115
+ | `zKey` | `string` | — | no | Optional numeric field mapped to point size (a bubble chart), via recharts `ZAxis`. |
116
+ | `zRange` | `[number, number]` | `[60, 400]` | no | Point-size range `[min, max]` the `zKey` maps into. Ignored when `zKey` is unset (points use recharts' default size). |
117
+ | `shape` | `'circle' | 'cross' | 'diamond' | 'square' | 'star' | 'triangle' | 'wye'` | `'circle'` | no | Marker shape for every point. |
118
+ | `showGrid` | `boolean` | `true` | no | Render the CartesianGrid. |
119
+ | `showTooltip` | `boolean` | `true` | no | Render the hover tooltip. |
120
+ | `showLegend` | `boolean` | `true` | no | Render the legend. |
121
+ | `tooltipContent` | `ReactElement | ((props) => ReactNode)` | — | no | Replace the default tooltip. Pass a configured ChartTooltipContent (from this library) — e.g. with a formatter / labelFormatter — to customize the tooltip content without composing recharts. Ignored when showTooltip is false. |
122
+ | `showXAxis` | `boolean` | `true` | no | Render the X axis (its ticks and title). Set false to hide it. |
123
+ | `showYAxis` | `boolean` | `true` | no | Render the Y axis (its ticks and title). Set false to hide it. |
124
+ | `xTickFormatter` | `(value: number | string, index?: number) => string` | — | no | Format each X-axis tick value. Unlike the `unit` suffix (append-only), a formatter transforms the value — abbreviate, prefix a symbol, or map to a label. Use formatCompactNumber / formatPercent / createTickFormatter from the shared Chart primitives, or any function. |
125
+ | `yTickFormatter` | `(value: number | string, index?: number) => string` | — | no | Format each Y-axis tick value (see xTickFormatter). |
126
+ | `xAxisAngle` | `number` | — | no | Rotate the X-axis tick labels by this many degrees (a negative angle tilts them up toward the right); the tick anchor + axis height adjust. |
127
+ | `xAxisInterval` | `number | 'preserveStart' | 'preserveEnd' | 'preserveStartEnd' | 'equidistantPreserveStart'` | — | no | X-axis tick density — a recharts placement strategy, or a fixed number of ticks to skip between two rendered ones (recharts interval: 0 shows every tick, 1 every other one, 2 every third). |
128
+ | `yAxisTickCount` | `number` | — | no | Desired number of ticks on the value axis (recharts tickCount; a hint, not exact). Applies to whichever axis holds the values — Y for most charts, X for BarChart with orientation="horizontal". |
129
+ | `yAxisDomain` | `'auto' | 'dataMin-dataMax' | 'zero'` | — | no | Value-axis domain preset — auto (fit the data at both ends; the axis need not include 0), zero (anchor the axis at 0, which is also recharts' behaviour when the prop is omitted), or dataMin-dataMax (tight to the data, no padding). Applies to whichever axis holds the values — Y for most charts, X for BarChart with orientation="horizontal". |
130
+ | `gridDashed` | `boolean` | — | no | Draw grid lines dashed instead of solid. |
131
+ | `gridHorizontal` | `boolean` | — | no | Show horizontal grid lines (defaults to the chart's own default when unset). |
132
+ | `gridVertical` | `boolean` | — | no | Show vertical grid lines (defaults to the chart's own default when unset). |
133
+ | `animate` | `boolean` | `false` | no | Enable entrance animation. Off by default so output/baselines are unchanged. |
134
+ | `animationDuration` | `number` | — | no | Animation duration in ms. |
135
+ | `animationBegin` | `number` | — | no | Delay before the animation starts, in ms. |
136
+ | `animationEasing` | `'ease' | 'ease-in' | 'ease-out' | 'ease-in-out' | 'linear'` | — | no | Easing curve. |
137
+
138
+ ## Behavior
139
+
140
+ `ScatterChart` is a typed [recharts](https://recharts.org) composition over the
141
+ shared `Chart` primitives. It plots each `series[]` entry's points on numeric
142
+ `xKey` / `yKey` axes inside a `ChartContainer`, optionally sizing points by a
143
+ `zKey` (bubble chart).
144
+
145
+ ```gherkin
146
+ Scenario: Render points from series and config
147
+ Given a series list, each { key, data }, and a config mapping each key to a label and color
148
+ Then one <Scatter> renders per series
149
+ And each series' points fill from its injected --color-<key> custom property
150
+ ```
151
+
152
+ ```gherkin
153
+ Scenario: Single (ungrouped) scatter
154
+ Given series has one entry
155
+ Then a single set of points renders against the x/y axes
156
+ ```
157
+
158
+ ```gherkin
159
+ Scenario: Grouped scatter
160
+ Given series has two or more entries
161
+ Then each renders as its own colored set of points
162
+ And the legend distinguishes them by color + label
163
+ ```
164
+
165
+ ```gherkin
166
+ Scenario: Bubble sizing
167
+ Given a zKey is supplied
168
+ Then a ZAxis maps that field to point size across zRange
169
+ But when zKey is omitted every point uses a fixed size
170
+ ```
171
+
172
+ ```gherkin
173
+ Scenario: Marker shape
174
+ Given shape is one of circle / cross / diamond / square / star / triangle / wye
175
+ Then every point renders with that marker glyph
176
+ ```
177
+
178
+ ```gherkin
179
+ Scenario: Tooltip on hover
180
+ Given showTooltip is true
181
+ When the user hovers a point
182
+ Then a card shows that point's axis values
183
+ ```
184
+
185
+ ```gherkin
186
+ Scenario: Legend
187
+ Given showLegend is true
188
+ Then a swatch + label renders for each series
189
+ ```
190
+
191
+ ```gherkin
192
+ Scenario: Empty series
193
+ Given series is an empty array
194
+ Then the chart renders its axes and grid with no points and does not throw
195
+ ```
196
+
197
+ ```gherkin
198
+ Scenario: Entrance animation is opt-in
199
+ Given animate is unset
200
+ Then the series render at their final geometry with no entrance animation
201
+ And the committed visual baselines are unaffected
202
+ ```
203
+
204
+ ```gherkin
205
+ Scenario: Reduced motion
206
+ Given animate is true
207
+ And a user with prefers-reduced-motion
208
+ Then the entrance animation does not play and the series render at their final geometry
209
+ And the same applies when rendering on the server
210
+ ```
211
+
212
+ ## Accessibility
213
+
214
+ - recharts' `accessibilityLayer` is **on by default** (recharts v3), giving the
215
+ chart keyboard focus and an accessible description of the plotted points.
216
+ - A scatter chart is inherently visual. **Pair it with a text alternative** — a
217
+ caption, a summary sentence, or an adjacent data table carrying the same
218
+ numbers — and give the chart an accessible name (`aria-label` /
219
+ `aria-labelledby` referencing a visible heading) when it is meaningful on its
220
+ own. The wrapper forwards native `div` attributes, so `aria-*` pass through.
221
+ - Do **not** rely on color alone to distinguish series. Keep `showLegend` (or the
222
+ tooltip) visible so each color is paired with a text label; the `shape` marker
223
+ can add a second, non-color channel when several series overlap.
224
+ - In a bubble chart (`zKey`), size encodes a value — call it out in the caption,
225
+ since point area is hard to read precisely and impossible for a screen reader
226
+ to infer.
227
+ - The chrome (tooltip, legend, axis ticks, grid) resolves to semantic `--ui-*`
228
+ tokens that meet contrast in light and dark. **Series colors are
229
+ caller-supplied** via `config` — pick values that meet 3:1 against the surface
230
+ and are distinguishable for color-vision deficiencies. The borrowed semantic
231
+ tokens are a design-pending stopgap until the `--ui-chart-*` palette lands.
232
+ - Watch recharts issue [#4809](https://github.com/recharts/recharts/issues/4809)
233
+ on the a11y layer for heavily-customized charts.
234
+
235
+ ## Contrast
236
+
237
+ Chart chrome meets contrast in both themes via the semantic tokens. Point fills
238
+ come from `config` and are the caller's responsibility — keep overlapping points
239
+ distinguishable from each other, not just against the surface.