@agregio-solutions/design-system 2.0.0 → 2.2.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 (228) hide show
  1. package/dist/design-system.cjs +378 -297
  2. package/dist/design-system.js +2602 -2462
  3. package/dist/packages/components/Button/components/HoldProgress/HoldProgress.d.ts +1 -1
  4. package/dist/packages/components/Button/components/IconLeftElement/IconLeftElement.d.ts +1 -1
  5. package/dist/packages/components/Button/components/IconRightElement/IconRightElement.d.ts +1 -1
  6. package/dist/packages/components/ChartLegend/ChartLegend.d.ts +1 -1
  7. package/dist/packages/components/Combobox/Combobox.d.ts +39 -82
  8. package/dist/packages/components/Combobox/doc.md +362 -7
  9. package/dist/packages/components/DataTable/doc.md +11 -11
  10. package/dist/packages/components/FileUpload/components/FileDetails/FileDetails.d.ts +1 -1
  11. package/dist/packages/components/FileUpload/components/FileDetails/FileDetails.styled.d.ts +1 -1
  12. package/dist/packages/components/Icon/components/access_time.d.ts +1 -1
  13. package/dist/packages/components/Icon/components/add.d.ts +1 -1
  14. package/dist/packages/components/Icon/components/add_box.d.ts +1 -1
  15. package/dist/packages/components/Icon/components/arrow_back.d.ts +1 -1
  16. package/dist/packages/components/Icon/components/arrow_downward.d.ts +1 -1
  17. package/dist/packages/components/Icon/components/arrow_enter.d.ts +1 -1
  18. package/dist/packages/components/Icon/components/arrow_forward.d.ts +1 -1
  19. package/dist/packages/components/Icon/components/arrow_upward.d.ts +1 -1
  20. package/dist/packages/components/Icon/components/back_time.d.ts +1 -1
  21. package/dist/packages/components/Icon/components/bar_chart.d.ts +1 -1
  22. package/dist/packages/components/Icon/components/bar_chart_2.d.ts +1 -1
  23. package/dist/packages/components/Icon/components/battery.d.ts +1 -1
  24. package/dist/packages/components/Icon/components/battery_alert.d.ts +1 -1
  25. package/dist/packages/components/Icon/components/battery_empty.d.ts +1 -1
  26. package/dist/packages/components/Icon/components/battery_full.d.ts +1 -1
  27. package/dist/packages/components/Icon/components/battery_half.d.ts +1 -1
  28. package/dist/packages/components/Icon/components/bolt.d.ts +1 -1
  29. package/dist/packages/components/Icon/components/book.d.ts +1 -1
  30. package/dist/packages/components/Icon/components/business.d.ts +1 -1
  31. package/dist/packages/components/Icon/components/calculator.d.ts +1 -1
  32. package/dist/packages/components/Icon/components/calendar.d.ts +1 -1
  33. package/dist/packages/components/Icon/components/calendar_today.d.ts +1 -1
  34. package/dist/packages/components/Icon/components/calibration.d.ts +1 -1
  35. package/dist/packages/components/Icon/components/cancel.d.ts +1 -1
  36. package/dist/packages/components/Icon/components/caret.d.ts +1 -1
  37. package/dist/packages/components/Icon/components/change_circle.d.ts +1 -1
  38. package/dist/packages/components/Icon/components/change_ok.d.ts +1 -1
  39. package/dist/packages/components/Icon/components/chart_curves.d.ts +1 -1
  40. package/dist/packages/components/Icon/components/chart_curves_rounded.d.ts +1 -1
  41. package/dist/packages/components/Icon/components/chart_plus.d.ts +1 -1
  42. package/dist/packages/components/Icon/components/chart_simple.d.ts +1 -1
  43. package/dist/packages/components/Icon/components/chart_up.d.ts +1 -1
  44. package/dist/packages/components/Icon/components/check.d.ts +1 -1
  45. package/dist/packages/components/Icon/components/check_circle_outline.d.ts +1 -1
  46. package/dist/packages/components/Icon/components/chevron_left.d.ts +1 -1
  47. package/dist/packages/components/Icon/components/chevron_right.d.ts +1 -1
  48. package/dist/packages/components/Icon/components/clear.d.ts +1 -1
  49. package/dist/packages/components/Icon/components/close.d.ts +1 -1
  50. package/dist/packages/components/Icon/components/cloud.d.ts +1 -1
  51. package/dist/packages/components/Icon/components/cloud_full.d.ts +1 -1
  52. package/dist/packages/components/Icon/components/collapse_menu.d.ts +1 -1
  53. package/dist/packages/components/Icon/components/content_copy.d.ts +1 -1
  54. package/dist/packages/components/Icon/components/cycle.d.ts +1 -1
  55. package/dist/packages/components/Icon/components/delete_outline.d.ts +1 -1
  56. package/dist/packages/components/Icon/components/dice.d.ts +1 -1
  57. package/dist/packages/components/Icon/components/disconnect.d.ts +1 -1
  58. package/dist/packages/components/Icon/components/download.d.ts +1 -1
  59. package/dist/packages/components/Icon/components/drag_indicator.d.ts +1 -1
  60. package/dist/packages/components/Icon/components/driver.d.ts +1 -1
  61. package/dist/packages/components/Icon/components/edit.d.ts +1 -1
  62. package/dist/packages/components/Icon/components/error_outline.d.ts +1 -1
  63. package/dist/packages/components/Icon/components/euro.d.ts +1 -1
  64. package/dist/packages/components/Icon/components/exit.d.ts +1 -1
  65. package/dist/packages/components/Icon/components/exit_to_app.d.ts +1 -1
  66. package/dist/packages/components/Icon/components/expand_less.d.ts +1 -1
  67. package/dist/packages/components/Icon/components/expand_more.d.ts +1 -1
  68. package/dist/packages/components/Icon/components/eye.d.ts +1 -1
  69. package/dist/packages/components/Icon/components/eye_off.d.ts +1 -1
  70. package/dist/packages/components/Icon/components/fiber_new.d.ts +1 -1
  71. package/dist/packages/components/Icon/components/file_download.d.ts +1 -1
  72. package/dist/packages/components/Icon/components/file_export.d.ts +1 -1
  73. package/dist/packages/components/Icon/components/file_plus.d.ts +1 -1
  74. package/dist/packages/components/Icon/components/filter_alt.d.ts +1 -1
  75. package/dist/packages/components/Icon/components/filter_list.d.ts +1 -1
  76. package/dist/packages/components/Icon/components/first_page.d.ts +1 -1
  77. package/dist/packages/components/Icon/components/flame.d.ts +1 -1
  78. package/dist/packages/components/Icon/components/flex.d.ts +1 -1
  79. package/dist/packages/components/Icon/components/folder_open.d.ts +1 -1
  80. package/dist/packages/components/Icon/components/gaz.d.ts +1 -1
  81. package/dist/packages/components/Icon/components/grid_view.d.ts +1 -1
  82. package/dist/packages/components/Icon/components/hand.d.ts +1 -1
  83. package/dist/packages/components/Icon/components/help_outline.d.ts +1 -1
  84. package/dist/packages/components/Icon/components/home.d.ts +1 -1
  85. package/dist/packages/components/Icon/components/hydraulic.d.ts +1 -1
  86. package/dist/packages/components/Icon/components/id.d.ts +1 -1
  87. package/dist/packages/components/Icon/components/industry.d.ts +1 -1
  88. package/dist/packages/components/Icon/components/insert_emoticon.d.ts +1 -1
  89. package/dist/packages/components/Icon/components/invoice.d.ts +1 -1
  90. package/dist/packages/components/Icon/components/invoice_full.d.ts +1 -1
  91. package/dist/packages/components/Icon/components/joystick.d.ts +1 -1
  92. package/dist/packages/components/Icon/components/language.d.ts +1 -1
  93. package/dist/packages/components/Icon/components/laptop.d.ts +1 -1
  94. package/dist/packages/components/Icon/components/last_page.d.ts +1 -1
  95. package/dist/packages/components/Icon/components/leaf.d.ts +1 -1
  96. package/dist/packages/components/Icon/components/lines_ok.d.ts +1 -1
  97. package/dist/packages/components/Icon/components/lines_plus.d.ts +1 -1
  98. package/dist/packages/components/Icon/components/link.d.ts +1 -1
  99. package/dist/packages/components/Icon/components/list.d.ts +1 -1
  100. package/dist/packages/components/Icon/components/location.d.ts +1 -1
  101. package/dist/packages/components/Icon/components/location_full.d.ts +1 -1
  102. package/dist/packages/components/Icon/components/location_searching.d.ts +1 -1
  103. package/dist/packages/components/Icon/components/logout.d.ts +1 -1
  104. package/dist/packages/components/Icon/components/logs.d.ts +1 -1
  105. package/dist/packages/components/Icon/components/magic_wand.d.ts +1 -1
  106. package/dist/packages/components/Icon/components/mail_empty.d.ts +1 -1
  107. package/dist/packages/components/Icon/components/mail_full.d.ts +1 -1
  108. package/dist/packages/components/Icon/components/mail_off.d.ts +1 -1
  109. package/dist/packages/components/Icon/components/mail_ok.d.ts +1 -1
  110. package/dist/packages/components/Icon/components/mail_open.d.ts +1 -1
  111. package/dist/packages/components/Icon/components/mail_open_full.d.ts +1 -1
  112. package/dist/packages/components/Icon/components/menu.d.ts +1 -1
  113. package/dist/packages/components/Icon/components/minimize.d.ts +1 -1
  114. package/dist/packages/components/Icon/components/modbus.d.ts +1 -1
  115. package/dist/packages/components/Icon/components/money_pig.d.ts +1 -1
  116. package/dist/packages/components/Icon/components/money_pig_full.d.ts +1 -1
  117. package/dist/packages/components/Icon/components/monitor_heart.d.ts +1 -1
  118. package/dist/packages/components/Icon/components/monitoring.d.ts +1 -1
  119. package/dist/packages/components/Icon/components/moon.d.ts +1 -1
  120. package/dist/packages/components/Icon/components/more_horiz.d.ts +1 -1
  121. package/dist/packages/components/Icon/components/more_vert.d.ts +1 -1
  122. package/dist/packages/components/Icon/components/moving.d.ts +1 -1
  123. package/dist/packages/components/Icon/components/notifications_active.d.ts +1 -1
  124. package/dist/packages/components/Icon/components/notifications_none.d.ts +1 -1
  125. package/dist/packages/components/Icon/components/notifications_off.d.ts +1 -1
  126. package/dist/packages/components/Icon/components/one_single.d.ts +1 -1
  127. package/dist/packages/components/Icon/components/pause.d.ts +1 -1
  128. package/dist/packages/components/Icon/components/pause_empty.d.ts +1 -1
  129. package/dist/packages/components/Icon/components/payments.d.ts +1 -1
  130. package/dist/packages/components/Icon/components/pdf.d.ts +1 -1
  131. package/dist/packages/components/Icon/components/phone_1_empty.d.ts +1 -1
  132. package/dist/packages/components/Icon/components/phone_1_full.d.ts +1 -1
  133. package/dist/packages/components/Icon/components/phone_2_empty.d.ts +1 -1
  134. package/dist/packages/components/Icon/components/phone_2_full.d.ts +1 -1
  135. package/dist/packages/components/Icon/components/play.d.ts +1 -1
  136. package/dist/packages/components/Icon/components/play_empty.d.ts +1 -1
  137. package/dist/packages/components/Icon/components/play_full.d.ts +1 -1
  138. package/dist/packages/components/Icon/components/power_off.d.ts +1 -1
  139. package/dist/packages/components/Icon/components/profile.d.ts +1 -1
  140. package/dist/packages/components/Icon/components/profile_full.d.ts +1 -1
  141. package/dist/packages/components/Icon/components/progress.d.ts +1 -1
  142. package/dist/packages/components/Icon/components/question.d.ts +1 -1
  143. package/dist/packages/components/Icon/components/rain.d.ts +1 -1
  144. package/dist/packages/components/Icon/components/receipt_long.d.ts +1 -1
  145. package/dist/packages/components/Icon/components/record.d.ts +1 -1
  146. package/dist/packages/components/Icon/components/record_full.d.ts +1 -1
  147. package/dist/packages/components/Icon/components/refresh.d.ts +1 -1
  148. package/dist/packages/components/Icon/components/remove.d.ts +1 -1
  149. package/dist/packages/components/Icon/components/remove_red_eye.d.ts +1 -1
  150. package/dist/packages/components/Icon/components/rename.d.ts +1 -1
  151. package/dist/packages/components/Icon/components/return.d.ts +1 -1
  152. package/dist/packages/components/Icon/components/save.d.ts +1 -1
  153. package/dist/packages/components/Icon/components/scan.d.ts +1 -1
  154. package/dist/packages/components/Icon/components/science.d.ts +1 -1
  155. package/dist/packages/components/Icon/components/science_2.d.ts +1 -1
  156. package/dist/packages/components/Icon/components/search.d.ts +1 -1
  157. package/dist/packages/components/Icon/components/sell.d.ts +1 -1
  158. package/dist/packages/components/Icon/components/sell_full.d.ts +1 -1
  159. package/dist/packages/components/Icon/components/send.d.ts +1 -1
  160. package/dist/packages/components/Icon/components/settings.d.ts +1 -1
  161. package/dist/packages/components/Icon/components/sms_empty.d.ts +1 -1
  162. package/dist/packages/components/Icon/components/sms_full.d.ts +1 -1
  163. package/dist/packages/components/Icon/components/square_plus.d.ts +1 -1
  164. package/dist/packages/components/Icon/components/ssid_chart.d.ts +1 -1
  165. package/dist/packages/components/Icon/components/stack_batch.d.ts +1 -1
  166. package/dist/packages/components/Icon/components/stacked_line_chart.d.ts +1 -1
  167. package/dist/packages/components/Icon/components/star.d.ts +1 -1
  168. package/dist/packages/components/Icon/components/star_outline.d.ts +1 -1
  169. package/dist/packages/components/Icon/components/storm.d.ts +1 -1
  170. package/dist/packages/components/Icon/components/sun.d.ts +1 -1
  171. package/dist/packages/components/Icon/components/sun_2.d.ts +1 -1
  172. package/dist/packages/components/Icon/components/sun_full.d.ts +1 -1
  173. package/dist/packages/components/Icon/components/swap_horiz.d.ts +1 -1
  174. package/dist/packages/components/Icon/components/tag.d.ts +1 -1
  175. package/dist/packages/components/Icon/components/tag_add.d.ts +1 -1
  176. package/dist/packages/components/Icon/components/tag_ok.d.ts +1 -1
  177. package/dist/packages/components/Icon/components/tag_remove.d.ts +1 -1
  178. package/dist/packages/components/Icon/components/team.d.ts +1 -1
  179. package/dist/packages/components/Icon/components/text_snippet.d.ts +1 -1
  180. package/dist/packages/components/Icon/components/ticket.d.ts +1 -1
  181. package/dist/packages/components/Icon/components/ticket_full.d.ts +1 -1
  182. package/dist/packages/components/Icon/components/tools.d.ts +1 -1
  183. package/dist/packages/components/Icon/components/tree_item.d.ts +1 -1
  184. package/dist/packages/components/Icon/components/undo.d.ts +1 -1
  185. package/dist/packages/components/Icon/components/update.d.ts +1 -1
  186. package/dist/packages/components/Icon/components/update_circle.d.ts +1 -1
  187. package/dist/packages/components/Icon/components/upload.d.ts +1 -1
  188. package/dist/packages/components/Icon/components/wallet.d.ts +1 -1
  189. package/dist/packages/components/Icon/components/warehouse.d.ts +1 -1
  190. package/dist/packages/components/Icon/components/warning_amber.d.ts +1 -1
  191. package/dist/packages/components/Icon/components/warning_badge.d.ts +1 -1
  192. package/dist/packages/components/Icon/components/warning_octogone.d.ts +1 -1
  193. package/dist/packages/components/Icon/components/warning_shield.d.ts +1 -1
  194. package/dist/packages/components/Icon/components/wifi.d.ts +1 -1
  195. package/dist/packages/components/Icon/components/wifi_level.d.ts +1 -1
  196. package/dist/packages/components/Icon/components/wifi_rounded.d.ts +1 -1
  197. package/dist/packages/components/Icon/components/wifi_rounded_alert.d.ts +1 -1
  198. package/dist/packages/components/Icon/components/wifi_settings.d.ts +1 -1
  199. package/dist/packages/components/Icon/components/wind_turbine.d.ts +1 -1
  200. package/dist/packages/components/LinearProgressBar/LinearProgressBar.d.ts +1 -1
  201. package/dist/packages/components/List/components/ListItem/ListItem.d.ts +1 -1
  202. package/dist/packages/components/Loader/Loader.d.ts +1 -1
  203. package/dist/packages/components/MenuItem/MenuItem.d.ts +1 -1
  204. package/dist/packages/components/Navigation/components/AgregioSolutionsLogo.d.ts +1 -1
  205. package/dist/packages/components/Navigation/components/ConnectionManagementLogo.d.ts +1 -1
  206. package/dist/packages/components/Navigation/components/IrisLogo.d.ts +1 -1
  207. package/dist/packages/components/Navigation/components/OBILogo.d.ts +1 -1
  208. package/dist/packages/components/Navigation/components/VPPLogo.d.ts +1 -1
  209. package/dist/packages/components/Notifications/components/EmptyNotifications/EmptyNotifications.d.ts +1 -1
  210. package/dist/packages/components/PageLayout/PageLayout.d.ts +1 -1
  211. package/dist/packages/components/PageLayout/doc.md +11 -11
  212. package/dist/packages/components/Radio/Radio.d.ts +7 -0
  213. package/dist/packages/components/Radio/doc.md +4 -0
  214. package/dist/packages/components/RadioGroup/RadioGroup.d.ts +92 -0
  215. package/dist/packages/components/RadioGroup/doc.md +569 -0
  216. package/dist/packages/components/RadioGroupItem/RadioGroupItem.d.ts +27 -0
  217. package/dist/packages/components/RouterProvider/RouterProvider.d.ts +1 -1
  218. package/dist/packages/components/SelectItem/SelectItem.d.ts +2 -1
  219. package/dist/packages/components/Timeline/Timeline.d.ts +1 -1
  220. package/dist/packages/components/Timeline/components/BlockLineContainer/BlockLineContainer.d.ts +1 -1
  221. package/dist/packages/components/Timeline/components/BlockLineContainer/components/ExpandButton/ExpandButton.d.ts +1 -1
  222. package/dist/packages/components/Timeline/components/BlockLineContainer/components/NameBlock/NameBlock.d.ts +1 -1
  223. package/dist/packages/components/Timeline/components/GroupLineContainer/GroupLineContainer.d.ts +1 -1
  224. package/dist/packages/components/Timeline/components/TimelineRange/TimelineRange.d.ts +1 -1
  225. package/dist/packages/components/Toaster/Toaster.d.ts +1 -1
  226. package/dist/packages/index.d.ts +5 -3
  227. package/dist/packages/internal-components/Logo/Logo.d.ts +1 -1
  228. package/package.json +11 -11
