@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,130 @@
1
+ # Loading
2
+
3
+ > A composite loading indicator — a spinning ring plus an optional label — for four placement contexts: inline (flush in text flow), two card-like chips for a primary/secondary app surface, and a higher-contrast chip for busy/photo surfaces. Distinct from `Spinner` (the bare ring primitive it reuses for its icon): `Spinner` has no label or container and is unaffected by this addition.
4
+
5
+ **Status:** ready · **Category:** feedback · **Since:** v0.58.0
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { Loading } from '@acronis-platform/ui-react'
11
+ ```
12
+
13
+ ## Quick example
14
+
15
+ ```tsx
16
+ <Loading />
17
+ <Loading variant="onSurfacePrimary" label="Fetching your data…" />
18
+ <Loading variant="onScreen" hasLabel={false} />
19
+ ```
20
+
21
+ A composite loading indicator — a spinning ring plus an optional label — for
22
+ four placement contexts.
23
+
24
+ ## When to use
25
+
26
+ - Indicating an in-progress, indeterminate operation, with a message, in one
27
+ of four contexts: inline in text flow, as a card-like chip over an app
28
+ surface, or as a higher-contrast chip over a busy/photo/video surface.
29
+
30
+ ## When not to use
31
+
32
+ - For a small inline icon-scale spinner (e.g. inside a `Button` or `Toast`) —
33
+ those compose the internal `Spinner` primitive directly; it isn't part of
34
+ the public component set.
35
+ - For determinate progress — use `Progress`.
36
+ - For content placeholders — use a skeleton.
37
+
38
+ ## Parts
39
+
40
+ | Part | Description |
41
+ | ----- | ------------------------------------------------------------------ |
42
+ | icon | The `Spinner` primitive, sized/colored per variant, `aria-hidden`. |
43
+ | label | Optional visible text (`hasLabel`), colored per variant. |
44
+
45
+ ## Example
46
+
47
+ ```tsx
48
+ import { Loading } from '@acronis-platform/ui-react';
49
+
50
+ <Loading />
51
+ <Loading variant="onSurfacePrimary" label="Fetching your data…" />
52
+ <Loading variant="onSurfaceSecondary" />
53
+ <Loading variant="onScreen" hasLabel={false} />
54
+ ```
55
+
56
+ ## Props
57
+
58
+ | Prop | Type | Default | Required | Description |
59
+ |------|------|---------|----------|-------------|
60
+ | `variant` | `'inline' | 'onSurfacePrimary' | 'onSurfaceSecondary' | 'onScreen'` | `'inline'` | no | Placement context. `inline` sits flush in text flow; `onSurfacePrimary`/ `onSurfaceSecondary` are card-like chips for a primary/secondary app surface; `onScreen` is the higher-contrast dark chip for busy/photo/video surfaces. Each maps to its own `--ui-loading-<variant>-*` tokens. |
61
+ | `hasLabel` | `boolean` | `true` | no | Whether `label` renders visibly. When false, `label` is still exposed to assistive tech via the root's `aria-label`. |
62
+ | `label` | `string` | `'Data is loading…'` | no | The loading message. |
63
+
64
+ ## Behavior
65
+
66
+ Loading is a pure function of its props — no internal state, no interaction.
67
+ It renders continuously (via `Spinner`) while mounted.
68
+
69
+ ```gherkin
70
+ Scenario: Default variant
71
+ Given a Loading with no props
72
+ Then it renders the inline variant with a 16px spinner and a visible label
73
+ And the label reads "Data is loading…"
74
+ ```
75
+
76
+ ```gherkin
77
+ Scenario: Card variants
78
+ Given a Loading with variant="onSurfacePrimary" (or "onSurfaceSecondary")
79
+ Then it renders a rounded, padded chip with a 32px spinner stacked above the label
80
+ ```
81
+
82
+ ```gherkin
83
+ Scenario: On-screen variant
84
+ Given a Loading with variant="onScreen"
85
+ Then it renders a higher-contrast dark chip with a 48px white spinner and white label,
86
+ suited to placement over busy/photo/video surfaces
87
+ ```
88
+
89
+ ```gherkin
90
+ Scenario: Custom label
91
+ Given a Loading with label="Uploading files…"
92
+ Then the visible label (or, when hasLabel is false, the root's aria-label) reads that text
93
+ ```
94
+
95
+ ```gherkin
96
+ Scenario: Label hidden but still accessible
97
+ Given a Loading with hasLabel={false}
98
+ Then no visible label renders
99
+ And the root carries aria-label equal to `label`, so assistive tech still announces it
100
+ ```
101
+
102
+ ```gherkin
103
+ Scenario: Reduced motion
104
+ Given a user with prefers-reduced-motion
105
+ Then the platform animation honors that preference (the ring is still shown)
106
+ ```
107
+
108
+ ## Accessibility
109
+
110
+ - The root is `role="status"` (a polite live region) — mounting it announces
111
+ the loading state without stealing focus.
112
+ - The `Spinner` icon is rendered `aria-hidden="true"`: it is purely decorative
113
+ motion here, since the root already owns the accessible name/announcement.
114
+ This also prevents assistive tech from double-announcing `Spinner`'s own
115
+ built-in "Loading" label alongside Loading's own label.
116
+ - When `hasLabel` is true (default), the visible label's text content is the
117
+ live region's announcement — no separate `aria-label` is needed or set.
118
+ - When `hasLabel` is false, the root carries `aria-label={label}` so the
119
+ loading state is still announced even though nothing is shown on screen.
120
+ - Pair with real content once the operation completes; Loading has no
121
+ "complete" state of its own — remove it from the DOM (or swap it for the
122
+ loaded content) when the operation finishes.
123
+
124
+ ## Contrast
125
+
126
+ Each variant wires its own icon/label color tokens
127
+ (`--ui-loading-<variant>-icon-color` / `-label-color`), so contrast against the
128
+ variant's own container background is guaranteed independent of the ambient
129
+ page background — this is why `onScreen` exists as a distinct, higher-contrast
130
+ variant for busy/photo/video surfaces rather than reusing `onSurfacePrimary`.
@@ -0,0 +1,177 @@
1
+ # Meter
2
+
3
+ > A labelled bar showing a scalar value within a known range — a fractional value / share (`role="meter"`, mirroring the HTML `<meter>` element), as opposed to `Progress` which tracks a task over time. One row: label + `value · %` over a proportional track bar, with a hover tooltip; designed to be stacked into a ranked breakdown (a "bar list"). Design-pending v1 (no `--ui-chart-*` palette; the fill color is caller-supplied per row).
4
+
5
+ **Status:** draft · **Category:** data-display · **Since:** v0.58.0
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { Meter } from '@acronis-platform/ui-react'
11
+ ```
12
+
13
+ ## Quick example
14
+
15
+ ```tsx
16
+ <Meter
17
+ label="Critical"
18
+ value={6}
19
+ max={29}
20
+ color="var(--ui-background-status-strong-danger)"
21
+ />
22
+ ```
23
+
24
+ A labelled proportional bar for a value within a known range — a fractional
25
+ value / share. Built on Base UI's `Meter` (`role="meter"`, like the HTML
26
+ `<meter>` element), as opposed to `Progress` / `ProgressCircle`, which track a
27
+ task over time. One row: label + `value · %` over a track bar, with a hover
28
+ tooltip; stack several to build a ranked breakdown (a "bar list").
29
+
30
+ > **Design-pending v1.** No chart token tier yet, so the fill color is
31
+ > **caller-supplied** per row via `color` (a dedicated `--ui-chart-*` data-viz
32
+ > palette is a pending upstream design deliverable). The tooltip uses the
33
+ > chart-tooltip look (light card). Code Connect deferred.
34
+
35
+ ## When to use
36
+
37
+ - One row of a **breakdown** — a category's value and its share of a total,
38
+ with a proportional bar (severity split, top browsers, storage by type).
39
+ - Stacked and sorted, as a ranked bar-list.
40
+
41
+ ## When not to use
42
+
43
+ - Task progress over time (uploads, loading) — use
44
+ [`Progress`](/components/progress) / `ProgressCircle`.
45
+ - Many categories compared without a part-to-whole reading — a bar chart.
46
+
47
+ ## Example
48
+
49
+ ```tsx
50
+ import { Meter } from '@acronis-platform/ui-react';
51
+
52
+ <Meter
53
+ label="Critical"
54
+ value={6}
55
+ max={29}
56
+ color="var(--ui-background-status-strong-danger)"
57
+ />;
58
+ ```
59
+
60
+ Stack several sharing one `max` (the total), sorted by value, for a ranked
61
+ breakdown:
62
+
63
+ ```tsx
64
+ const rows = [
65
+ {
66
+ label: 'High',
67
+ value: 9,
68
+ color: 'var(--ui-background-status-strong-warning)',
69
+ },
70
+ {
71
+ label: 'Medium',
72
+ value: 8,
73
+ color: 'var(--ui-background-status-strong-info)',
74
+ },
75
+ {
76
+ label: 'Critical',
77
+ value: 6,
78
+ color: 'var(--ui-background-status-strong-danger)',
79
+ },
80
+ ];
81
+ const total = rows.reduce((sum, r) => sum + r.value, 0);
82
+
83
+ <div className="flex flex-col gap-4">
84
+ {rows
85
+ .sort((a, b) => b.value - a.value)
86
+ .map((r) => (
87
+ <Meter
88
+ key={r.label}
89
+ label={r.label}
90
+ value={r.value}
91
+ max={total}
92
+ color={r.color}
93
+ />
94
+ ))}
95
+ </div>;
96
+ ```
97
+
98
+ The fill color references an existing semantic `--ui-*` token; the status tokens
99
+ are chromatic across brands, so they read consistently until the real data-viz
100
+ palette lands.
101
+
102
+ ## Props
103
+
104
+ | Prop | Type | Default | Required | Description |
105
+ |------|------|---------|----------|-------------|
106
+ | `label` | `string` | — | yes | Row label shown on the left. |
107
+ | `value` | `number` | — | yes | The value this meter represents. |
108
+ | `max` | `number` | `100` | no | Upper bound of the range — the whole the value is a share of. |
109
+ | `color` | `string` | — | yes | Fill color for the bar — an existing semantic `--ui-*` token (or any CSS color). Caller-supplied; there is no chart palette tier yet. |
110
+ | `valueFormatter` | `(value: number) => string` | `toLocaleString` | no | Format the numeric value in the label + tooltip. |
111
+ | `showTooltip` | `boolean` | `true` | no | Show the hover tooltip (`label · value of max · %`). |
112
+ | `tooltip` | `ReactNode` | — | no | Custom tooltip content — replaces the default (dot + label + `value of max · %`) inside the same chart-style card. Ignored when `showTooltip` is false. |
113
+ | `defaultOpen` | `boolean` | — | no | Render with the tooltip initially open (Base UI `defaultOpen`). |
114
+
115
+ ## Behavior
116
+
117
+ `Meter` is a labelled proportional bar for a value within a range (Base UI
118
+ `Meter`, `role="meter"`).
119
+
120
+ ```gherkin
121
+ Scenario: Render a value's share
122
+ Given a label, value, and max
123
+ Then the fill spans value / max of the track (Base UI sizes the indicator)
124
+ And the row shows the formatted value and `· <pct>%` on the right
125
+ And the fill uses the caller-supplied color
126
+ ```
127
+
128
+ ```gherkin
129
+ Scenario: Accessible value
130
+ Given value and max
131
+ Then the meter exposes role="meter" with aria-valuenow / aria-valuemin (0) /
132
+ aria-valuemax (max), an accessible name from the label, and an
133
+ aria-valuetext of "value of max (pct%)"
134
+ ```
135
+
136
+ ```gherkin
137
+ Scenario: Tooltip on hover
138
+ Given showTooltip is true (the default)
139
+ When the user hovers or focuses the meter
140
+ Then a chart-style tooltip card (light surface + border + shadow) shows a color
141
+ dot, the label, and "value of max · pct%"
142
+ And with showTooltip false, no tooltip is wired
143
+ ```
144
+
145
+ ```gherkin
146
+ Scenario: Zero or empty range
147
+ Given max is 0 (or value is 0)
148
+ Then the share reads 0% and the fill is empty, without dividing by zero
149
+ ```
150
+
151
+ ```gherkin
152
+ Scenario: Stacked into a ranked breakdown
153
+ Given several meters sharing one max (the total), sorted by value
154
+ Then they read as a ranked bar-list of shares
155
+ ```
156
+
157
+ ## Accessibility
158
+
159
+ - Built on Base UI `Meter`, so the root carries `role="meter"` with
160
+ `aria-valuenow` / `aria-valuemin` (0) / `aria-valuemax` (the `max`), an
161
+ accessible name wired from `Meter.Label` (`aria-labelledby`), and an
162
+ `aria-valuetext` giving the human-readable "value of max (pct%)".
163
+ - `role="meter"` (not `progressbar`) is deliberate — a meter is a scalar value
164
+ within a known range, not task progress over time. Screen readers announce it
165
+ as a gauge/measurement.
166
+ - The percentage and value are real text in the row, so the meaning is in the
167
+ accessible tree, not only the bar. **Don't rely on the fill color alone** to
168
+ distinguish stacked meters — pair each with its label (already shown).
169
+ - The tooltip repeats the value/share; it's supplementary. When it's shown the
170
+ meter root is focusable (`tabIndex={0}`), so keyboard users reach it on focus,
171
+ not just hover. The bar's color is caller-supplied, so pick a token with enough
172
+ contrast on the surface.
173
+
174
+ ## Contrast
175
+
176
+ The label, value, track, and tooltip resolve semantic `--ui-*` tokens that meet
177
+ contrast in both themes. The fill color is the caller's responsibility.
@@ -0,0 +1,204 @@
1
+ # Metric
2
+
3
+ > A presentational stats strip: an optional info-tinted icon badge + primary value + unit on the left, an optional caption on the right, an optional trend row (auto-composed from `trend` + `trendValue` as a `TrendIndicator`), optional supporting text, and an optional `children` body (a chart, Separator, insight line, …). No Card wrapper, no size or status axes — nest inside `ChartWidget` or a `Card` when card chrome is needed. It owns visual hierarchy and layout only; it never computes or formats the value or decides whether a change is good or bad. Design-pending v1.
4
+
5
+ **Status:** draft · **Category:** data-display
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { Metric } from '@acronis-platform/ui-react'
11
+ ```
12
+
13
+ ## Quick example
14
+
15
+ ```tsx
16
+ <Metric
17
+ value="73"
18
+ unit="%"
19
+ caption={<Tag>Last 30 days</Tag>}
20
+ icon={<ChartPieIcon />}
21
+ trend="down"
22
+ trendValue="5%"
23
+ supportingText="Target: 80%"
24
+ >
25
+ <BarChart {...} />
26
+ <Separator className="my-3" />
27
+ <p>Margin eroding — check labor cost per client…</p>
28
+ </Metric>
29
+ ```
30
+
31
+ A presentational metric / statistic **card**, modelled on the Figma MetricCard
32
+ node: a label + optional caption over a primary value (with an optional
33
+ status-tinted icon badge, unit, and trend), plus an optional body for a chart,
34
+ breakdown, or insight.
35
+
36
+ ## When to use
37
+
38
+ - A dashboard KPI tile: a headline number with a trend and a small visual.
39
+ - Any "value + context" surface (health score, coverage, ARR, MTTR, at-risk
40
+ count, …).
41
+
42
+ ## When not to use
43
+
44
+ - To plot a series over time — use a Line / Area / Composed chart (compose it as
45
+ the Metric body).
46
+ - To compute the value or the trend — the consumer passes a ready-formatted
47
+ `value` and a resolved `status`; Metric never does maths or business rules.
48
+
49
+ ## Anatomy
50
+
51
+ ```
52
+ GROSS MARGIN [Last 30 days] ← label + caption
53
+ [◐] 73 % ↘ 5% vs prev 30d ← icon badge + value + unit · trend
54
+ —————————————————————————————————————— ← (children body: chart / Separator / insight)
55
+ ```
56
+
57
+ ## Composition
58
+
59
+ Metric is a Card. Put the trend in the `trend` slot (a `TrendIndicator`), a
60
+ timeframe in `caption` (a `Tag`), and drop a chart / `Meter` breakdown /
61
+ `Separator` / insight line into `children`:
62
+
63
+ ```tsx
64
+ <Metric
65
+ label="At-risk customers"
66
+ status="critical"
67
+ icon={<ChartPieIcon />}
68
+ caption={<Tag>Now</Tag>}
69
+ value="3"
70
+ trend={
71
+ <TrendIndicator
72
+ direction="up"
73
+ sentiment="negative"
74
+ value="1"
75
+ size="small"
76
+ />
77
+ }
78
+ >
79
+ <Meter
80
+ label="Healthy"
81
+ value={46}
82
+ max={54}
83
+ color="var(--ui-background-status-strong-success)"
84
+ />
85
+ <Separator className="my-3" />
86
+ <p>+3 customers predicted at-risk within 30 days.</p>
87
+ </Metric>
88
+ ```
89
+
90
+ ## Notes
91
+
92
+ - **Design-pending v1** — the Figma node is a reference, not a published
93
+ component; no dedicated `--ui-metric-*` token tier yet.
94
+ - Value may be numeric or a ReactNode; the kit never formats it.
95
+ - `status` (`neutral | info | success | warning | danger | critical`) tints the
96
+ icon badge only (subtle) — the `--ui-background-status-<status>-pressed` fill +
97
+ the `--ui-text-on-status-<status>` icon color — never a full color fill, so
98
+ many metrics stay calm together.
99
+
100
+ ## Props
101
+
102
+ | Prop | Type | Default | Required | Description |
103
+ |------|------|---------|----------|-------------|
104
+ | `value` | `ReactNode` | — | yes | The primary value, already formatted (`73`, `"94%"`, `"$72K"`, `"2.8"`). The kit does not format currency, units, or decimals. |
105
+ | `unit` | `ReactNode` | — | no | Unit shown next to the value at a smaller, muted size — e.g. "%" or "hours". |
106
+ | `caption` | `ReactNode` | — | no | Caption at the right end of the stats row — e.g. a timeframe `Tag`. |
107
+ | `trend` | `'up' | 'down' | 'stable'` | — | no | Trend direction — renders a `TrendIndicator` on its own row below the value. Sentiment follows direction automatically: `up` → positive, `down` → negative, `stable` → neutral. Pair with `trendValue` for the change text. |
108
+ | `trendValue` | `ReactNode` | — | no | Already-formatted change text shown next to the trend arrow — e.g. "20%", "+3". Requires `trend`. |
109
+ | `supportingText` | `ReactNode` | — | no | Secondary line below the trend — e.g. a target or note. |
110
+ | `badge` | `ReactNode` | — | no | A small badge / metadata slot beside the value — e.g. a Tag. |
111
+ | `icon` | `ReactNode` | — | no | Icon rendered in a status-info-tinted badge before the value. Always uses the info tint — the badge is a contextual cue, not a status signal. The icon is cloned to 16 px (icons-react sizes from a `size` prop). |
112
+ | `tooltip` | `ReactNode` | — | no | Contextual hint shown on an info affordance next to the value (Base UI Tooltip). |
113
+ | `tooltipLabel` | `string` | `More information` | no | Accessible name for the info affordance that reveals `tooltip`. |
114
+ | `loading` | `boolean` | `false` | no | Show a skeleton in place of the value, preserving its space. |
115
+
116
+ ## Content slots
117
+
118
+ | Slot | Description |
119
+ |------|-------------|
120
+ | `default` | Content below the stats strip (`children`) — e.g. a chart, a `Separator`, an AI-insight line. Composed by the consumer. |
121
+
122
+ ## Behavior
123
+
124
+ ### Renders the value
125
+
126
+ - **Given** `value`, `unit`
127
+ **Then** the value is the highest-hierarchy element (`text-2xl font-semibold`)
128
+ with the unit beside it at a smaller muted size — both share one baseline row.
129
+
130
+ ### Stats row layout
131
+
132
+ - **Given** any combination of `icon`, `value`, `unit`, `badge`, `tooltip`, `caption`
133
+ **Then** the left side of the stats row holds icon badge → value → unit → badge
134
+ → tooltip affordance (in that order); the right side holds the optional caption.
135
+ The row is `justify-between`, so left and right sit at the ends.
136
+
137
+ ### Composes a trend
138
+
139
+ - **Given** `trend="up"` (or `"down"` or `"stable"`)
140
+ **Then** a `TrendIndicator` renders on its own row below the stats row.
141
+ Direction and sentiment are derived automatically: `up` → positive,
142
+ `down` → negative, `stable` → neutral. Pair with `trendValue` for the change
143
+ text. Metric never computes or interprets the values.
144
+
145
+ ### Value is caller-formatted
146
+
147
+ - **Given** `value="$72K"` (or `value={82}`, or a ReactNode)
148
+ **Then** it renders verbatim — the kit never formats currency, units, or
149
+ decimals, and never decides whether the value is good or bad.
150
+
151
+ ### Icon badge is always info-tinted
152
+
153
+ - **Given** an `icon`
154
+ **Then** it renders in a fixed `size-9` rounded badge using the info status
155
+ tint (`--ui-background-status-info` fill, `--ui-glyph-on-surface-neutral-dark`
156
+ icon color) unconditionally — the badge is a contextual slot, not a status
157
+ signal.
158
+
159
+ ### Loading
160
+
161
+ - **Given** `loading`
162
+ **Then** a `Skeleton` renders in place of the value, preserving its space.
163
+ - No data: the consumer passes `value="—"` — never `0`, which is a real value.
164
+
165
+ ### Tooltip
166
+
167
+ - **Given** a `tooltip`, **then** an info affordance (`CircleInfoIcon`, 16 px,
168
+ named by `tooltipLabel`) appears next to the value and reveals the hint on
169
+ hover/focus; it is keyboard-reachable via Base UI `Tooltip`.
170
+
171
+ ### Body
172
+
173
+ - **Given** `children` (a chart, a `Separator`, an insight line)
174
+ **Then** they render below the stats strip. No card chrome wraps them — Metric
175
+ is a plain `<div>`.
176
+
177
+ ## Accessibility
178
+
179
+ - **DOM order matches reading order**: icon badge → value + unit → badge →
180
+ tooltip affordance (left), caption (right), then trend, supporting text, body.
181
+ Assistive tech reads a coherent "73 % ↓ 5% …".
182
+ - The unit stays adjacent to the value so they're announced together.
183
+ - The icon in the badge is decorative (`aria-hidden`). The badge tint is always
184
+ the info color — it is a contextual slot, not a status signal, so it carries
185
+ no meaning that must be communicated via ARIA.
186
+ - **Tooltip affordance**: when `tooltip` is set, the info trigger is a real
187
+ focusable element named by `tooltipLabel` (default "More information"), so it
188
+ is keyboard-reachable and announced. The tooltip must not be the only source
189
+ of essential information.
190
+ - **Trend**: the rendered `TrendIndicator` is decorative by default (glyph +
191
+ text, no `role="img"`). Supply an `ariaLabel` on the TrendIndicator directly
192
+ when a screen reader needs the full sentence ("Revenue down 5% vs last
193
+ quarter").
194
+ - Abbreviations (ARR, MTTR) may need a `tooltip` / accessible expansion supplied
195
+ by the consumer.
196
+ - Dynamically-updating values are not announced via `aria-live` unless the
197
+ consumer wraps them.
198
+
199
+ ## Contrast
200
+
201
+ The value resolves the primary surface-text token; unit, supporting text, and
202
+ the tooltip icon use the secondary token. The info badge pairs
203
+ `--ui-background-status-info` with `--ui-glyph-on-surface-neutral-dark`. All
204
+ meet contrast in light and dark.
@@ -0,0 +1,122 @@
1
+ # NumberField
2
+
3
+ > A numeric input with decrement / increment steppers, min/max/step, and scrub support. Built on Base UI's NumberField; the field box reuses the InputText token tier. Ported from the legacy shadcn-uikit `number-field`.
4
+
5
+ **Status:** draft · **Category:** forms · **Since:** v0.51.0
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { NumberField, NumberFieldGroup, NumberFieldDecrement, NumberFieldInput, NumberFieldIncrement } from '@acronis-platform/ui-react'
11
+ ```
12
+
13
+ ## Quick example
14
+
15
+ ```tsx
16
+ <NumberField defaultValue={1} min={0} max={99}>
17
+ <NumberFieldGroup>
18
+ <NumberFieldDecrement />
19
+ <NumberFieldInput />
20
+ <NumberFieldIncrement />
21
+ </NumberFieldGroup>
22
+ </NumberField>
23
+ ```
24
+
25
+ A numeric input with decrement / increment steppers, min/max/step, and keyboard
26
+ stepping. Built on Base UI's NumberField; the box reuses the InputText token tier
27
+ so it matches the other inputs.
28
+
29
+ > Design-pending v1, ported from the legacy shadcn-uikit `number-field`.
30
+
31
+ ## When to use
32
+
33
+ - Entering a bounded number where stepping by a fixed amount helps (quantity,
34
+ retention days, counts).
35
+
36
+ ## When not to use
37
+
38
+ - An approximate value across a range — use `Slider`.
39
+ - Free text — use `InputText`.
40
+
41
+ ## Parts
42
+
43
+ | Export | Purpose |
44
+ | ---------------------- | ------------------------------------------ |
45
+ | `NumberField` | Root — holds the value / min / max / step. |
46
+ | `NumberFieldGroup` | The bordered box. |
47
+ | `NumberFieldDecrement` | − stepper (defaults to a minus icon). |
48
+ | `NumberFieldInput` | The numeric input. |
49
+ | `NumberFieldIncrement` | + stepper (defaults to a plus icon). |
50
+
51
+ ## Example
52
+
53
+ ```tsx
54
+ import {
55
+ NumberField,
56
+ NumberFieldGroup,
57
+ NumberFieldDecrement,
58
+ NumberFieldInput,
59
+ NumberFieldIncrement,
60
+ } from '@acronis-platform/ui-react';
61
+
62
+ <NumberField defaultValue={3} min={0} max={99}>
63
+ <NumberFieldGroup>
64
+ <NumberFieldDecrement aria-label="Decrease" />
65
+ <NumberFieldInput aria-label="Quantity" />
66
+ <NumberFieldIncrement aria-label="Increase" />
67
+ </NumberFieldGroup>
68
+ </NumberField>;
69
+ ```
70
+
71
+ ## Props
72
+
73
+ | Prop | Type | Default | Required | Description |
74
+ |------|------|---------|----------|-------------|
75
+ | `value` | `number | null` | — | no | The value (controlled). |
76
+ | `defaultValue` | `number | null` | — | no | The initial value (uncontrolled). |
77
+ | `min` | `number` | — | no | Minimum value (clamped). |
78
+ | `max` | `number` | — | no | Maximum value (clamped). |
79
+ | `step` | `number` | `1` | no | Increment for the steppers / arrow keys. |
80
+ | `disabled` | `boolean` | `false` | no | Disables the field and steppers. |
81
+
82
+ ## Events
83
+
84
+ | Event | Payload | Description |
85
+ |-------|---------|-------------|
86
+ | `onValueChange` | `(value: number | null, eventDetails) => void` | Fired when the value changes. |
87
+
88
+ ## Behavior
89
+
90
+ ```gherkin
91
+ Scenario: Step the value
92
+ Given a NumberField with a value
93
+ When the user clicks − / + (or presses ↓ / ↑)
94
+ Then the value decrements / increments by step, clamped to min/max
95
+ ```
96
+
97
+ ```gherkin
98
+ Scenario: Type a value
99
+ Given the input is focused
100
+ When the user types a number and blurs
101
+ Then the value is parsed and clamped to min/max
102
+ ```
103
+
104
+ ```gherkin
105
+ Scenario: Disabled
106
+ Given disabled is set
107
+ Then the input and both steppers are non-interactive
108
+ ```
109
+
110
+ ## Accessibility
111
+
112
+ - Built on Base UI's NumberField: the input is keyboard-operable (↑/↓ step,
113
+ PageUp/PageDown, Home/End) and exposes the value to assistive tech; the steppers
114
+ are real `<button>`s.
115
+ - Give the steppers accessible labels ("Increase" / "Decrease") and the input a
116
+ name — via `aria-label` or by pairing the field with a `Field` / `FieldLabel`.
117
+
118
+ ## Contrast
119
+
120
+ The box reuses the InputText tier (border / value text meet contrast in light and
121
+ dark); the stepper icons use the muted `--ui-text-on-surface-secondary`, going to
122
+ the primary text on hover, and the disabled token when disabled.