@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,453 @@
1
+ # Toolbar
2
+
3
+ > A horizontal action row — list actions, an optional overflow control (e.g. a ButtonMenu), and an optional trailing area (a status text, or a selection counter + action) — typically shown above/below a list or table when rows are selected or bulk actions are available. Pure layout — no dedicated token tier; every action is an existing Button/ButtonMenu instance that brings its own tokens. Distinct from FilterSearch/DataTableToolbar (search + filter toolbars): Toolbar is a bulk-action/selection bar, not a filter bar.
4
+
5
+ **Status:** ready · **Category:** layout · **Since:** v0.57.0
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { Toolbar, ToolbarActionList, ToolbarActions } from '@acronis-platform/ui-react'
11
+ ```
12
+
13
+ ## Quick example
14
+
15
+ ```tsx
16
+ // ToolbarActionList collapses trailing actions into "More actions"
17
+ // once they no longer fit the row — no manual breakpoint wiring.
18
+ <Toolbar disabled={selectedCount === 0}>
19
+ <ToolbarActionList
20
+ actions={[
21
+ { key: 'first', label: 'First action', onSelect: () => {} },
22
+ { key: 'second', label: 'Second action', onSelect: () => {} },
23
+ ]}
24
+ />
25
+ <ToolbarActions>
26
+ <span>{selectedCount} items selected:</span>
27
+ <Button variant="ghost" onClick={clearSelection}>
28
+ Deselect
29
+ </Button>
30
+ </ToolbarActions>
31
+ </Toolbar>
32
+ ```
33
+
34
+ A horizontal action row — list actions, an optional overflow control, and an
35
+ optional trailing area — typically shown above/below a list or table when
36
+ rows are selected or bulk actions are available.
37
+
38
+ ## When to Use
39
+
40
+ - A bulk-action bar that appears when one or more rows in a table/list are
41
+ selected (e.g. "6 items selected: Deselect").
42
+ - A row of always-available actions with an overflow "More actions" menu for
43
+ actions that don't fit.
44
+ - A status row (e.g. "25 of 1250 items loaded") alongside action buttons.
45
+
46
+ ## When NOT to Use
47
+
48
+ - **Search/filtering above a table** — use `FilterSearch` or
49
+ `DataTableToolbar`. Toolbar has no search field, filter popover, or
50
+ applied-filter chips.
51
+ - **Navigation bars** — use a dedicated nav component.
52
+
53
+ ## Related Components
54
+
55
+ - **FilterSearch** / **DataTableToolbar** — search-and-filter toolbars, not
56
+ bulk-action bars. Compose both above the same table if you need filtering
57
+ and a selection action bar (e.g. `FilterSearch` always visible,
58
+ `Toolbar` shown only while rows are selected).
59
+ - **Button**, **ButtonMenu** — the action controls Toolbar arranges. Toolbar
60
+ itself renders no button; every action is a consumer-supplied instance.
61
+
62
+ ## Parts
63
+
64
+ | Part | Element / component | Role |
65
+ | ------------------- | ------------------- | ---------------------------------------------------------- |
66
+ | `Toolbar` | `<fieldset>` | Root flex container (16px gap, disabled cascade) |
67
+ | `ToolbarActionList` | `<div>` | Figma's `ListActions` — self-collapsing action row (below) |
68
+ | `ToolbarActions` | `<div>` | Right-aligned trailing area (8px gap) |
69
+
70
+ ## Behavior at a glance
71
+
72
+ - Children render in source order; `ToolbarActions`, if present, is pushed to
73
+ the trailing edge via `grow shrink-0` (not `flex-1`, which also shrinks —
74
+ the actions area must never shrink below its own content's natural width).
75
+ - `disabled` cascades to every nested Button/ButtonMenu via the native
76
+ `<fieldset disabled>` behavior — no prop-drilling required.
77
+ - No dedicated token tier: every action brings its own tokens, and the
78
+ 16px/8px gaps are un-tokenized Tailwind utilities (same precedent as
79
+ `FilterSearch`).
80
+ - **`ToolbarActionList` auto-collapses.** The Figma breakpoints spec (node
81
+ `6262:28276`) requires that actions which don't fit the available width
82
+ move into a "More actions" menu. `ToolbarActionList` measures its own row
83
+ against a `ResizeObserver` on its parent `Toolbar` and moves trailing
84
+ actions into a `ButtonMenu` + `DropdownMenu` once they no longer fit — no
85
+ manual breakpoint wiring needed. Use plain `Button`/`ButtonMenu` children
86
+ directly on `Toolbar` instead when the action list is short and fixed and
87
+ auto-collapse isn't needed.
88
+
89
+ ## Quick Examples
90
+
91
+ ### React — auto-collapsing action list
92
+
93
+ ```tsx
94
+ import {
95
+ Toolbar,
96
+ ToolbarActionList,
97
+ ToolbarActions,
98
+ Button,
99
+ } from '@acronis-platform/ui-react';
100
+
101
+ function SelectionToolbar({
102
+ selectedCount,
103
+ onDeselect,
104
+ }: {
105
+ selectedCount: number;
106
+ onDeselect: () => void;
107
+ }) {
108
+ return (
109
+ <Toolbar>
110
+ <ToolbarActionList
111
+ actions={[
112
+ { key: 'first', label: 'First action', onSelect: () => {} },
113
+ { key: 'second', label: 'Second action', onSelect: () => {} },
114
+ { key: 'third', label: 'Third action', onSelect: () => {} },
115
+ ]}
116
+ />
117
+ <ToolbarActions>
118
+ <span>{selectedCount} items selected:</span>
119
+ <Button variant="ghost" onClick={onDeselect}>
120
+ Deselect
121
+ </Button>
122
+ </ToolbarActions>
123
+ </Toolbar>
124
+ );
125
+ }
126
+ ```
127
+
128
+ ### React — fixed, manually composed actions
129
+
130
+ ```tsx
131
+ import {
132
+ Toolbar,
133
+ ToolbarActions,
134
+ Button,
135
+ ButtonMenu,
136
+ } from '@acronis-platform/ui-react';
137
+
138
+ <Toolbar>
139
+ <Button variant="ghost">First action</Button>
140
+ <Button variant="ghost">Second action</Button>
141
+ <ButtonMenu>More actions</ButtonMenu>
142
+ <ToolbarActions>
143
+ <span>25 of 1250 items loaded</span>
144
+ </ToolbarActions>
145
+ </Toolbar>;
146
+ ```
147
+
148
+ ### Disabled
149
+
150
+ ```tsx
151
+ <Toolbar disabled>
152
+ <ToolbarActionList actions={[{ key: 'first', label: 'First action' }]} />
153
+ </Toolbar>
154
+ ```
155
+
156
+ ## Spec Files
157
+
158
+ | File | Contents |
159
+ | ------------------ | -------------------------------------------------------- |
160
+ | `index.yaml` | Identity, status, category, dependencies, Figma link |
161
+ | `anatomy.yaml` | Root, parts, layout, prop states |
162
+ | `api.yaml` | Framework-agnostic contract + framework adapters |
163
+ | `tokens.yaml` | No dedicated tier — see note in the file |
164
+ | `behavior.md` | Given/When/Then behavior scenarios |
165
+ | `accessibility.md` | ARIA guidance (delegated to child components + fieldset) |
166
+
167
+ ## Props
168
+
169
+ | Prop | Type | Default | Required | Description |
170
+ |------|------|---------|----------|-------------|
171
+ | `disabled` | `boolean` | `false` | no | Disables every native form control nested inside (Button, ButtonMenu), via the platform's own fieldset-disables-descendants cascade. No prop-drilling into arbitrary children is required. |
172
+ | `className` | `string` | `undefined` | no | Additional CSS classes for the root container. |
173
+ | `actions` | `Array<{ key: string; label: Node; onSelect?: () => void; disabled?: boolean }>` | `undefined` | no | `ToolbarActionList`-only: the ordered action list it renders. As many leading actions as fit the row render as ghost Buttons; the rest move into the `more-actions` overflow menu, recomputed on resize (see `internal_state.visibleCount` in anatomy.yaml). `onSelect`/`disabled` are honored whichever way an action currently renders. |
174
+ | `moreActionsLabel` | `Node` | `'More actions'` | no | ToolbarActionList-only: label for the overflow trigger. |
175
+
176
+ ## Content slots
177
+
178
+ | Slot | Description |
179
+ |------|-------------|
180
+ | `default` | The list-action controls — either a `ToolbarActionList` (self- collapsing, see `actions` prop) or plain Button/ButtonMenu instances for a short, fixed action list — and, as the last child, an optional `actions` part (ToolbarActions) for the trailing status text or selection counter. Order of children determines visual order. |
181
+ | `actions` | ToolbarActions' children — a status text, or a selection counter + action (e.g. a "Deselect" Button). |
182
+
183
+ ## Behavior
184
+
185
+ ### Structure
186
+
187
+ #### Renders a horizontal action row
188
+
189
+ **Given** a Toolbar wrapping Button/ButtonMenu children
190
+ **When** the component renders
191
+ **Then** the root is a `<fieldset>` with a horizontal flex layout and 16px gap
192
+ **And** children are vertically centered
193
+
194
+ #### Renders with list actions only
195
+
196
+ **Given** a Toolbar containing only Button children
197
+ **When** it renders
198
+ **Then** only those buttons are shown in the row, with no trailing spacer
199
+
200
+ #### Renders with an overflow control and a trailing area
201
+
202
+ **Given** a Toolbar containing Button children, a ButtonMenu, and a
203
+ ToolbarActions child
204
+ **When** it renders
205
+ **Then** all three appear in order: list actions, overflow menu, trailing area
206
+
207
+ ---
208
+
209
+ ### Disabled
210
+
211
+ #### Disables every nested control
212
+
213
+ **Given** a Toolbar with `disabled` set to `true`, containing Button and
214
+ ButtonMenu children (including inside a ToolbarActions child)
215
+ **When** it renders
216
+ **Then** every nested Button/ButtonMenu is disabled — via the native
217
+ `<fieldset disabled>` cascade, with no explicit prop passed to each child
218
+
219
+ #### Leaves nested controls enabled by default
220
+
221
+ **Given** a Toolbar with no `disabled` prop
222
+ **When** it renders
223
+ **Then** every nested Button/ButtonMenu is enabled
224
+
225
+ #### Closes an open overflow menu when the Toolbar becomes disabled
226
+
227
+ **Given** a ToolbarActionList whose overflow menu is open
228
+ **When** the ancestor Toolbar's `disabled` becomes `true`
229
+ **Then** the menu closes and its items are disabled — the menu renders in a
230
+ portal, outside the `<fieldset>` subtree the native cascade reaches, so the
231
+ disabled state is carried to it in the same render rather than observed off
232
+ the DOM afterwards
233
+
234
+ #### Keeps the overflow menu closed once the Toolbar is re-enabled
235
+
236
+ **Given** a Toolbar that was disabled while its overflow menu was open
237
+ **When** `disabled` becomes `false` again
238
+ **Then** the menu stays closed until the user opens it again
239
+
240
+ ---
241
+
242
+ ### Actions Area
243
+
244
+ #### Pushes trailing content to the trailing edge
245
+
246
+ **Given** a Toolbar with a ToolbarActions containing a status text
247
+ **When** it renders
248
+ **Then** the actions area grows to take remaining space but never shrinks
249
+ below its own content's natural width (`grow shrink-0`, not `flex-1`)
250
+ **And** its content is right-aligned
251
+
252
+ #### Renders a selection counter with an action
253
+
254
+ **Given** a Toolbar with a ToolbarActions containing a text node and a
255
+ "Deselect" Button
256
+ **When** it renders
257
+ **Then** both are shown with an 8px gap between them, right-aligned
258
+
259
+ #### Renders without a trailing area
260
+
261
+ **Given** a Toolbar with no ToolbarActions child
262
+ **When** it renders
263
+ **Then** children are laid out from the leading edge with no trailing spacer
264
+
265
+ ---
266
+
267
+ ### Overflow (ToolbarActionList)
268
+
269
+ #### Renders every action inline when they all fit
270
+
271
+ **Given** a ToolbarActionList whose actions' combined width (plus gaps) fits
272
+ the available row width
273
+ **When** it renders
274
+ **Then** every action renders as a ghost Button in source order
275
+ **And** no "More actions" trigger is rendered
276
+
277
+ #### Collapses trailing actions into an overflow menu once they no longer fit
278
+
279
+ **Given** a ToolbarActionList whose actions no longer fit the available row
280
+ width
281
+ **When** it renders (or the row is resized narrower)
282
+ **Then** as many leading actions as fit alongside a "More actions" trigger
283
+ render inline
284
+ **And** the remaining trailing actions render as items inside the
285
+ `ButtonMenu` + `DropdownMenu` opened by that trigger
286
+
287
+ #### Accounts for sibling width when measuring available space
288
+
289
+ **Given** a ToolbarActionList rendered alongside a sibling ToolbarActions in
290
+ the same Toolbar
291
+ **When** it measures available width
292
+ **Then** it subtracts the sibling's rendered width and the gap between them
293
+ from the parent Toolbar's width, rather than assuming it owns the full row
294
+
295
+ #### Re-measures on resize
296
+
297
+ **Given** a mounted ToolbarActionList
298
+ **When** its parent Toolbar's rendered width changes
299
+ **Then** a `ResizeObserver` on the parent triggers a re-measurement and the
300
+ visible/hidden split updates accordingly
301
+
302
+ #### Preserves onSelect and disabled whether an action is inline or hidden
303
+
304
+ **Given** a ToolbarActionList item with `onSelect` and/or `disabled` set
305
+ **When** the item renders inline (a Button) or inside the overflow menu (a
306
+ DropdownMenuItem), depending on available width
307
+ **Then** `onSelect` fires from either rendering, and `disabled` is honored
308
+ in either rendering
309
+
310
+ #### Moves roving focus between visible actions with arrow keys
311
+
312
+ **Given** a mounted ToolbarActionList with focus on a visible action
313
+ **When** ArrowLeft/ArrowRight is pressed
314
+ **Then** focus moves to the previous/next visible action, and tabindex rolls
315
+ from that action to the newly-focused one (one Tab stop into the row overall)
316
+
317
+ #### Moves roving focus into the overflow trigger with arrow keys
318
+
319
+ **Given** a mounted ToolbarActionList with hidden actions and focus on the
320
+ last visible action
321
+ **When** ArrowRight is pressed
322
+ **Then** focus moves into the "More actions" overflow trigger
323
+
324
+ #### Skips a disabled action during roving-tabindex navigation
325
+
326
+ **Given** a mounted ToolbarActionList with a `disabled` action among its
327
+ visible actions
328
+ **When** arrow keys move roving focus through the row
329
+ **Then** the disabled action is unreachable — it is skipped, not merely
330
+ focusable-but-inert
331
+
332
+ ---
333
+
334
+ ### Composition
335
+
336
+ #### Supports arbitrary children
337
+
338
+ **Given** a Toolbar with custom children (not just Button/ButtonMenu)
339
+ **When** it renders
340
+ **Then** all children appear in source order within the flex container
341
+
342
+ #### Merges custom className
343
+
344
+ **Given** a Toolbar with a custom className
345
+ **When** it renders
346
+ **Then** the custom class is merged onto the root element
347
+
348
+ #### Spreads native fieldset attributes
349
+
350
+ **Given** a Toolbar with `aria-label` or other native attributes
351
+ **When** it renders
352
+ **Then** those attributes are applied to the root `<fieldset>`
353
+
354
+ ## Accessibility
355
+
356
+ `Toolbar` itself is a layout wrapper — most accessibility concerns are
357
+ delegated to its composed children (Button, ButtonMenu). Its own contribution
358
+ is the native `disabled` cascade. `ToolbarActionList`, when used, additionally
359
+ implements the WAI-ARIA `toolbar` pattern (`role="toolbar"` + roving
360
+ tabindex) on its own root — see below.
361
+
362
+ ## ARIA Roles and Attributes
363
+
364
+ ### Root (`fieldset`)
365
+
366
+ The root renders as a `<fieldset>`, reset to look like a plain flex container
367
+ (no border/margin/padding). A `<fieldset>` carries an implicit ARIA role of
368
+ `group` — acceptable for a generic control grouping. `role="toolbar"` is
369
+ **not** applied here: when the child action row needs the WAI-ARIA `toolbar`
370
+ pattern, it lives one level down on `ToolbarActionList`'s own root (below),
371
+ not on this fieldset. Plain Button/ButtonMenu children composed directly on
372
+ `Toolbar` (not through `ToolbarActionList`) each keep their own natural Tab
373
+ stop, matching `FilterSearch`'s and `DataTableToolbar`'s existing precedent
374
+ in this kit.
375
+
376
+ | Attribute | Value | Reason |
377
+ | ------------ | -------- | --------------------------------------------------------- |
378
+ | No `role` | — | Implicit `group` from `<fieldset>` |
379
+ | `disabled` | (opt-in) | Cascades to every nested form control |
380
+ | `aria-label` | (opt-in) | Consumer may set this for a landmark-like accessible name |
381
+
382
+ ### List Actions (`ToolbarActionList`)
383
+
384
+ `ToolbarActionList`'s own root implements the WAI-ARIA `toolbar` pattern via
385
+ Base UI's `Toolbar.Root`/`Toolbar.Button` (`@base-ui/react/toolbar`):
386
+ `role="toolbar"`, one Tab stop into the row, and roving `tabindex` between
387
+ every visible action and the overflow trigger, driven by arrow keys. A
388
+ disabled action opts out of Base UI's default APG toolbar
389
+ treatment (`focusableWhenDisabled={false}`) so it matches every other
390
+ disabled `Button` in this kit: unreachable via Tab or arrow keys, rather than
391
+ focusable-but-inert. The invisible measurement clones used to compute
392
+ collapse width are not registered in the roving-tabindex sequence.
393
+
394
+ | Attribute | Value | Reason |
395
+ | ---------------- | ------- | ---------------------------------------------------- |
396
+ | `role="toolbar"` | (fixed) | WAI-ARIA toolbar pattern for the action row |
397
+ | `tabindex` | roving | One Tab stop into the row; arrow keys move within it |
398
+
399
+ ---
400
+
401
+ ## Keyboard Navigation
402
+
403
+ | Component | Key | Action |
404
+ | ------------------------------------- | -------------------- | ------------------------------------------------------------------- |
405
+ | `ToolbarActionList` visible action | Enter/Space | Activates the action |
406
+ | `ToolbarActionList` overflow trigger | Enter/Space | Opens/closes the overflow `DropdownMenu` |
407
+ | `ToolbarActionList` row | ArrowLeft/ArrowRight | Moves roving focus between visible actions and the overflow trigger |
408
+ | Button/ButtonMenu (composed directly) | Enter/Space | Activates the action / opens the menu it triggers |
409
+
410
+ Plain Button/ButtonMenu children composed directly on `Toolbar` (not through
411
+ `ToolbarActionList`) keep their natural individual Tab order — the fieldset
412
+ itself does not manage their focus. When `disabled` is set, every nested
413
+ Button/ButtonMenu is removed from the Tab order automatically (native
414
+ `disabled` behavior), so no manual `tabIndex` management is needed.
415
+
416
+ ---
417
+
418
+ ## Screen Reader Requirements
419
+
420
+ 1. Each child component announces itself according to its own spec.
421
+ 2. Action buttons should have descriptive labels (e.g. "First action", not
422
+ an icon alone without an accessible name).
423
+ 3. A selection counter rendered inside `ToolbarActions` should state the
424
+ count in text (e.g. "6 items selected:") so it's announced, not conveyed
425
+ by an icon or color alone.
426
+ 4. When `disabled` is set, screen readers announce every nested control as
427
+ disabled — no additional `aria-disabled` wiring is required.
428
+
429
+ ---
430
+
431
+ ## Color and Contrast
432
+
433
+ All contrast requirements are owned by the child components and their
434
+ respective token tiers (`Button`, `ButtonMenu`). Any status/counter text the
435
+ consumer renders inside `actions` should use the shared
436
+ `--ui-text-on-surface-primary`/`-secondary` semantic tokens to remain
437
+ compliant.
438
+
439
+ ---
440
+
441
+ ## Testing Checklist
442
+
443
+ - [ ] Root renders as a `<fieldset>` with no unexpected ARIA role
444
+ - [ ] Plain Button/ButtonMenu children composed directly on `Toolbar` are each
445
+ reachable via Tab
446
+ - [ ] `ToolbarActionList` renders `role="toolbar"` and is reachable as a
447
+ single Tab stop, with arrow keys moving roving focus between its
448
+ visible actions and the overflow trigger
449
+ - [ ] `disabled` removes every nested control from the Tab order
450
+ - [ ] A disabled action inside `ToolbarActionList` is unreachable via Tab or
451
+ arrow keys, not merely `aria-disabled`
452
+ - [ ] Action buttons have accessible names
453
+ - [ ] A rendered selection counter states the count as text
@@ -0,0 +1,164 @@
1
+ # Tooltip
2
+
3
+ > A contextual hint that appears on hover or focus of its trigger and disappears when the interaction ends. Used for supplementary information — not for critical content or actions.
4
+
5
+ **Status:** ready · **Category:** overlay · **Since:** v0.12.0
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from '@acronis-platform/ui-react'
11
+ ```
12
+
13
+ ## Quick example
14
+
15
+ ```tsx
16
+ <Tooltip>
17
+ <TooltipTrigger render={<Button>Save</Button>} />
18
+ <TooltipContent>Save your changes</TooltipContent>
19
+ </Tooltip>
20
+ ```
21
+
22
+ A contextual hint shown on hover or focus of its trigger.
23
+
24
+ ## When to use
25
+
26
+ - Supplementary information that clarifies an element or action (e.g. what an
27
+ icon button does) without cluttering the UI.
28
+
29
+ ## When not to use
30
+
31
+ - Critical information or actions — tooltips aren't available to touch users and
32
+ disappear on blur. Use inline text, a Popover, or a Dialog.
33
+ - Rich or interactive content — the popup is non-interactive. Use a Popover.
34
+
35
+ ## Anatomy
36
+
37
+ A composable set of parts:
38
+
39
+ | Part | Element | Role | Purpose |
40
+ | ----------------- | ---------- | --------- | ------------------------------ |
41
+ | `Tooltip` | — (no DOM) | — | Owns open state. |
42
+ | `TooltipTrigger` | `button` | — | The anchor (wrap any element). |
43
+ | `TooltipContent` | `div` | `tooltip` | The floating hint bubble. |
44
+ | `TooltipProvider` | — (no DOM) | — | Shares open/close delays. |
45
+
46
+ ## Examples
47
+
48
+ ```tsx
49
+ import {
50
+ Tooltip,
51
+ TooltipTrigger,
52
+ TooltipContent,
53
+ TooltipProvider,
54
+ } from '@acronis-platform/ui-react';
55
+ import { Button } from '@acronis-platform/ui-react';
56
+
57
+ // Wrap your app (or a region) once to share delays:
58
+ <TooltipProvider delay={300}>
59
+ <Tooltip>
60
+ <TooltipTrigger render={<Button>Save</Button>} />
61
+ <TooltipContent>Save your changes</TooltipContent>
62
+ </Tooltip>
63
+ </TooltipProvider>;
64
+ ```
65
+
66
+ `TooltipContent` accepts `side` / `align` / `sideOffset` to control placement. No
67
+ arrow is rendered, matching the design.
68
+
69
+ ## Props
70
+
71
+ | Prop | Type | Default | Required | Description |
72
+ |------|------|---------|----------|-------------|
73
+ | `open` | `boolean` | — | no | Controlled open state of the popup. Pair with the change event. |
74
+ | `default-open` | `boolean` | `false` | no | Whether the popup is initially open when uncontrolled. |
75
+ | `disabled` | `boolean` | `false` | no | Disables the tooltip — the popup never opens. |
76
+ | `side` | `'top' | 'right' | 'bottom' | 'left'` | `top` | no | Which side of the trigger the popup is placed on (on the content). |
77
+ | `delay` | `number` | — | no | Open delay in ms. Set on a `TooltipProvider` to share across tooltips. |
78
+
79
+ ## Events
80
+
81
+ | Event | Payload | Description |
82
+ |-------|---------|-------------|
83
+ | `open-change` | `boolean` | Fired when the popup opens or closes (React: `onOpenChange`). Payload is the new open state. |
84
+
85
+ ## Content slots
86
+
87
+ | Slot | Description |
88
+ |------|-------------|
89
+ | `default` | The composed tooltip: a trigger (wrap any element via the trigger's `render` prop) and a content popup holding the hint text. |
90
+
91
+ ## Behavior
92
+
93
+ ### Opening
94
+
95
+ - **Given** an enabled tooltip
96
+ **When** the user hovers the trigger or moves keyboard focus to it (after the
97
+ open delay)
98
+ **Then** the popup appears next to the trigger (`open-change(true)`).
99
+
100
+ - **Given** a `disabled` tooltip
101
+ **When** the user hovers or focuses the trigger
102
+ **Then** nothing happens — the popup never opens.
103
+
104
+ ### Closing
105
+
106
+ - **Given** an open tooltip
107
+ **When** the pointer leaves the trigger (and popup), focus moves away, or the
108
+ user presses Escape
109
+ **Then** the popup hides (`open-change(false)`).
110
+
111
+ ### Delay
112
+
113
+ - **Given** a `TooltipProvider` wrapping several tooltips
114
+ **When** one opens after its delay
115
+ **Then** sibling tooltips can open without re-waiting the full delay (shared
116
+ delay), per the provider configuration.
117
+
118
+ ### Controlled vs uncontrolled
119
+
120
+ - **Given** `open` is controlled
121
+ **When** the user hovers/focuses
122
+ **Then** internal state does not change on its own; the component emits
123
+ `open-change` and the consumer updates the `open` prop.
124
+ - **Given** only `default-open`
125
+ **Then** the tooltip manages its own open state.
126
+
127
+ ### Placement
128
+
129
+ - **Given** a `side` on the content
130
+ **When** the popup opens
131
+ **Then** it is placed on that side of the trigger, flipping to stay in view
132
+ when there isn't room.
133
+
134
+ ## Accessibility
135
+
136
+ Provided by the Base UI Tooltip primitive; verify these hold after styling.
137
+
138
+ ## Roles & ARIA
139
+
140
+ - The popup has `role="tooltip"`. The trigger references it via
141
+ `aria-describedby` while open, so screen readers announce the hint as a
142
+ description of the trigger.
143
+ - The trigger must be a real, focusable element (a button by default, or any
144
+ focusable element via the trigger's `render` prop) so the tooltip is reachable
145
+ by keyboard, not just pointer.
146
+
147
+ ## Keyboard & focus
148
+
149
+ - **Focus** the trigger opens the tooltip; **blur** closes it.
150
+ - **Escape** closes an open tooltip.
151
+ - The tooltip is supplementary — focus never moves into the popup, and the popup
152
+ contains no interactive content (use a Popover/Dialog for that).
153
+
154
+ ## Content guidance
155
+
156
+ - Keep tooltips to short, non-essential text. Don't put critical information or
157
+ actions in a tooltip — it isn't available to touch users and vanishes on blur.
158
+ - Don't rely on a tooltip as the only label for an icon-only control; give the
159
+ control its own accessible name (e.g. `aria-label`) as well.
160
+
161
+ ## Contrast
162
+
163
+ - `--ui-tooltip-label-color` on `--ui-tooltip-container-color` meets contrast; the bubble's
164
+ ~90% opacity keeps text legible over varied backgrounds.