@@ -350,6 +350,10 @@ import * as RadioTests from "./tests/Radio.stories";
350
350
 
351
351
  # Radio
352
352
 
353
+ > **Deprecated** — use `RadioGroup` with `RadioGroupItem` instead. It names the group for
354
+ > assistive technologies, handles keyboard navigation (one tab stop, arrow keys) and displays
355
+ > helper and error texts. See the "Migrating from `Radio`" section of the `RadioGroup` docs.
356
+
353
357
  Use this component exactly like an `<input type="radio">` but with an added `label` prop.
354
358
 
355
359
  <Canvas of={Radio.WithLabel} />
@@ -0,0 +1,92 @@
1
+ import { default as React } from 'react';
2
+ import { Props as LabelProps } from '../Label/Label';
3
+ import { Props as FormGroupWrapperProps } from '../../internal-components/FormGroupWrapper/FormGroupWrapper';
4
+ export type Props = {
5
+ /**
6
+ * The `RadioGroupItem`s to display in the group.
7
+ */
8
+ children: React.ReactNode;
9
+ /**
10
+ * The value of the selected radio (controlled). `null` means no radio is selected.
11
+ */
12
+ value?: string | null;
13
+ /**
14
+ * The value of the radio selected on first render (uncontrolled).
15
+ */
16
+ defaultValue?: string;
17
+ /**
18
+ * Handler that is called with the value of the newly selected radio.
19
+ */
20
+ onChange?: (value: string) => void;
21
+ /**
22
+ * The name of the radios, used when submitting an HTML form.
23
+ */
24
+ name?: string;
25
+ /**
26
+ * Whether all the radios of the group are disabled.
27
+ */
28
+ isDisabled?: boolean;
29
+ /**
30
+ * Whether the radios can be focused but not changed by the user.
31
+ */
32
+ isReadOnly?: boolean;
33
+ /**
34
+ * Layout of the radios inside the group.
35
+ * @default "vertical"
36
+ */
37
+ direction?: "vertical" | "horizontal";
38
+ /**
39
+ * Accessible name of the group, required when `label` is not a string.
40
+ */
41
+ "aria-label"?: string;
42
+ /**
43
+ * Props to pass to the wrapper div (for example, `style` or `className`).
44
+ */
45
+ wrapperProps?: React.HTMLProps<HTMLDivElement>;
46
+ } & Pick<LabelProps, "label" | "labelIconRight" | "labelIconRightTooltip" | "required"> & Pick<FormGroupWrapperProps, "helperText" | "helperTextIcon" | "errorHelperText" | "errorHelperTextIcon" | "successHelperText" | "successHelperTextIcon" | "warningHelperText" | "warningHelperTextIcon" | "orientation" | "className" | "style">;
47
+ declare const RadioGroup: React.ForwardRefExoticComponent<{
48
+ /**
49
+ * The `RadioGroupItem`s to display in the group.
50
+ */
51
+ children: React.ReactNode;
52
+ /**
53
+ * The value of the selected radio (controlled). `null` means no radio is selected.
54
+ */
55
+ value?: string | null;
56
+ /**
57
+ * The value of the radio selected on first render (uncontrolled).
58
+ */
59
+ defaultValue?: string;
60
+ /**
61
+ * Handler that is called with the value of the newly selected radio.
62
+ */
63
+ onChange?: (value: string) => void;
64
+ /**
65
+ * The name of the radios, used when submitting an HTML form.
66
+ */
67
+ name?: string;
68
+ /**
69
+ * Whether all the radios of the group are disabled.
70
+ */
71
+ isDisabled?: boolean;
72
+ /**
73
+ * Whether the radios can be focused but not changed by the user.
74
+ */
75
+ isReadOnly?: boolean;
76
+ /**
77
+ * Layout of the radios inside the group.
78
+ * @default "vertical"
79
+ */
80
+ direction?: "vertical" | "horizontal";
81
+ /**
82
+ * Accessible name of the group, required when `label` is not a string.
83
+ */
84
+ "aria-label"?: string;
85
+ /**
86
+ * Props to pass to the wrapper div (for example, `style` or `className`).
87
+ */
88
+ wrapperProps?: React.HTMLProps<HTMLDivElement>;
89
+ } & Pick<LabelProps, "label" | "required" | "labelIconRight" | "labelIconRightTooltip"> & Pick<FormGroupWrapperProps, "className" | "style" | "orientation" | "helperText" | "helperTextIcon" | "errorHelperText" | "errorHelperTextIcon" | "successHelperText" | "successHelperTextIcon" | "warningHelperText" | "warningHelperTextIcon"> & React.RefAttributes<{
90
+ focus: (options?: FocusOptions) => void;
91
+ }>>;
92
+ export default RadioGroup;
@@ -0,0 +1,569 @@
1
+ # RadioGroup
2
+
3
+ ## Props
4
+
5
+ The complete Props documentation with JS doc for this component is available at this path:
6
+
7
+ node_modules/@agregio-solutions/design-system/dist/packages/components/RadioGroup/RadioGroup.d.ts
8
+
9
+ ## Example usage
10
+
11
+ Here are the Storybook Stories.
12
+
13
+ Base stories:
14
+
15
+ ```tsx
16
+ import { Meta, StoryObj } from "@storybook/react-vite";
17
+ import { expect, fn, within } from "storybook/test";
18
+ import RadioGroup from "./RadioGroup";
19
+ import RadioGroupItem from "../RadioGroupItem/RadioGroupItem";
20
+ import { ICON_NAMES_ARRAY } from "../Icon/Icon";
21
+
22
+ const meta: Meta<typeof RadioGroup> = {
23
+ component: RadioGroup,
24
+ argTypes: {
25
+ direction: {
26
+ control: "select",
27
+ options: ["vertical", "horizontal"],
28
+ },
29
+ orientation: {
30
+ control: "select",
31
+ options: ["vertical", "horizontal"],
32
+ },
33
+ labelIconRight: {
34
+ control: "select",
35
+ options: ["", ...ICON_NAMES_ARRAY],
36
+ },
37
+ helperTextIcon: {
38
+ control: "select",
39
+ options: ["", ...ICON_NAMES_ARRAY],
40
+ },
41
+ errorHelperTextIcon: {
42
+ control: "select",
43
+ options: ["", ...ICON_NAMES_ARRAY],
44
+ },
45
+ children: { control: false },
46
+ value: { control: false },
47
+ },
48
+ parameters: {
49
+ layout: "centered",
50
+ },
51
+ render: (args) => (
52
+ <RadioGroup {...args}>
53
+ <RadioGroupItem value="solar" label="Solar" />
54
+ <RadioGroupItem value="wind" label="Wind" />
55
+ <RadioGroupItem value="hydro" label="Hydro" />
56
+ </RadioGroup>
57
+ ),
58
+ };
59
+ export default meta;
60
+
61
+ type Story = StoryObj<typeof RadioGroup>;
62
+
63
+ export const Playground: Story = {
64
+ args: {
65
+ label: "Energy source",
66
+ onChange: fn(),
67
+ },
68
+ play: async ({ canvasElement }) => {
69
+ const canvas = within(canvasElement);
70
+ const group = canvas.getByRole("radiogroup", { name: "Energy source" });
71
+ await expect(within(group).getAllByRole("radio")).toHaveLength(3);
72
+ await expect(
73
+ canvas.getByRole("radio", { name: "Solar" }),
74
+ ).not.toBeChecked();
75
+ },
76
+ };
77
+
78
+ export const ShouldPreselectDefaultValue: Story = {
79
+ args: {
80
+ ...Playground.args,
81
+ defaultValue: "wind",
82
+ },
83
+ play: async ({ canvasElement }) => {
84
+ const canvas = within(canvasElement);
85
+ await expect(canvas.getByRole("radio", { name: "Wind" })).toBeChecked();
86
+ await expect(
87
+ canvas.getByRole("radio", { name: "Solar" }),
88
+ ).not.toBeChecked();
89
+ },
90
+ };
91
+
92
+ export const ShouldDisableAllRadios: Story = {
93
+ args: {
94
+ ...Playground.args,
95
+ defaultValue: "wind",
96
+ isDisabled: true,
97
+ },
98
+ play: async ({ canvasElement }) => {
99
+ const canvas = within(canvasElement);
100
+ for (const radio of canvas.getAllByRole("radio")) {
101
+ await expect(radio).toBeDisabled();
102
+ }
103
+ },
104
+ };
105
+
106
+ export const ShouldDisableOneRadio: Story = {
107
+ args: Playground.args,
108
+ render: (args) => (
109
+ <RadioGroup {...args}>
110
+ <RadioGroupItem value="solar" label="Solar" />
111
+ <RadioGroupItem value="wind" label="Wind" isDisabled />
112
+ <RadioGroupItem value="hydro" label="Hydro" />
113
+ </RadioGroup>
114
+ ),
115
+ play: async ({ canvasElement }) => {
116
+ const canvas = within(canvasElement);
117
+ await expect(canvas.getByRole("radio", { name: "Wind" })).toBeDisabled();
118
+ await expect(canvas.getByRole("radio", { name: "Solar" })).toBeEnabled();
119
+ },
120
+ };
121
+
122
+ export const ShouldDisplayReadOnly: Story = {
123
+ args: {
124
+ ...Playground.args,
125
+ defaultValue: "wind",
126
+ isReadOnly: true,
127
+ },
128
+ play: async ({ canvasElement }) => {
129
+ const canvas = within(canvasElement);
130
+ await expect(canvas.getByRole("radio", { name: "Wind" })).toBeChecked();
131
+ await expect(canvas.getByText("Wind").closest("label")).toHaveAttribute(
132
+ "data-readonly",
133
+ "true",
134
+ );
135
+ },
136
+ };
137
+
138
+ export const ShouldDisplayHorizontally: Story = {
139
+ args: {
140
+ ...Playground.args,
141
+ direction: "horizontal",
142
+ },
143
+ play: async ({ canvasElement }) => {
144
+ const canvas = within(canvasElement);
145
+ await expect(canvas.getByRole("radiogroup")).toHaveAttribute(
146
+ "data-orientation",
147
+ "horizontal",
148
+ );
149
+ },
150
+ };
151
+
152
+ export const ShouldDisplayLabelDecorations: Story = {
153
+ args: {
154
+ ...Playground.args,
155
+ required: true,
156
+ labelIconRight: "help_outline",
157
+ labelIconRightTooltip: "Additional information",
158
+ helperText: "Main source of the site",
159
+ helperTextIcon: "help_outline",
160
+ },
161
+ play: async ({ canvasElement }) => {
162
+ const canvas = within(canvasElement);
163
+ await canvas.findByText("Main source of the site");
164
+ await canvas.findByTitle("Required");
165
+ for (const radio of canvas.getAllByRole("radio")) {
166
+ await expect(radio).toBeRequired();
167
+ }
168
+ },
169
+ };
170
+
171
+ export const ShouldDisplayError: Story = {
172
+ args: {
173
+ ...Playground.args,
174
+ errorHelperText: "Select an energy source",
175
+ errorHelperTextIcon: "error_outline",
176
+ },
177
+ play: async ({ canvasElement }) => {
178
+ const canvas = within(canvasElement);
179
+ await expect(canvas.getByRole("alert")).toHaveTextContent(
180
+ "Select an energy source",
181
+ );
182
+ await expect(canvas.getByRole("radiogroup")).toHaveAttribute(
183
+ "data-invalid",
184
+ "true",
185
+ );
186
+ },
187
+ };
188
+
189
+ export const ShouldDescribeARadio: Story = {
190
+ args: Playground.args,
191
+ render: (args) => (
192
+ <RadioGroup {...args}>
193
+ <RadioGroupItem
194
+ value="solar"
195
+ label="Solar"
196
+ description="Production during daytime only"
197
+ />
198
+ <RadioGroupItem value="wind" label="Wind" />
199
+ </RadioGroup>
200
+ ),
201
+ play: async ({ canvasElement }) => {
202
+ const canvas = within(canvasElement);
203
+ await expect(
204
+ canvas.getByRole("radio", { name: "Solar" }),
205
+ ).toHaveAccessibleDescription("Production during daytime only");
206
+ },
207
+ };
208
+
209
+ export const ShouldWrapLongText: Story = {
210
+ args: Playground.args,
211
+ render: (args) => (
212
+ <div style={{ width: 200 }}>
213
+ <RadioGroup {...args}>
214
+ <RadioGroupItem
215
+ value="long"
216
+ label="This is a very long text that should wrap on several lines"
217
+ />
218
+ <RadioGroupItem value="short" label="Short" />
219
+ </RadioGroup>
220
+ </div>
221
+ ),
222
+ play: async ({ canvasElement }) => {
223
+ const canvas = within(canvasElement);
224
+ await canvas.findByText(
225
+ "This is a very long text that should wrap on several lines",
226
+ );
227
+ },
228
+ };
229
+ ```
230
+
231
+ ## How to test this component
232
+
233
+ Here are some more advanced stories with more testing coverage and examples that you can read to understand how to test this component.
234
+
235
+ ```tsx
236
+ import { Meta, StoryObj } from "@storybook/react-vite";
237
+ import { expect, fn, userEvent, within } from "storybook/test";
238
+ import { useState } from "react";
239
+ import { Controller, useForm, useWatch } from "react-hook-form";
240
+ import RadioGroup from "../RadioGroup";
241
+ import RadioGroupItem from "../../RadioGroupItem/RadioGroupItem";
242
+ import * as RadioGroupStories from "../RadioGroup.stories";
243
+
244
+ const meta: Meta<typeof RadioGroup> = {
245
+ ...RadioGroupStories.default,
246
+ component: RadioGroup,
247
+ parameters: {
248
+ ...RadioGroupStories.default.parameters,
249
+ chromatic: { disableSnapshot: true },
250
+ },
251
+ };
252
+ export default meta;
253
+
254
+ type Story = StoryObj<typeof RadioGroup>;
255
+
256
+ const ENERGY_SOURCES = [
257
+ { value: "solar", label: "Solar" },
258
+ { value: "wind", label: "Wind" },
259
+ { value: "hydro", label: "Hydro" },
260
+ ];
261
+
262
+ const EnergyItems = () =>
263
+ ENERGY_SOURCES.map((source) => (
264
+ <RadioGroupItem key={source.value} {...source} />
265
+ ));
266
+
267
+ const ControlledExample = ({
268
+ onChange,
269
+ }: {
270
+ onChange?: (value: string) => void;
271
+ }) => {
272
+ const [selected, setSelected] = useState<string | null>(null);
273
+ return (
274
+ <div>
275
+ <div>Debug selected: {selected}</div>
276
+ <RadioGroup
277
+ label="Energy source"
278
+ value={selected}
279
+ onChange={(value) => {
280
+ setSelected(value);
281
+ onChange?.(value);
282
+ }}
283
+ >
284
+ <EnergyItems />
285
+ </RadioGroup>
286
+ </div>
287
+ );
288
+ };
289
+
290
+ export const ExampleControlled: Story = {
291
+ args: { onChange: fn() },
292
+ render: (args) => <ControlledExample onChange={args.onChange} />,
293
+ };
294
+
295
+ export const ShouldUpdateControlledValue: Story = {
296
+ ...ExampleControlled,
297
+ play: async ({ canvasElement, args }) => {
298
+ const canvas = within(canvasElement);
299
+ const user = userEvent.setup();
300
+
301
+ await user.click(canvas.getByText("Wind"));
302
+ await expect(canvas.getByRole("radio", { name: "Wind" })).toBeChecked();
303
+ await canvas.findByText("Debug selected: wind");
304
+ await expect(args.onChange).toHaveBeenCalledWith("wind");
305
+
306
+ await user.click(canvas.getByText("Hydro"));
307
+ await expect(canvas.getByRole("radio", { name: "Wind" })).not.toBeChecked();
308
+ await canvas.findByText("Debug selected: hydro");
309
+ },
310
+ };
311
+
312
+ export const ShouldSelectWhenUncontrolled: Story = {
313
+ args: { label: "Energy source", defaultValue: "solar", onChange: fn() },
314
+ play: async ({ canvasElement, args }) => {
315
+ const canvas = within(canvasElement);
316
+ const user = userEvent.setup();
317
+
318
+ await expect(canvas.getByRole("radio", { name: "Solar" })).toBeChecked();
319
+ await user.click(canvas.getByText("Hydro"));
320
+ await expect(canvas.getByRole("radio", { name: "Hydro" })).toBeChecked();
321
+ await expect(
322
+ canvas.getByRole("radio", { name: "Solar" }),
323
+ ).not.toBeChecked();
324
+ await expect(args.onChange).toHaveBeenCalledWith("hydro");
325
+ },
326
+ };
327
+
328
+ export const ShouldNavigateWithKeyboard: Story = {
329
+ args: { label: "Energy source", defaultValue: "solar" },
330
+ render: (args) => (
331
+ <div>
332
+ <RadioGroup {...args}>
333
+ <RadioGroupItem value="solar" label="Solar" />
334
+ <RadioGroupItem value="wind" label="Wind" isDisabled />
335
+ <RadioGroupItem value="hydro" label="Hydro" />
336
+ </RadioGroup>
337
+ <button type="button">After</button>
338
+ </div>
339
+ ),
340
+ play: async ({ canvasElement }) => {
341
+ const canvas = within(canvasElement);
342
+ const user = userEvent.setup();
343
+ const solar = canvas.getByRole("radio", { name: "Solar" });
344
+ const hydro = canvas.getByRole("radio", { name: "Hydro" });
345
+
346
+ await user.tab();
347
+ await expect(solar).toHaveFocus();
348
+ await expect(canvas.getByText("Solar").closest("label")).toHaveAttribute(
349
+ "data-focus-visible",
350
+ "true",
351
+ );
352
+
353
+ await user.keyboard("{ArrowDown}");
354
+ await expect(hydro).toHaveFocus();
355
+ await expect(hydro).toBeChecked();
356
+
357
+ await user.tab();
358
+ await expect(canvas.getByRole("button", { name: "After" })).toHaveFocus();
359
+ },
360
+ };
361
+
362
+ export const ShouldNameARadioWithoutVisibleLabel: Story = {
363
+ args: RadioGroupStories.Playground.args,
364
+ render: (args) => (
365
+ <RadioGroup {...args}>
366
+ <RadioGroupItem value="solar" aria-label="Solar" />
367
+ <RadioGroupItem value="wind" aria-label="Wind" />
368
+ </RadioGroup>
369
+ ),
370
+ play: async ({ canvasElement }) => {
371
+ const canvas = within(canvasElement);
372
+ await expect(canvas.getByRole("radio", { name: "Solar" })).toBeVisible();
373
+ await expect(canvas.queryByText("Solar")).not.toBeInTheDocument();
374
+ },
375
+ };
376
+
377
+ export const ShouldNotChangeWhenReadOnly: Story = {
378
+ args: {
379
+ label: "Energy source",
380
+ defaultValue: "solar",
381
+ isReadOnly: true,
382
+ onChange: fn(),
383
+ },
384
+ play: async ({ canvasElement, args }) => {
385
+ const canvas = within(canvasElement);
386
+ const user = userEvent.setup();
387
+
388
+ await user.click(canvas.getByText("Wind"));
389
+ await expect(canvas.getByRole("radio", { name: "Solar" })).toBeChecked();
390
+ await expect(canvas.getByRole("radio", { name: "Wind" })).not.toBeChecked();
391
+ await expect(args.onChange).not.toHaveBeenCalled();
392
+ },
393
+ };
394
+
395
+ const ReactHookFormExample = () => {
396
+ const { control } = useForm({ defaultValues: { energy: "wind" } });
397
+ const energy = useWatch({ control, name: "energy" });
398
+
399
+ return (
400
+ <form>
401
+ <div>Debug selected: {energy}</div>
402
+ <Controller
403
+ control={control}
404
+ name="energy"
405
+ render={({ field }) => (
406
+ <RadioGroup
407
+ ref={field.ref}
408
+ label="Energy source"
409
+ name={field.name}
410
+ value={field.value}
411
+ onChange={field.onChange}
412
+ >
413
+ <EnergyItems />
414
+ </RadioGroup>
415
+ )}
416
+ />
417
+ </form>
418
+ );
419
+ };
420
+
421
+ export const ExampleWithReactHookForm: Story = {
422
+ render: () => <ReactHookFormExample />,
423
+ };
424
+
425
+ export const ShouldWorkWithReactHookForm: Story = {
426
+ ...ExampleWithReactHookForm,
427
+ play: async ({ canvasElement }) => {
428
+ const canvas = within(canvasElement);
429
+ const user = userEvent.setup();
430
+
431
+ await canvas.findByText("Debug selected: wind");
432
+ await expect(canvas.getByRole("radio", { name: "Wind" })).toBeChecked();
433
+ await user.click(canvas.getByText("Solar"));
434
+ await canvas.findByText("Debug selected: solar");
435
+ await expect(canvas.getByRole("radio", { name: "Wind" })).not.toBeChecked();
436
+ },
437
+ };
438
+
439
+ const ReactHookFormRequiredExample = () => {
440
+ const { control, handleSubmit } = useForm<{ energy: string | null }>({
441
+ defaultValues: { energy: null },
442
+ });
443
+
444
+ return (
445
+ <form onSubmit={handleSubmit(() => {})}>
446
+ <Controller
447
+ control={control}
448
+ name="energy"
449
+ rules={{ required: "Select an energy source" }}
450
+ render={({ field, fieldState }) => (
451
+ <RadioGroup
452
+ ref={field.ref}
453
+ label="Energy source"
454
+ name={field.name}
455
+ value={field.value}
456
+ onChange={field.onChange}
457
+ errorHelperText={fieldState.error?.message}
458
+ >
459
+ <EnergyItems />
460
+ </RadioGroup>
461
+ )}
462
+ />
463
+ <button type="submit">Submit</button>
464
+ </form>
465
+ );
466
+ };
467
+
468
+ export const ShouldFocusFirstRadioOnReactHookFormError: Story = {
469
+ render: () => <ReactHookFormRequiredExample />,
470
+ play: async ({ canvasElement }) => {
471
+ const canvas = within(canvasElement);
472
+ const user = userEvent.setup();
473
+
474
+ await user.click(canvas.getByRole("button", { name: "Submit" }));
475
+ await canvas.findByText("Select an energy source");
476
+ await expect(canvas.getByRole("radio", { name: "Solar" })).toHaveFocus();
477
+ },
478
+ };
479
+
480
+ const onNativeSubmit = fn();
481
+
482
+ export const ShouldSubmitValueInNativeForm: Story = {
483
+ beforeEach: () => {
484
+ onNativeSubmit.mockClear();
485
+ },
486
+ render: () => (
487
+ <form
488
+ onSubmit={(event) => {
489
+ event.preventDefault();
490
+ onNativeSubmit(new FormData(event.currentTarget).get("energy"));
491
+ }}
492
+ >
493
+ <RadioGroup label="Energy source" name="energy">
494
+ <EnergyItems />
495
+ </RadioGroup>
496
+ <button type="submit">Submit</button>
497
+ </form>
498
+ ),
499
+ play: async ({ canvasElement }) => {
500
+ const canvas = within(canvasElement);
501
+ const user = userEvent.setup();
502
+
503
+ await user.click(canvas.getByText("Hydro"));
504
+ await user.click(canvas.getByRole("button", { name: "Submit" }));
505
+ await expect(onNativeSubmit).toHaveBeenCalledWith("hydro");
506
+ },
507
+ };
508
+ ```
509
+
510
+ ## Developer notes
511
+
512
+ Here are the notes available for the developer on the built Storybook, you can read them to understand the component and how to use it.
513
+
514
+ ```mdx
515
+ import {
516
+ Canvas,
517
+ Meta,
518
+ Stories,
519
+ Controls,
520
+ Source,
521
+ } from "@storybook/addon-docs/blocks";
522
+
523
+ import * as RadioGroup from "./RadioGroup.stories";
524
+ import * as RadioGroupTests from "./tests/RadioGroup.stories";
525
+
526
+ <Meta of={RadioGroup} />
527
+
528
+ # RadioGroup
529
+
530
+ Lets the user pick one option among several. Each option is a `RadioGroupItem` with a unique `value`.
531
+ The group carries the state (`value` / `defaultValue` / `onChange`), the label, and the helper and error texts.
532
+
533
+ It is built on React Aria: the group is announced as a `radiogroup` with its label, it is a single tab stop,
534
+ and arrow keys move the selection.
535
+
536
+ <Canvas of={RadioGroup.Playground} />
537
+
538
+ ## Controlled example
539
+
540
+ <Source of={RadioGroupTests.ExampleControlled} type="code" dark />
541
+
542
+ ## With react-hook-form
543
+
544
+ Use a `Controller` (or `useController`): `register()` only works with a native input.
545
+ Pass `field.ref` to the group's `ref`: on validation error, react-hook-form then focuses the radio holding the tab stop
546
+ (the selected one, otherwise the first enabled one).
547
+
548
+ <Source of={RadioGroupTests.ExampleWithReactHookForm} type="code" dark />
549
+
550
+ ## Migrating from `Radio`
551
+
552
+ `Radio` is deprecated. To migrate a group of `Radio`s:
553
+
554
+ - Wrap all the radios in one `RadioGroup` and move the group title into its `label` (or `aria-label`).
555
+ - Replace each `Radio` by a `RadioGroupItem` with a `value`: it is now mandatory, even when you used to rely on `checked`.
556
+ - Replace `checked={selected === x}` + `onChange` on each radio by `value={selected}` + `onChange={setSelected}` on the group.
557
+ `onChange` receives the value, not an event.
558
+ - Replace `{...register("field")}` by a `Controller`.
559
+ - Replace `disabled` by `isDisabled`. A radio without visible text takes an `aria-label`.
560
+
561
+ Keep `Radio` for now when the radios can't sit in one block (spread across table cells) or when clicking
562
+ the selected radio must deselect it: a radio group can't be emptied by the user.
563
+
564
+ ### RadioGroup props
565
+
566
+ <Controls of={RadioGroup.Playground} />
567
+
568
+ <Stories />
569
+ ```
@@ -0,0 +1,27 @@
1
+ import { default as React } from 'react';
2
+ export type Props = {
3
+ /**
4
+ * The value of the radio, returned by the `onChange` of the parent `RadioGroup`.
5
+ * Also used as the native `value` attribute when submitting an HTML form.
6
+ */
7
+ value: string;
8
+ /**
9
+ * The text to display next to the radio.
10
+ * If you give a ReactNode or no label at all, also provide an `aria-label`.
11
+ */
12
+ label?: string | React.ReactNode;
13
+ /**
14
+ * Accessible name of the radio, required when there is no string `label`.
15
+ */
16
+ "aria-label"?: string;
17
+ /**
18
+ * Additional text displayed below the label, linked to the radio with `aria-describedby`.
19
+ */
20
+ description?: React.ReactNode;
21
+ /**
22
+ * Whether the radio is disabled.
23
+ */
24
+ isDisabled?: boolean;
25
+ };
26
+ declare const RadioGroupItem: React.ForwardRefExoticComponent<Props & React.RefAttributes<HTMLDivElement>>;
27
+ export default RadioGroupItem;
@@ -9,5 +9,5 @@ export type Props = {
9
9
  useHref?: ComponentProps<typeof AriaRouterProvider>["useHref"];
10
10
  children: ReactNode;
11
11
  };
12
- declare const RouterProvider: ({ children, ...props }: Props) => import("react").JSX.Element;
12
+ declare const RouterProvider: ({ children, ...props }: Props) => import('react').JSX.Element;
13
13
  export default RouterProvider;