@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,369 @@
1
+ # LineChart
2
+
3
+ > A typed line-chart composition over the shared `Chart` primitives. Takes `data` + `config` + a set of series `dataKeys` and renders a themed recharts `LineChart` inside a `ChartContainer`, with tooltip and legend chrome. Two variant axes: `curve` (linear / monotone / step interpolation) and `lineStyle` (solid / dashed stroke); single vs multi line is driven by the number of `dataKeys`. Ported from the apps/demo `ChartPlayground`.
4
+
5
+ **Status:** draft · **Category:** data-display · **Since:** v0.58.0
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { LineChart } from '@acronis-platform/ui-react'
11
+ ```
12
+
13
+ ## Quick example
14
+
15
+ ```tsx
16
+ <LineChart
17
+ config={config}
18
+ data={data}
19
+ dataKeys={['desktop', 'mobile']}
20
+ xKey="month"
21
+ curve="monotone"
22
+ lineStyle="solid"
23
+ className="h-[320px] w-[560px]"
24
+ />
25
+ ```
26
+
27
+ A typed line-chart built on the shared `Chart` primitives. Give it `data`, a
28
+ per-series `config`, the series to plot (`dataKeys`), and the category key
29
+ (`xKey`); it renders a themed recharts `LineChart` — tooltip, legend, axes, and
30
+ grid included — so you don't hand-compose recharts children.
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 `ChartPlayground`. The chrome
36
+ > is reconciled with Figma later; Code Connect is deferred.
37
+
38
+ ## When to use
39
+
40
+ - Showing a trend over a continuous or ordered dimension (revenue by month,
41
+ latency over time).
42
+ - Comparing the trends of a few series on shared axes.
43
+
44
+ ## When not to use
45
+
46
+ - Comparing a quantity across discrete categories — use a bar chart.
47
+ - Part-to-whole of a single total — consider a pie/donut chart.
48
+ - A single metric or KPI — use a `Tag`, `Badge`, or plain text.
49
+ - Tabular detail — use `Table` / `DataTable`.
50
+
51
+ ## Variants
52
+
53
+ | Axis | Values | Effect |
54
+ | ----------- | ------------------------------ | ------------------------------------------------------------ |
55
+ | `curve` | `linear` · `monotone` · `step` | Straight, smoothed, or stepped interpolation between points. |
56
+ | `lineStyle` | `solid` · `dashed` | Solid or dashed stroke. |
57
+
58
+ Single vs multi line is not a variant — it follows from how many `dataKeys` you
59
+ plot.
60
+
61
+ ## Example
62
+
63
+ ```tsx
64
+ import { LineChart } from '@acronis-platform/ui-react';
65
+ import type { ChartConfig } from '@acronis-platform/ui-react';
66
+
67
+ const data = [
68
+ { month: 'Jan', desktop: 186, mobile: 80 },
69
+ { month: 'Feb', desktop: 305, mobile: 200 },
70
+ { month: 'Mar', desktop: 237, mobile: 120 },
71
+ ];
72
+
73
+ const config = {
74
+ desktop: { label: 'Desktop', color: 'var(--ui-background-brand-secondary)' },
75
+ mobile: {
76
+ label: 'Mobile',
77
+ color: 'var(--ui-background-status-strong-danger)',
78
+ },
79
+ } satisfies ChartConfig;
80
+
81
+ <LineChart
82
+ config={config}
83
+ data={data}
84
+ dataKeys={['desktop', 'mobile']}
85
+ xKey="month"
86
+ className="h-[320px] w-[560px]"
87
+ />;
88
+ ```
89
+
90
+ Series colors reference existing semantic `--ui-*` tokens. `--ui-background-status-strong-*`
91
+ is chromatic in every brand; `--ui-background-brand-secondary` is brand-dependent
92
+ (blue in `default`, neutral in some white-label brands), so it is not color-stable
93
+ across brands until the real data-viz palette lands.
94
+
95
+ ## Props
96
+
97
+ | Prop | Type | Default | Required | Description |
98
+ |------|------|---------|----------|-------------|
99
+ | `curve` | `'linear' | 'monotone' | 'natural' | 'basis' | 'step' | 'stepBefore' | 'stepAfter'` | `'monotone'` | no | How each line interpolates between points. `linear` = straight segments; `monotone` = a smoothed curve that never overshoots a point; `natural` = a natural cubic spline (smoother, may overshoot); `basis` = the smoothest option, and not required to pass through the points at all; `step` = right-angle segments changing at the midpoint, with `stepBefore` / `stepAfter` changing at the leading or trailing point instead. |
100
+ | `lineStyle` | `'solid' | 'dashed'` | `'solid'` | no | Stroke style of every line — solid or dashed. |
101
+ | `data` | `ReadonlyArray<Record<string, string | number | null>>` | — | yes | Row-per-point data — each row holds `xKey` plus one numeric field per series. A `null` breaks the line at that point unless `connectNulls`. |
102
+ | `config` | `ChartConfig` | — | yes | Series take their colour from the container's `palette`; each entry maps a data key to a `label` and an optional `tone`. Resolved into the `--color-<key>` custom properties the lines stroke from. |
103
+ | `dataKeys` | `string[]` | — | yes | Series to plot — one line per key. Each must exist in `config` and every data row. |
104
+ | `xKey` | `string` | — | yes | The category dimension key shared across rows. |
105
+ | `comparisonKeys` | `string[]` | — | no | Subset of `dataKeys` rendered as comparison/trend overlays (e.g. a previous quarter or year) — dashed, dimmed, and dot-less, keeping each series' own `config` color. |
106
+ | `deltaBands` | `[string, string][]` | — | no | Pairs `[current, comparison]` to shade a delta band between — a dimmed area filling the gap between the two series at each point (the QoQ/YoY difference), tinted with the first key's `config` color. |
107
+ | `xAxisLabel` | `string` | — | no | Title rendered beneath the horizontal (X) axis. |
108
+ | `yAxisLabel` | `string` | — | no | Title rendered beside the vertical (Y) axis (rotated). |
109
+ | `yUnit` | `string` | — | no | Unit suffix appended to Y-axis tick values (recharts `unit`); the X axis is categorical. |
110
+ | `strokeWidth` | `number` | `2` | no | Stroke width of each line. |
111
+ | `showDots` | `boolean` | `true` | no | Render a dot at each data point. |
112
+ | `dotSize` | `number` | `3` | no | Radius of each point's dot, in px. Its hover dot is 2px larger. |
113
+ | `showActiveDot` | `boolean` | — | no | Enlarge the hovered point's dot. Defaults to following `showDots`, so set it explicitly for a hover-only line (dots off, active dot on) or a static-only line (dots on, active dot off). |
114
+ | `lineSettings` | `Record<string, { color?: string; strokeWidth?: number; dashed?: boolean; curveType?: CurveType; showDots?: boolean; dotSize?: number; showLabel?: boolean; labelPosition?: LabelPosition }>` | — | no | Per-series style override keyed by `dataKeys` entry — anything unset falls back to the chart-wide prop, so an entry states only what differs. A series listed in `comparisonKeys` keeps its dashed, dimmed, dot-less treatment: `color` / `strokeWidth` / `curveType` still apply to it, but `showDots` / `dotSize` do not. |
115
+ | `referenceLine` | `Line | Line[] where Line = { value?: number; average?: boolean | string; label?: string; labelPosition?: 'top' | 'insideTopLeft' | 'insideTopRight' | 'insideBottomLeft' | 'insideBottomRight' }` | — | no | One or more dashed reference/average lines on the value axis. Pass a single object or an array. Per line, a fixed `value` wins; otherwise the mean of one series (`average: '<key>'`) or of every plotted series (`average: true`, which includes any `comparisonKeys` overlay). An optional `label` captions each, at the rule's top right unless `labelPosition` moves it away from a series it would sit on. The same config shape as `BarChart` / `AreaChart`. |
116
+ | `connectNulls` | `boolean` | `false` | no | Bridge `null` gaps in the data instead of breaking the line. |
117
+ | `showGrid` | `boolean` | `true` | no | Render the CartesianGrid. |
118
+ | `showTooltip` | `boolean` | `true` | no | Render the hover tooltip. |
119
+ | `showLegend` | `boolean` | `true` | no | Render the legend. |
120
+ | `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. |
121
+ | `showXAxis` | `boolean` | `true` | no | Render the X axis (its ticks and title). Set false to hide it. |
122
+ | `showYAxis` | `boolean` | `true` | no | Render the Y axis (its ticks and title). Set false to hide it. |
123
+ | `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. |
124
+ | `yTickFormatter` | `(value: number | string, index?: number) => string` | — | no | Format each Y-axis tick value (see xTickFormatter). |
125
+ | `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. |
126
+ | `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). |
127
+ | `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". |
128
+ | `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". |
129
+ | `gridDashed` | `boolean` | — | no | Draw grid lines dashed instead of solid. |
130
+ | `gridHorizontal` | `boolean` | — | no | Show horizontal grid lines (defaults to the chart's own default when unset). |
131
+ | `gridVertical` | `boolean` | — | no | Show vertical grid lines (defaults to the chart's own default when unset). |
132
+ | `animate` | `boolean` | `false` | no | Enable entrance animation. Off by default so output/baselines are unchanged. |
133
+ | `animationDuration` | `number` | — | no | Animation duration in ms. |
134
+ | `animationBegin` | `number` | — | no | Delay before the animation starts, in ms. |
135
+ | `animationEasing` | `'ease' | 'ease-in' | 'ease-out' | 'ease-in-out' | 'linear'` | — | no | Easing curve. |
136
+ | `showLabels` | `boolean` | `false` | no | Render a value label on each data point/segment. |
137
+ | `labelPosition` | `'top' | 'bottom' | 'left' | 'right' | 'center' | 'insideTop' | 'insideBottom' | 'insideLeft' | 'insideRight' | 'insideStart' | 'insideEnd'` | — | no | Where the value labels sit. |
138
+ | `labelFormatter` | `(value) => string` | — | no | Format each label value (reuses the tick formatters). |
139
+ | `showBrush` | `boolean` | `false` | no | Render a range brush beneath the chart — drag a handle (or the selected window) to zoom the series into a slice of the data. |
140
+ | `brushHeight` | `number` | `28` | no | Height of the brush strip in px. A non-positive value falls back to the default rather than erasing the brush. |
141
+ | `brushAriaLabel` | `string` | `'Chart range selector'` | no | Accessible name for the brush's two range handles, which are focusable `role="slider"` elements. Consumers localize by passing their own. |
142
+
143
+ ## Behavior
144
+
145
+ `LineChart` is a typed [recharts](https://recharts.org) composition over the
146
+ shared `Chart` primitives. It takes `data`, a per-series `config`, the series to
147
+ plot (`dataKeys`), and the category key (`xKey`), and renders a themed recharts
148
+ `LineChart` inside a `ChartContainer`.
149
+
150
+ ```gherkin
151
+ Scenario: Render lines from data and config
152
+ Given data rows and a config mapping each series key to a label and color
153
+ And dataKeys ["desktop", "mobile"]
154
+ Then one <Line> renders per dataKey
155
+ And each line strokes from its injected --color-<key> custom property
156
+ ```
157
+
158
+ ```gherkin
159
+ Scenario: Single line
160
+ Given dataKeys has one entry
161
+ Then a single line renders against the category and value axes
162
+ ```
163
+
164
+ ```gherkin
165
+ Scenario: Multiple lines
166
+ Given dataKeys has two or more entries
167
+ Then one line renders per key on shared axes
168
+ And the legend distinguishes them by color + label
169
+ ```
170
+
171
+ ```gherkin
172
+ Scenario: Curve interpolation (default monotone)
173
+ Given curve is one of linear, monotone, natural, basis, step, stepBefore, stepAfter
174
+ Then every line uses that recharts `type`
175
+ And "linear" draws straight segments, "monotone" smooths them without overshooting a point
176
+ And "natural" smooths further and may overshoot, while "basis" need not pass through the points
177
+ And "step" draws right angles at the midpoint, "stepBefore" at the leading point, "stepAfter" at the trailing one
178
+ And each type draws distinct geometry — an unrecognized value would silently fall back to straight segments
179
+ ```
180
+
181
+ ```gherkin
182
+ Scenario: Dashed line style
183
+ Given lineStyle is "dashed"
184
+ Then every line strokes with a dashed pattern
185
+ ```
186
+
187
+ ```gherkin
188
+ Scenario: Dots
189
+ Given showDots is true
190
+ Then a dot renders at each data point with radius dotSize
191
+ And hovering a point enlarges its active dot by 2px
192
+ But when showDots is false neither the static dots nor the hover active dot render
193
+ ```
194
+
195
+ ```gherkin
196
+ Scenario: Hover dot independent of the static dots
197
+ Given showActiveDot is set
198
+ Then it decides the hover dot on its own instead of following showDots
199
+ And showDots false with showActiveDot true gives a bare line that still emphasizes the hovered point
200
+ And showDots true with showActiveDot false gives static dots with no hover emphasis
201
+ ```
202
+
203
+ ```gherkin
204
+ Scenario: Restyle one series
205
+ Given lineSettings maps "mobile" to { dashed: true, strokeWidth: 3, showDots: false }
206
+ Then only the "mobile" line is dashed, thicker, and dot-less
207
+ And every other series renders from the chart-wide props
208
+ And an unset field in the entry falls back to the chart-wide prop
209
+ ```
210
+
211
+ ```gherkin
212
+ Scenario: A comparison overlay keeps its treatment
213
+ Given a series is listed in comparisonKeys
214
+ And its lineSettings entry sets showDots true
215
+ Then the series still renders dot-less — the overlay treatment wins
216
+ But its color, strokeWidth and curveType overrides still apply
217
+ ```
218
+
219
+ ```gherkin
220
+ Scenario: Per-series value labels
221
+ Given lineSettings maps a series to { showLabel: false }
222
+ And showLabels is true
223
+ Then that series renders no value labels while the others do
224
+ And a { showLabel: true } entry labels only that series with showLabels unset
225
+ ```
226
+
227
+ ```gherkin
228
+ Scenario: Reference line
229
+ Given referenceLine is { value: 250, label: "Target" }
230
+ Then a dashed rule draws across the value axis at 250, captioned "Target"
231
+ And it is drawn in the muted text token, over the series
232
+ And the axis domain extends to include it, so a target above the data maximum stays visible
233
+ And the caption sits at the rule's top right unless labelPosition moves it
234
+ ```
235
+
236
+ ```gherkin
237
+ Scenario: Averaged reference line
238
+ Given referenceLine is { average: true } (or a single series key)
239
+ Then the rule draws at the mean of every plotted series' values (or that one series)
240
+ And a comparisonKeys overlay counts as a plotted series in that mean
241
+ And null values are skipped rather than counted as zero
242
+ And when there is nothing numeric to average, no rule is drawn
243
+ ```
244
+
245
+ ```gherkin
246
+ Scenario: Multiple reference lines
247
+ Given referenceLine is an array of configs (e.g. a fixed target and an average)
248
+ Then one dashed rule draws per config
249
+ And each is resolved independently (a config with nothing to draw is skipped)
250
+ ```
251
+
252
+ ```gherkin
253
+ Scenario: Null gaps
254
+ Given a data row has a null value for a series
255
+ And connectNulls is false
256
+ Then that line breaks at the gap
257
+ But when connectNulls is true the line bridges the gap
258
+ ```
259
+
260
+ ```gherkin
261
+ Scenario: Tooltip on hover
262
+ Given showTooltip is true
263
+ When the user hovers a point
264
+ Then a card shows the category label and one row per series (indicator + value)
265
+ ```
266
+
267
+ ```gherkin
268
+ Scenario: Legend
269
+ Given showLegend is true
270
+ Then a swatch + label renders for each series in dataKeys
271
+ ```
272
+
273
+ ```gherkin
274
+ Scenario: Comparison / trend overlay
275
+ Given comparisonKeys lists a subset of dataKeys (e.g. ["lastYear"])
276
+ Then those series render dashed, dimmed, and without dots
277
+ And the remaining series render normally (current lineStyle / showDots)
278
+ And each series keeps its own config color
279
+ ```
280
+
281
+ ```gherkin
282
+ Scenario: Delta band between two series
283
+ Given deltaBands lists a pair [current, comparison] (e.g. [["thisYear","lastYear"]])
284
+ Then a dimmed area shades the gap between the two series at each point
285
+ And the band is tinted with the current key's config color and sits behind the lines
286
+ And it follows the current key's curveType, so its edges match the line it shades
287
+ And points where either series is non-numeric are left un-banded
288
+ And the band is not surfaced as its own tooltip row or legend entry
289
+ ```
290
+
291
+ ```gherkin
292
+ Scenario: Empty data
293
+ Given data is an empty array
294
+ Then the chart renders its axes and grid with no lines and does not throw
295
+ ```
296
+
297
+ ```gherkin
298
+ Scenario: Entrance animation is opt-in
299
+ Given animate is unset
300
+ Then the series render at their final geometry with no entrance animation
301
+ And the committed visual baselines are unaffected
302
+ ```
303
+
304
+ ```gherkin
305
+ Scenario: Reduced motion
306
+ Given animate is true
307
+ And a user with prefers-reduced-motion
308
+ Then the entrance animation does not play and the series render at their final geometry
309
+ And the same applies when rendering on the server
310
+ ```
311
+
312
+ ```gherkin
313
+ Scenario: Range brush
314
+ Given showBrush is true
315
+ Then a brush strip renders beneath the plot with a handle at each end
316
+ And dragging a handle (or the selected window) zooms the series to that slice
317
+ And the category axis and tooltip follow the selected range
318
+ And the brush renders whether or not the category axis is shown
319
+ And unset renders no brush
320
+ ```
321
+
322
+ ```gherkin
323
+ Scenario: Range brush keyboard and accessible name
324
+ Given showBrush is true
325
+ Then each of the two handles is reachable by Tab
326
+ And the focused handle moves one row per left/right arrow key press
327
+ And each handle exposes brushAriaLabel as its accessible name
328
+ ```
329
+
330
+ ## Accessibility
331
+
332
+ - recharts' `accessibilityLayer` is **on by default** (recharts v3), giving the
333
+ chart keyboard focus and an accessible description of the plotted points.
334
+ - The **range brush** (`showBrush`) is the only interactive control these charts
335
+ render. It adds two focusable `role="slider"` handles: Tab reaches each one and
336
+ the left/right arrow keys move the selection a row at a time, so the whole
337
+ feature is operable without a pointer.
338
+ - Both handles take their accessible name from `brushAriaLabel` (default
339
+ `'Chart range selector'`); pass your own to localize it. Never leave it to
340
+ recharts' fallback, which names the handles from a `name` field on the data
341
+ row and otherwise announces "Min value: undefined, Max value: undefined".
342
+ - The handles keep a visible focus indicator: the shared `ChartContainer`
343
+ suppresses outlines on recharts layers, so it re-enables one for
344
+ `.recharts-brush-traveller` specifically (an `outline`, since `box-shadow`
345
+ does not paint on SVG children).
346
+ - The two range captions only appear while a handle is hovered, dragged, or
347
+ focused — they are a supplement to the category axis, not a replacement for
348
+ it. Zooming changes which rows are plotted, so **pair the brush with a text
349
+ alternative that reflects the current range** rather than the full series.
350
+ - A line chart is inherently visual. **Pair it with a text alternative** — a
351
+ caption, a summary sentence, or an adjacent data table carrying the same
352
+ numbers — and give the chart an accessible name (`aria-label` /
353
+ `aria-labelledby` referencing a visible heading) when it is meaningful on its
354
+ own. The wrapper forwards native `div` attributes, so `aria-*` pass through.
355
+ - Do **not** rely on color alone to distinguish series. Keep `showLegend` (or the
356
+ tooltip) visible so each color is paired with a text label; the `lineStyle`
357
+ (solid / dashed) and `curve` variants add a non-color channel between lines.
358
+ - The chrome (tooltip, legend, axis ticks, grid) resolves to semantic `--ui-*`
359
+ tokens that meet contrast in light and dark. **Series colors are
360
+ caller-supplied** via `config` — pick values that meet 3:1 against the surface
361
+ and are distinguishable for color-vision deficiencies. The borrowed semantic
362
+ tokens are a design-pending stopgap until the `--ui-chart-*` palette lands.
363
+ - Watch recharts issue [#4809](https://github.com/recharts/recharts/issues/4809)
364
+ on the a11y layer for heavily-customized charts.
365
+
366
+ ## Contrast
367
+
368
+ Chart chrome meets contrast in both themes via the semantic tokens. Line strokes
369
+ come from `config` and are the caller's responsibility.
@@ -0,0 +1,209 @@
1
+ # Link
2
+
3
+ > An inline text link (semibold) that underlines on hover, with an optional trailing external-link icon. Navigates to an href or composes a router link. Themed by the `--ui-link-*` token tier.
4
+
5
+ **Status:** ready · **Category:** navigation · **Since:** v0.31.0
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { Link } from '@acronis-platform/ui-react'
11
+ ```
12
+
13
+ ## Quick example
14
+
15
+ ```tsx
16
+ <Link href="/docs">Documentation</Link>
17
+
18
+ {/* External */}
19
+ <Link href="https://acronis.com" external target="_blank" rel="noreferrer">
20
+ Acronis
21
+ </Link>
22
+
23
+ {/* On a backdrop / dark brand surface */}
24
+ <Link href="/docs" variant="inverse">Documentation</Link>
25
+
26
+ {/* Polymorphic — render a router link */}
27
+ <Link render={<RouterLink to="/settings" />}>Settings</Link>
28
+ ```
29
+
30
+ An inline text link (semibold) that underlines on hover, with an optional trailing
31
+ external-link icon. Navigates via `href` or composes a router link through `render`.
32
+ Themed by the `--ui-link-*` token tier, which carries one token set per surface —
33
+ `variant="normal"` (default) and `variant="inverse"` for links over a backdrop.
34
+
35
+ ## When to use
36
+
37
+ - Inline navigation within prose or UI — to another page, a section, or an external
38
+ resource (`external`).
39
+ - Over a scrim, dark brand banner, or other dark surface — with `variant="inverse"`.
40
+
41
+ ## When not to use
42
+
43
+ - For a primary/secondary **action** (submit, open dialog) — use `Button` (its
44
+ borderless `ghost`/link-style variant reads like a link but is a real button).
45
+ - For breadcrumb trails — use `Breadcrumb`.
46
+
47
+ ## Examples
48
+
49
+ ```tsx
50
+ import { Link } from '@acronis-platform/ui-react';
51
+
52
+ // Internal
53
+ <Link href="/docs">Documentation</Link>;
54
+
55
+ // External (trailing icon)
56
+ <Link
57
+ href="https://acronis.com"
58
+ external
59
+ target="_blank"
60
+ rel="noopener noreferrer"
61
+ >
62
+ Acronis
63
+ </Link>;
64
+
65
+ // Polymorphic — render a router link, keep the Link styling
66
+ <Link render={<RouterLink to="/settings" />}>Settings</Link>;
67
+
68
+ // On a backdrop / dark brand surface. Text-only and always enabled: both `external`
69
+ // and `disabled` are ignored here.
70
+ <Link href="/docs" variant="inverse">
71
+ Documentation
72
+ </Link>;
73
+
74
+ // Disabled (inert) — `variant="normal"` only; the prop is ignored on "inverse".
75
+ <Link href="/docs" disabled>
76
+ Documentation
77
+ </Link>;
78
+ ```
79
+
80
+ ## Parts
81
+
82
+ | Part | Element | Description |
83
+ | ------- | ------- | ------------------------------------------------------------------------------ |
84
+ | `label` | text | The link text (children). |
85
+ | `icon` | `<svg>` | Optional trailing external-link icon (`external`), on `variant="normal"` only. |
86
+
87
+ ## Props
88
+
89
+ | Prop | Type | Default | Required | Description |
90
+ |------|------|---------|----------|-------------|
91
+ | `variant` | `'normal' | 'inverse'` | `'normal'` | no | Which surface the link sits on (Figma's `background` property). `normal` targets ordinary surfaces via the `--ui-link-normal-*` tokens; `inverse` targets a backdrop/scrim or other dark brand surface via `--ui-link-inverse-*`. `inverse` is text-only and always enabled: it supports neither the external icon (see `external`) nor the disabled state (see `disabled`), and both props are ignored there. |
92
+ | `href` | `string` | — | no | Navigation target. Omitted when `disabled`. |
93
+ | `external` | `boolean` | `false` | no | Append a trailing external-link icon (for links that leave the app). Ignored on `variant="inverse"`: the design carries the icon layer only on the `normal` surface, so no icon is rendered there. |
94
+ | `disabled` | `boolean` | `false` | no | Render the link inert — disabled color, removed from the tab order (`tabindex=-1`), `aria-disabled`, and no navigation (href dropped). Ignored entirely on `variant="inverse"`: the design defines no disabled state on a backdrop, so the link renders exactly as an enabled one — still navigable, focusable and hoverable, with no `aria-disabled`. Omit the link when it must be inert on that surface. |
95
+
96
+ ## Events
97
+
98
+ | Event | Payload | Description |
99
+ |-------|---------|-------------|
100
+ | `click` | `MouseEvent` | Native activation (click / Enter), forwarded to the anchor. |
101
+
102
+ ## Content slots
103
+
104
+ | Slot | Description |
105
+ |------|-------------|
106
+ | `default` | The link label. |
107
+
108
+ ## Behavior
109
+
110
+ ### Rendering
111
+
112
+ **Given** an `href` and a label
113
+ **When** the link renders
114
+ **Then** it is an `<a role="link">` with the label in `--ui-link-normal-text-color-idle` (semibold,
115
+ no underline).
116
+
117
+ **Given** `external`
118
+ **Then** a trailing external-link icon is appended (`--ui-link-normal-external-icon-color-*`).
119
+
120
+ ### Surface (`variant`)
121
+
122
+ **Given** no `variant`
123
+ **Then** the link uses the `normal` surface — the `--ui-link-normal-*` token set.
124
+
125
+ **Given** `variant="inverse"`
126
+ **When** the link renders on a backdrop/scrim or dark brand surface
127
+ **Then** every state resolves its text color against
128
+ `--ui-link-inverse-text-color-{idle,hover,active}` instead. Text decoration and the
129
+ focus ring are shared with the `normal` surface (`--ui-link-global-text-decoration-*`,
130
+ `--ui-focus-primary`).
131
+
132
+ **Given** `variant="inverse"` **and** `external`
133
+ **When** the link renders
134
+ **Then** no external icon is appended — the design defines the icon layer only on the
135
+ `normal` surface, so `external` is a no-op here (as it is on an inverse Figma
136
+ instance). The link is text-only.
137
+
138
+ ### Interaction
139
+
140
+ **Given** the link
141
+ **When** the pointer hovers
142
+ **Then** the text shifts to `--ui-link-normal-text-color-hover` and the
143
+ `--ui-link-global-text-decoration-hover` underline appears (the icon shifts to its hover
144
+ color).
145
+
146
+ **Given** the link
147
+ **When** it is pressed (`:active`)
148
+ **Then** the text/icon shift to their `-active` color.
149
+
150
+ **Given** the link
151
+ **When** it receives keyboard focus
152
+ **Then** a 3px `--ui-focus-primary` ring is shown.
153
+
154
+ **Given** the link
155
+ **When** activated (click / Enter)
156
+ **Then** the native `click` fires and the browser navigates to `href`.
157
+
158
+ ### Disabled
159
+
160
+ **Given** `disabled`
161
+ **When** the link renders
162
+ **Then** it uses `--ui-link-normal-text-color-disabled`, drops its `href`, sets
163
+ `aria-disabled="true"` and `tabindex="-1"`, and does not navigate or underline.
164
+
165
+ **Given** `disabled` **and** `variant="inverse"`
166
+ **When** the link renders
167
+ **Then** `disabled` has no effect whatsoever: the link keeps its `href`, sets no
168
+ `aria-disabled`, stays in the tab order, and hovers, underlines and navigates exactly
169
+ like an enabled one. The Figma set has only four enabled inverse variants and marks the
170
+ fifth unsupported ("disable state not supported onBackdrop"), so the prop is discarded
171
+ rather than applied without its color. A link that must be inert on a backdrop should be
172
+ omitted from the UI instead.
173
+
174
+ ### Composition
175
+
176
+ **Given** a `render` prop (e.g. a router link component)
177
+ **When** the link renders
178
+ **Then** it renders as that element with the Link's classes/props merged on (Base UI
179
+ `useRender`), so client-side routing works while keeping the Link styling.
180
+
181
+ ## Accessibility
182
+
183
+ - **Role:** a native `<a>` with an `href` exposes `role="link"` and is keyboard
184
+ focusable / activatable by default.
185
+ - **Accessible name:** comes from the link text (the children). For icon-only or
186
+ ambiguous links, provide `aria-label`. The external icon is decorative and inherits
187
+ the text color.
188
+ - **External links:** when `external`, also set `target="_blank"` +
189
+ `rel="noopener noreferrer"` as appropriate; consider announcing "opens in a new tab"
190
+ in the label or an `aria-label` for screen-reader users.
191
+ - **Keyboard:** Tab focuses the link; Enter activates it (native anchor behavior).
192
+ - **Focus visible:** keyboard focus paints a 3px `--ui-focus-primary` ring; `:focus`
193
+ is not suppressed without a visible alternative.
194
+ - **Disabled:** `disabled` removes the link from the tab order (`tabindex="-1"`), sets
195
+ `aria-disabled="true"`, and drops the `href` so it is not navigable — state is not
196
+ conveyed by color alone (the control is inert). This applies to `variant="normal"`
197
+ only. On `variant="inverse"` the design defines no disabled state, so the prop is
198
+ ignored outright and the link stays fully interactive and exposed as an enabled link
199
+ to assistive tech. **Do not rely on `disabled` to make a link on a backdrop inert** —
200
+ omit the link, or render it on the `normal` surface, instead.
201
+ - **Decoration:** underline is reserved for hover/affordance; the semibold weight +
202
+ link color distinguish the link at rest. Within body copy, prefer a persistent
203
+ underline for the clearest affordance.
204
+ - **Contrast:** link / hover / active / disabled colors come from the design tokens,
205
+ authored to meet WCAG contrast against the surface. Each surface has its own set —
206
+ use `variant="inverse"` over a backdrop/scrim rather than leaving the `normal`
207
+ tokens to fail contrast there.
208
+ - **WCAG:** 1.4.3 / 1.4.11 (contrast), 2.1.1 (keyboard), 2.4.4 (link purpose), 2.4.7
209
+ (focus visible), 4.1.2.