@okta/odyssey-react-mui 0.22.0 → 0.23.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 (280) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/Autocomplete.js +5 -1
  3. package/dist/Autocomplete.js.map +1 -1
  4. package/dist/Banner.js +3 -3
  5. package/dist/Banner.js.map +1 -1
  6. package/dist/Button.js +8 -8
  7. package/dist/Button.js.map +1 -1
  8. package/dist/CheckboxGroup.js +23 -35
  9. package/dist/CheckboxGroup.js.map +1 -1
  10. package/dist/Dialog.js +68 -0
  11. package/dist/Dialog.js.map +1 -0
  12. package/dist/Field.js +18 -5
  13. package/dist/Field.js.map +1 -1
  14. package/dist/FieldLabel.js +3 -3
  15. package/dist/FieldLabel.js.map +1 -1
  16. package/dist/Icon.js +7 -6
  17. package/dist/Icon.js.map +1 -1
  18. package/dist/Infobox.js +1 -1
  19. package/dist/Infobox.js.map +1 -1
  20. package/dist/Link.js +5 -2
  21. package/dist/Link.js.map +1 -1
  22. package/dist/MenuButton.js +3 -2
  23. package/dist/MenuButton.js.map +1 -1
  24. package/dist/MuiPropsChild.js +30 -0
  25. package/dist/MuiPropsChild.js.map +1 -0
  26. package/dist/MuiPropsContext.js +14 -0
  27. package/dist/MuiPropsContext.js.map +1 -0
  28. package/dist/PasswordField.js +8 -3
  29. package/dist/PasswordField.js.map +1 -1
  30. package/dist/RadioGroup.js +25 -26
  31. package/dist/RadioGroup.js.map +1 -1
  32. package/dist/SearchField.js +6 -4
  33. package/dist/SearchField.js.map +1 -1
  34. package/dist/Status.js.map +1 -1
  35. package/dist/TextField.js +17 -8
  36. package/dist/TextField.js.map +1 -1
  37. package/dist/Toast.js +72 -0
  38. package/dist/Toast.js.map +1 -0
  39. package/dist/ToastStack.js +33 -0
  40. package/dist/ToastStack.js.map +1 -0
  41. package/dist/Tooltip.js +20 -0
  42. package/dist/Tooltip.js.map +1 -0
  43. package/dist/iconDictionary/Add.js +4 -4
  44. package/dist/iconDictionary/Add.js.map +1 -1
  45. package/dist/iconDictionary/AddCircle.js +4 -4
  46. package/dist/iconDictionary/AddCircle.js.map +1 -1
  47. package/dist/iconDictionary/AlertCircle.js +4 -4
  48. package/dist/iconDictionary/AlertCircle.js.map +1 -1
  49. package/dist/iconDictionary/AlertCircleFilled.js +4 -4
  50. package/dist/iconDictionary/AlertCircleFilled.js.map +1 -1
  51. package/dist/iconDictionary/AlertTriangleFilled.js +4 -4
  52. package/dist/iconDictionary/AlertTriangleFilled.js.map +1 -1
  53. package/dist/iconDictionary/Anchor.js +5 -5
  54. package/dist/iconDictionary/Anchor.js.map +1 -1
  55. package/dist/iconDictionary/ArrowDown.js +4 -4
  56. package/dist/iconDictionary/ArrowDown.js.map +1 -1
  57. package/dist/iconDictionary/ArrowLeft.js +4 -4
  58. package/dist/iconDictionary/ArrowLeft.js.map +1 -1
  59. package/dist/iconDictionary/ArrowRight.js +4 -4
  60. package/dist/iconDictionary/ArrowRight.js.map +1 -1
  61. package/dist/iconDictionary/ArrowUp.js +4 -4
  62. package/dist/iconDictionary/ArrowUp.js.map +1 -1
  63. package/dist/iconDictionary/ArrowUpDown.js +4 -4
  64. package/dist/iconDictionary/ArrowUpDown.js.map +1 -1
  65. package/dist/iconDictionary/Calendar.js +4 -4
  66. package/dist/iconDictionary/Calendar.js.map +1 -1
  67. package/dist/iconDictionary/Check.js +4 -4
  68. package/dist/iconDictionary/Check.js.map +1 -1
  69. package/dist/iconDictionary/CheckCircleFilled.js +4 -4
  70. package/dist/iconDictionary/CheckCircleFilled.js.map +1 -1
  71. package/dist/iconDictionary/ChevronDown.js +4 -4
  72. package/dist/iconDictionary/ChevronDown.js.map +1 -1
  73. package/dist/iconDictionary/ChevronUp.js +4 -4
  74. package/dist/iconDictionary/ChevronUp.js.map +1 -1
  75. package/dist/iconDictionary/Close.js +4 -4
  76. package/dist/iconDictionary/Close.js.map +1 -1
  77. package/dist/iconDictionary/CloseCircleFilled.js +4 -4
  78. package/dist/iconDictionary/CloseCircleFilled.js.map +1 -1
  79. package/dist/iconDictionary/Copy.js +4 -4
  80. package/dist/iconDictionary/Copy.js.map +1 -1
  81. package/dist/iconDictionary/Delete.js +4 -4
  82. package/dist/iconDictionary/Delete.js.map +1 -1
  83. package/dist/iconDictionary/Download.js +4 -4
  84. package/dist/iconDictionary/Download.js.map +1 -1
  85. package/dist/iconDictionary/DragHandle.js +4 -4
  86. package/dist/iconDictionary/DragHandle.js.map +1 -1
  87. package/dist/iconDictionary/Edit.js +4 -4
  88. package/dist/iconDictionary/Edit.js.map +1 -1
  89. package/dist/iconDictionary/ExternalLink.js +4 -4
  90. package/dist/iconDictionary/ExternalLink.js.map +1 -1
  91. package/dist/iconDictionary/Eye.js +4 -4
  92. package/dist/iconDictionary/Eye.js.map +1 -1
  93. package/dist/iconDictionary/EyeOff.js +4 -4
  94. package/dist/iconDictionary/EyeOff.js.map +1 -1
  95. package/dist/iconDictionary/Filter.js +4 -4
  96. package/dist/iconDictionary/Filter.js.map +1 -1
  97. package/dist/iconDictionary/Globe.js +4 -4
  98. package/dist/iconDictionary/Globe.js.map +1 -1
  99. package/dist/iconDictionary/Home.js +4 -4
  100. package/dist/iconDictionary/Home.js.map +1 -1
  101. package/dist/iconDictionary/InformationCircle.js +4 -4
  102. package/dist/iconDictionary/InformationCircle.js.map +1 -1
  103. package/dist/iconDictionary/InformationCircleFilled.js +4 -4
  104. package/dist/iconDictionary/InformationCircleFilled.js.map +1 -1
  105. package/dist/iconDictionary/Notification.js +4 -4
  106. package/dist/iconDictionary/Notification.js.map +1 -1
  107. package/dist/iconDictionary/OverflowVertical.js +4 -4
  108. package/dist/iconDictionary/OverflowVertical.js.map +1 -1
  109. package/dist/iconDictionary/QuestionCircle.js +4 -4
  110. package/dist/iconDictionary/QuestionCircle.js.map +1 -1
  111. package/dist/iconDictionary/QuestionCircleFilled.js +4 -4
  112. package/dist/iconDictionary/QuestionCircleFilled.js.map +1 -1
  113. package/dist/iconDictionary/Search.js +4 -4
  114. package/dist/iconDictionary/Search.js.map +1 -1
  115. package/dist/iconDictionary/Settings.js +3 -3
  116. package/dist/iconDictionary/Settings.js.map +1 -1
  117. package/dist/iconDictionary/Subtract.js +4 -4
  118. package/dist/iconDictionary/Subtract.js.map +1 -1
  119. package/dist/iconDictionary/User.js +4 -4
  120. package/dist/iconDictionary/User.js.map +1 -1
  121. package/dist/iconDictionary/UserGroup.js +4 -4
  122. package/dist/iconDictionary/UserGroup.js.map +1 -1
  123. package/dist/iconDictionary/index.js.map +1 -1
  124. package/dist/index.js +5 -4
  125. package/dist/index.js.map +1 -1
  126. package/dist/src/Autocomplete.d.ts +2 -1
  127. package/dist/src/Autocomplete.d.ts.map +1 -1
  128. package/dist/src/Banner.d.ts +19 -19
  129. package/dist/src/Banner.d.ts.map +1 -1
  130. package/dist/src/Button.d.ts +4 -3
  131. package/dist/src/Button.d.ts.map +1 -1
  132. package/dist/src/CheckboxGroup.d.ts +7 -4
  133. package/dist/src/CheckboxGroup.d.ts.map +1 -1
  134. package/dist/src/Dialog.d.ts +25 -0
  135. package/dist/src/Dialog.d.ts.map +1 -0
  136. package/dist/src/Field.d.ts +14 -3
  137. package/dist/src/Field.d.ts.map +1 -1
  138. package/dist/src/FieldLabel.d.ts +2 -2
  139. package/dist/src/Icon.d.ts +6 -7
  140. package/dist/src/Icon.d.ts.map +1 -1
  141. package/dist/src/Infobox.d.ts +7 -7
  142. package/dist/src/Infobox.d.ts.map +1 -1
  143. package/dist/src/Link.d.ts +9 -4
  144. package/dist/src/Link.d.ts.map +1 -1
  145. package/dist/src/MenuButton.d.ts +7 -3
  146. package/dist/src/MenuButton.d.ts.map +1 -1
  147. package/dist/src/MenuItem.d.ts +1 -1
  148. package/dist/src/MuiPropsChild.d.ts +18 -0
  149. package/dist/src/MuiPropsChild.d.ts.map +1 -0
  150. package/dist/src/MuiPropsContext.d.ts +15 -0
  151. package/dist/src/MuiPropsContext.d.ts.map +1 -0
  152. package/dist/src/PasswordField.d.ts +8 -8
  153. package/dist/src/PasswordField.d.ts.map +1 -1
  154. package/dist/src/RadioGroup.d.ts +8 -8
  155. package/dist/src/RadioGroup.d.ts.map +1 -1
  156. package/dist/src/SearchField.d.ts +4 -4
  157. package/dist/src/SearchField.d.ts.map +1 -1
  158. package/dist/src/Status.d.ts +2 -2
  159. package/dist/src/Status.d.ts.map +1 -1
  160. package/dist/src/TextField.d.ts +13 -12
  161. package/dist/src/TextField.d.ts.map +1 -1
  162. package/dist/src/Toast.d.ts +60 -0
  163. package/dist/src/Toast.d.ts.map +1 -0
  164. package/dist/src/ToastStack.d.ts +19 -0
  165. package/dist/src/ToastStack.d.ts.map +1 -0
  166. package/dist/src/Tooltip.d.ts +21 -0
  167. package/dist/src/Tooltip.d.ts.map +1 -0
  168. package/dist/src/iconDictionary/Add.d.ts +2 -2
  169. package/dist/src/iconDictionary/AddCircle.d.ts +2 -2
  170. package/dist/src/iconDictionary/AlertCircle.d.ts +2 -2
  171. package/dist/src/iconDictionary/AlertCircleFilled.d.ts +2 -2
  172. package/dist/src/iconDictionary/AlertTriangleFilled.d.ts +2 -2
  173. package/dist/src/iconDictionary/Anchor.d.ts +2 -2
  174. package/dist/src/iconDictionary/ArrowDown.d.ts +2 -2
  175. package/dist/src/iconDictionary/ArrowLeft.d.ts +2 -2
  176. package/dist/src/iconDictionary/ArrowRight.d.ts +2 -2
  177. package/dist/src/iconDictionary/ArrowUp.d.ts +2 -2
  178. package/dist/src/iconDictionary/ArrowUpDown.d.ts +2 -2
  179. package/dist/src/iconDictionary/Calendar.d.ts +2 -2
  180. package/dist/src/iconDictionary/Check.d.ts +2 -2
  181. package/dist/src/iconDictionary/CheckCircleFilled.d.ts +2 -2
  182. package/dist/src/iconDictionary/ChevronDown.d.ts +2 -2
  183. package/dist/src/iconDictionary/ChevronUp.d.ts +2 -2
  184. package/dist/src/iconDictionary/Close.d.ts +2 -2
  185. package/dist/src/iconDictionary/CloseCircleFilled.d.ts +2 -2
  186. package/dist/src/iconDictionary/Copy.d.ts +2 -2
  187. package/dist/src/iconDictionary/Delete.d.ts +2 -2
  188. package/dist/src/iconDictionary/Download.d.ts +2 -2
  189. package/dist/src/iconDictionary/DragHandle.d.ts +2 -2
  190. package/dist/src/iconDictionary/Edit.d.ts +2 -2
  191. package/dist/src/iconDictionary/ExternalLink.d.ts +2 -2
  192. package/dist/src/iconDictionary/Eye.d.ts +2 -2
  193. package/dist/src/iconDictionary/EyeOff.d.ts +2 -2
  194. package/dist/src/iconDictionary/Filter.d.ts +2 -2
  195. package/dist/src/iconDictionary/Globe.d.ts +2 -2
  196. package/dist/src/iconDictionary/Home.d.ts +2 -2
  197. package/dist/src/iconDictionary/InformationCircle.d.ts +2 -2
  198. package/dist/src/iconDictionary/InformationCircleFilled.d.ts +2 -2
  199. package/dist/src/iconDictionary/Notification.d.ts +2 -2
  200. package/dist/src/iconDictionary/OverflowVertical.d.ts +2 -2
  201. package/dist/src/iconDictionary/QuestionCircle.d.ts +2 -2
  202. package/dist/src/iconDictionary/QuestionCircleFilled.d.ts +2 -2
  203. package/dist/src/iconDictionary/Search.d.ts +2 -2
  204. package/dist/src/iconDictionary/Settings.d.ts +2 -2
  205. package/dist/src/iconDictionary/Subtract.d.ts +2 -2
  206. package/dist/src/iconDictionary/User.d.ts +2 -2
  207. package/dist/src/iconDictionary/UserGroup.d.ts +2 -2
  208. package/dist/src/iconDictionary/index.d.ts +40 -40
  209. package/dist/src/index.d.ts +8 -7
  210. package/dist/src/index.d.ts.map +1 -1
  211. package/dist/src/theme/components.d.ts.map +1 -1
  212. package/dist/theme/components.js +32 -12
  213. package/dist/theme/components.js.map +1 -1
  214. package/dist/tsconfig.production.tsbuildinfo +1 -1
  215. package/package.json +3 -3
  216. package/src/Autocomplete.tsx +10 -1
  217. package/src/Banner.tsx +21 -21
  218. package/src/Button.tsx +38 -18
  219. package/src/CheckboxGroup.tsx +27 -34
  220. package/src/Dialog.tsx +110 -0
  221. package/src/Field.tsx +42 -19
  222. package/src/FieldLabel.tsx +7 -7
  223. package/src/Icon.test.tsx +1 -1
  224. package/src/Icon.tsx +24 -7
  225. package/src/Infobox.tsx +7 -7
  226. package/src/Link.tsx +14 -6
  227. package/src/MenuButton.tsx +8 -3
  228. package/src/MuiPropsChild.tsx +41 -0
  229. package/src/MuiPropsContext.ts +17 -0
  230. package/src/PasswordField.tsx +17 -11
  231. package/src/RadioGroup.tsx +31 -46
  232. package/src/SearchField.tsx +10 -8
  233. package/src/Status.tsx +2 -2
  234. package/src/TextField.tsx +32 -21
  235. package/src/Toast.tsx +138 -0
  236. package/src/ToastStack.tsx +33 -0
  237. package/src/Tooltip.tsx +39 -0
  238. package/src/iconDictionary/Add.tsx +3 -3
  239. package/src/iconDictionary/AddCircle.tsx +3 -3
  240. package/src/iconDictionary/AlertCircle.tsx +3 -3
  241. package/src/iconDictionary/AlertCircleFilled.tsx +3 -3
  242. package/src/iconDictionary/AlertTriangleFilled.tsx +3 -3
  243. package/src/iconDictionary/Anchor.tsx +3 -3
  244. package/src/iconDictionary/ArrowDown.tsx +3 -3
  245. package/src/iconDictionary/ArrowLeft.tsx +3 -3
  246. package/src/iconDictionary/ArrowRight.tsx +3 -3
  247. package/src/iconDictionary/ArrowUp.tsx +3 -3
  248. package/src/iconDictionary/ArrowUpDown.tsx +3 -3
  249. package/src/iconDictionary/Calendar.tsx +3 -3
  250. package/src/iconDictionary/Check.tsx +3 -3
  251. package/src/iconDictionary/CheckCircleFilled.tsx +3 -3
  252. package/src/iconDictionary/ChevronDown.tsx +3 -3
  253. package/src/iconDictionary/ChevronUp.tsx +3 -3
  254. package/src/iconDictionary/Close.tsx +3 -3
  255. package/src/iconDictionary/CloseCircleFilled.tsx +3 -3
  256. package/src/iconDictionary/Copy.tsx +3 -3
  257. package/src/iconDictionary/Delete.tsx +3 -3
  258. package/src/iconDictionary/Download.tsx +3 -3
  259. package/src/iconDictionary/DragHandle.tsx +3 -3
  260. package/src/iconDictionary/Edit.tsx +3 -3
  261. package/src/iconDictionary/ExternalLink.tsx +3 -3
  262. package/src/iconDictionary/Eye.tsx +3 -3
  263. package/src/iconDictionary/EyeOff.tsx +3 -3
  264. package/src/iconDictionary/Filter.tsx +3 -3
  265. package/src/iconDictionary/Globe.tsx +3 -3
  266. package/src/iconDictionary/Home.tsx +3 -3
  267. package/src/iconDictionary/InformationCircle.tsx +3 -3
  268. package/src/iconDictionary/InformationCircleFilled.tsx +3 -3
  269. package/src/iconDictionary/Notification.tsx +3 -3
  270. package/src/iconDictionary/OverflowVertical.tsx +3 -3
  271. package/src/iconDictionary/QuestionCircle.tsx +3 -3
  272. package/src/iconDictionary/QuestionCircleFilled.tsx +3 -3
  273. package/src/iconDictionary/Search.tsx +3 -3
  274. package/src/iconDictionary/Settings.tsx +2 -2
  275. package/src/iconDictionary/Subtract.tsx +3 -3
  276. package/src/iconDictionary/User.tsx +3 -3
  277. package/src/iconDictionary/UserGroup.tsx +3 -3
  278. package/src/iconDictionary/index.ts +1 -1
  279. package/src/index.ts +4 -14
  280. package/src/theme/components.tsx +32 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@okta/odyssey-react-mui",
3
- "version": "0.22.0",
3
+ "version": "0.23.0",
4
4
  "description": "React MUI components for Odyssey, Okta's design system",
5
5
  "author": "Okta, Inc.",
6
6
  "license": "Apache-2.0",
@@ -25,7 +25,7 @@
25
25
  "@mui/lab": "^5.0.0-alpha.117",
26
26
  "@mui/material": "^5.11.6",
27
27
  "@mui/utils": "^5.11.2",
28
- "@okta/odyssey-design-tokens": "0.22.0"
28
+ "@okta/odyssey-design-tokens": "0.23.0"
29
29
  },
30
30
  "peerDependencies": {
31
31
  "@emotion/react": "^11",
@@ -33,5 +33,5 @@
33
33
  "react": ">=17 <19",
34
34
  "react-dom": ">=17 <19"
35
35
  },
36
- "gitHead": "b1a4a93f7d570162a52e4c28012fb65e31d5bb4b"
36
+ "gitHead": "46e7484fa0317496e65b9ba8b3f930956b0470e9"
37
37
  }
@@ -62,6 +62,12 @@ export type AutocompleteProps<
62
62
  undefined,
63
63
  IsCustomValueAllowed
64
64
  >["onChange"];
65
+ onInputChange?: MuiAutocompleteProps<
66
+ OptionType,
67
+ HasMultipleChoices,
68
+ undefined,
69
+ IsCustomValueAllowed
70
+ >["onInputChange"];
65
71
  options: MuiAutocompleteProps<
66
72
  OptionType,
67
73
  HasMultipleChoices,
@@ -89,14 +95,16 @@ const Autocomplete = <
89
95
  hint,
90
96
  label,
91
97
  onChange,
98
+ onInputChange,
92
99
  options,
93
100
  value,
94
101
  }: AutocompleteProps<OptionType, HasMultipleChoices, IsCustomValueAllowed>) => {
95
102
  const renderInput = useCallback(
96
103
  ({ InputLabelProps, InputProps, ...params }) => (
97
104
  <Field
98
- {...InputLabelProps}
105
+ fieldType="single"
99
106
  hasVisibleLabel
107
+ id={InputLabelProps.htmlFor}
100
108
  hint={hint}
101
109
  label={label}
102
110
  renderFieldComponent={({ ariaDescribedBy, id }) => (
@@ -119,6 +127,7 @@ const Autocomplete = <
119
127
  loading={isLoading}
120
128
  multiple={hasMultipleChoices}
121
129
  onChange={onChange}
130
+ onInputChange={onInputChange}
122
131
  options={options}
123
132
  readOnly={isReadOnly}
124
133
  renderInput={renderInput}
package/src/Banner.tsx CHANGED
@@ -14,44 +14,44 @@ import { AlertColor, AlertProps } from "@mui/material";
14
14
  import { memo } from "react";
15
15
  import { Alert, Link, ScreenReaderText } from "./";
16
16
 
17
- export interface BannerProps {
17
+ export type BannerProps = {
18
18
  /**
19
- * Determine the color and icon of the alert
20
- */
21
- severity: AlertColor;
22
- /**
23
- * Sets the ARIA role of the alert
24
- * ("status" for something that dynamically updates, "alert" for errors, null for something
25
- * unchanging)
19
+ * If linkUrl is not undefined, this is the text of the link.
20
+ * If left blank, it defaults to "Learn more".
21
+ * Note that linkText does nothing if linkUrl is not defined
26
22
  */
27
- role?: "status" | "alert";
23
+ linkText?: string;
28
24
  /**
29
- * The text content of the alert
25
+ * If defined, the alert will include a link to the URL
30
26
  */
31
- text: string;
27
+ linkUrl?: string;
32
28
  /**
33
29
  * The function that's fired when the user clicks the close button. If undefined,
34
30
  * the close button will not be shown.
35
31
  */
36
32
  onClose?: AlertProps["onClose"];
37
33
  /**
38
- * If defined, the alert will include a link to the URL
34
+ * Sets the ARIA role of the alert
35
+ * ("status" for something that dynamically updates, "alert" for errors, null for something
36
+ * unchanging)
39
37
  */
40
- linkUrl?: string;
38
+ role?: "status" | "alert";
41
39
  /**
42
- * If linkUrl is not undefined, this is the text of the link.
43
- * If left blank, it defaults to "Learn more".
44
- * Note that linkText does nothing if linkUrl is not defined
40
+ * Determine the color and icon of the alert
45
41
  */
46
- linkText?: string;
47
- }
42
+ severity: AlertColor;
43
+ /**
44
+ * The text content of the alert
45
+ */
46
+ text: string;
47
+ };
48
48
 
49
49
  const Banner = ({
50
- onClose,
51
- severity,
52
- role,
53
50
  linkUrl,
54
51
  linkText,
52
+ onClose,
53
+ role,
54
+ severity,
55
55
  text,
56
56
  }: BannerProps) => (
57
57
  <Alert onClose={onClose} role={role} severity={severity} variant="banner">
package/src/Button.tsx CHANGED
@@ -12,17 +12,20 @@
12
12
 
13
13
  import { Button as MuiButton } from "@mui/material";
14
14
  import type { ButtonProps as MuiButtonProps } from "@mui/material";
15
- import { Tooltip } from "./";
16
- import { memo } from "react";
15
+ import { memo, ReactElement, useContext, useMemo } from "react";
16
+
17
+ import { Icon } from "./Icon";
18
+ import { MuiPropsContext } from "./MuiPropsContext";
19
+ import { Tooltip } from "./Tooltip";
17
20
 
18
21
  export type ButtonProps = {
19
- endIcon?: React.ReactNode;
22
+ endIcon?: ReactElement<typeof Icon>;
20
23
  id?: string;
21
24
  isDisabled?: boolean;
22
25
  isFullWidth?: boolean;
23
26
  onClick?: MuiButtonProps["onClick"];
24
27
  size?: MuiButtonProps["size"];
25
- startIcon?: React.ReactNode;
28
+ startIcon?: ReactElement<typeof Icon>;
26
29
  text?: string;
27
30
  /**
28
31
  * `tooltipText` determines the text of the tooltip that wraps the button if it's icon-only.
@@ -43,25 +46,42 @@ const Button = ({
43
46
  tooltipText,
44
47
  variant,
45
48
  }: ButtonProps) => {
46
- const button = (
47
- <MuiButton
48
- disabled={isDisabled}
49
- endIcon={endIcon}
50
- fullWidth={isFullWidth}
51
- id={id}
52
- onClick={onClick}
53
- size={size}
54
- startIcon={startIcon}
55
- variant={variant}
56
- >
57
- {text}
58
- </MuiButton>
49
+ const muiProps = useContext(MuiPropsContext);
50
+
51
+ const button = useMemo(
52
+ () => (
53
+ <MuiButton
54
+ {...muiProps}
55
+ disabled={isDisabled}
56
+ endIcon={endIcon}
57
+ fullWidth={isFullWidth}
58
+ id={id}
59
+ onClick={onClick}
60
+ size={size}
61
+ startIcon={startIcon}
62
+ variant={variant}
63
+ >
64
+ {text}
65
+ </MuiButton>
66
+ ),
67
+ [
68
+ endIcon,
69
+ id,
70
+ isDisabled,
71
+ isFullWidth,
72
+ muiProps,
73
+ onClick,
74
+ size,
75
+ startIcon,
76
+ text,
77
+ variant,
78
+ ]
59
79
  );
60
80
 
61
81
  return (
62
82
  <>
63
83
  {tooltipText && (
64
- <Tooltip describeChild placement="top" title={tooltipText}>
84
+ <Tooltip ariaType="description" placement="top" text={tooltipText}>
65
85
  {button}
66
86
  </Tooltip>
67
87
  )}
@@ -10,16 +10,11 @@
10
10
  * See the License for the specific language governing permissions and limitations under the License.
11
11
  */
12
12
 
13
- import { memo, ReactElement, useMemo } from "react";
13
+ import { FormGroup as MuiFormGroup } from "@mui/material";
14
+ import { memo, ReactElement, useCallback } from "react";
14
15
 
15
- import {
16
- Checkbox,
17
- FormControl,
18
- FormGroup,
19
- FormHelperText,
20
- FormLabel,
21
- ScreenReaderText,
22
- } from ".";
16
+ import { Checkbox } from "./Checkbox";
17
+ import { Field } from "./Field";
23
18
 
24
19
  export type CheckboxGroupProps = {
25
20
  children:
@@ -27,9 +22,12 @@ export type CheckboxGroupProps = {
27
22
  | Array<ReactElement<typeof Checkbox>>;
28
23
  errorMessage?: string;
29
24
  hint?: string;
25
+ /**
26
+ * The id of the `input` element. This will also be the input's `name` field.
27
+ */
28
+ id?: string;
30
29
  isDisabled?: boolean;
31
- label?: string;
32
- name?: string;
30
+ label: string;
33
31
  };
34
32
 
35
33
  const CheckboxGroup = ({
@@ -37,34 +35,29 @@ const CheckboxGroup = ({
37
35
  isDisabled,
38
36
  errorMessage,
39
37
  hint,
38
+ id: idOverride,
40
39
  label,
41
- name,
42
40
  }: CheckboxGroupProps) => {
43
- const ariaDescribedBy = useMemo(
44
- () =>
45
- errorMessage || hint
46
- ? [hint && `${name}-hint`, errorMessage && `${name}-error`]
47
- .filter(Boolean)
48
- .join(" ")
49
- : undefined,
50
- [errorMessage, hint, name]
41
+ const renderFieldComponent = useCallback(
42
+ ({ ariaDescribedBy, id }) => (
43
+ <MuiFormGroup aria-describedby={ariaDescribedBy} id={id}>
44
+ {children}
45
+ </MuiFormGroup>
46
+ ),
47
+ [children]
51
48
  );
52
49
 
53
50
  return (
54
- <FormControl
55
- component="fieldset"
56
- disabled={isDisabled}
57
- error={Boolean(errorMessage)}
58
- >
59
- {label && <FormLabel component="legend">{label}</FormLabel>}
60
- {hint && <FormHelperText id={`${name}-hint`}>{hint}</FormHelperText>}
61
- <FormGroup aria-describedby={ariaDescribedBy}>{children}</FormGroup>
62
- {errorMessage && (
63
- <FormHelperText id={`${name}-error`} error>
64
- <ScreenReaderText>Error:</ScreenReaderText> {errorMessage}
65
- </FormHelperText>
66
- )}
67
- </FormControl>
51
+ <Field
52
+ errorMessage={errorMessage}
53
+ fieldType="group"
54
+ hasVisibleLabel={false}
55
+ hint={hint}
56
+ id={idOverride}
57
+ isDisabled={isDisabled}
58
+ label={label}
59
+ renderFieldComponent={renderFieldComponent}
60
+ />
68
61
  );
69
62
  };
70
63
 
package/src/Dialog.tsx ADDED
@@ -0,0 +1,110 @@
1
+ /*!
2
+ * Copyright (c) 2022-present, Okta, Inc. and/or its affiliates. All rights reserved.
3
+ * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
4
+ *
5
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
6
+ * Unless required by applicable law or agreed to in writing, software
7
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
8
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9
+ *
10
+ * See the License for the specific language governing permissions and limitations under the License.
11
+ */
12
+
13
+ import { Dialog as MuiDialog } from "@mui/material";
14
+ import {
15
+ DialogTitle,
16
+ DialogContent,
17
+ DialogContentText,
18
+ DialogActions,
19
+ } from "@mui/material";
20
+ import { Button, CloseIcon } from "./";
21
+ import {
22
+ memo,
23
+ ReactNode,
24
+ useState,
25
+ useEffect,
26
+ useRef,
27
+ ReactElement,
28
+ } from "react";
29
+
30
+ export type DialogProps = {
31
+ callToActionPrimaryComponent?: ReactElement<typeof Button>;
32
+ callToActionSecondaryComponent?: ReactElement<typeof Button>;
33
+ callToActionTertiaryComponent?: ReactElement<typeof Button>;
34
+ children: ReactNode | Array<ReactNode>;
35
+ onClose: () => void;
36
+ isOpen: boolean;
37
+ title: string;
38
+ };
39
+
40
+ const Dialog = ({
41
+ callToActionPrimaryComponent,
42
+ callToActionSecondaryComponent,
43
+ callToActionTertiaryComponent,
44
+ children,
45
+ isOpen,
46
+ onClose,
47
+ title,
48
+ }: DialogProps) => {
49
+ const [isContentScrollable, setIsContentScrollable] = useState(false);
50
+ const dialogContentRef = useRef<HTMLDivElement>(null);
51
+
52
+ useEffect(() => {
53
+ let frameId: number;
54
+
55
+ const handleContentScroll = () => {
56
+ const dialogContentElement = dialogContentRef.current;
57
+ if (dialogContentElement) {
58
+ setIsContentScrollable(
59
+ dialogContentElement.scrollHeight > dialogContentElement.clientHeight
60
+ );
61
+ }
62
+ frameId = requestAnimationFrame(handleContentScroll);
63
+ };
64
+
65
+ if (isOpen) {
66
+ frameId = requestAnimationFrame(handleContentScroll);
67
+ }
68
+
69
+ return () => {
70
+ cancelAnimationFrame(frameId);
71
+ };
72
+ }, [isOpen]);
73
+
74
+ const content =
75
+ typeof children === "string" ? (
76
+ <DialogContentText>{children}</DialogContentText>
77
+ ) : (
78
+ children
79
+ );
80
+
81
+ return (
82
+ <MuiDialog open={isOpen} onClose={onClose}>
83
+ <DialogTitle>
84
+ {title}
85
+ <Button
86
+ variant="floating"
87
+ onClick={onClose}
88
+ startIcon={<CloseIcon />}
89
+ />
90
+ </DialogTitle>
91
+ <DialogContent dividers={isContentScrollable} ref={dialogContentRef}>
92
+ {content}
93
+ </DialogContent>
94
+
95
+ {(callToActionPrimaryComponent ||
96
+ callToActionSecondaryComponent ||
97
+ callToActionTertiaryComponent) && (
98
+ <DialogActions>
99
+ {callToActionTertiaryComponent}
100
+ {callToActionSecondaryComponent}
101
+ {callToActionPrimaryComponent}
102
+ </DialogActions>
103
+ )}
104
+ </MuiDialog>
105
+ );
106
+ };
107
+
108
+ const MemoizedDialog = memo(Dialog);
109
+
110
+ export { MemoizedDialog as Dialog };
package/src/Field.tsx CHANGED
@@ -13,18 +13,23 @@
13
13
  import { memo, ReactElement, useMemo } from "react";
14
14
 
15
15
  import {
16
- FieldError,
17
- FieldHint,
18
- FieldLabel,
19
- FormControl,
20
- useUniqueId,
21
- } from "./";
16
+ FormControl as MuiFormControl,
17
+ FormLabel as MuiFormLabel,
18
+ } from "@mui/material";
19
+ import { FieldError } from "./FieldError";
20
+ import { FieldHint } from "./FieldHint";
21
+ import { FieldLabel } from "./FieldLabel";
22
+ import { useUniqueId } from "./useUniqueId";
22
23
 
23
24
  export type FieldProps = {
24
25
  /**
25
26
  * If `error` is not undefined, the `input` will indicate an error.
26
27
  */
27
28
  errorMessage?: string;
29
+ /**
30
+ * The field type determines how ARIA components are setup. It's important to use this to denote if you expect only one component (like a text field) or multiple (like a radio group).
31
+ */
32
+ fieldType: "single" | "group";
28
33
  hasVisibleLabel: boolean;
29
34
  /**
30
35
  * The helper text content.
@@ -34,14 +39,18 @@ export type FieldProps = {
34
39
  * The id of the `input` element.
35
40
  */
36
41
  id?: string;
42
+ /**
43
+ * Important for narrowing down the `fieldset` role to "radiogroup".
44
+ */
45
+ isRadioGroup?: boolean;
37
46
  /**
38
47
  * If `true`, the component is disabled.
39
48
  */
40
49
  isDisabled?: boolean;
41
50
  /**
42
- * If `true`, the `input` element is required.
51
+ * If `true`, the `input` element is not required.
43
52
  */
44
- isRequired?: boolean;
53
+ isOptional?: boolean;
45
54
  /**
46
55
  * The label for the `input` element.
47
56
  */
@@ -54,6 +63,9 @@ export type FieldProps = {
54
63
  * The short hint displayed in the `input` before the user enters a value.
55
64
  */
56
65
  placeholder?: string;
66
+ /**
67
+ * Render-props function that sends back ARIA props to your field component.
68
+ */
57
69
  renderFieldComponent: ({
58
70
  ariaDescribedBy,
59
71
  id,
@@ -65,11 +77,13 @@ export type FieldProps = {
65
77
 
66
78
  const Field = ({
67
79
  errorMessage,
80
+ fieldType,
68
81
  hasVisibleLabel,
69
82
  hint,
70
83
  id: idOverride,
71
84
  isDisabled = false,
72
- isRequired = true,
85
+ isRadioGroup = false,
86
+ isOptional = false,
73
87
  label,
74
88
  optionalLabel,
75
89
  renderFieldComponent,
@@ -85,15 +99,24 @@ const Field = ({
85
99
  );
86
100
 
87
101
  return (
88
- <FormControl disabled={isDisabled} error={Boolean(errorMessage)}>
89
- <FieldLabel
90
- hasVisibleLabel={hasVisibleLabel}
91
- id={labelId}
92
- inputId={id}
93
- isRequired={isRequired}
94
- optionalText={optionalLabel}
95
- text={label}
96
- />
102
+ <MuiFormControl
103
+ component={fieldType === "group" ? "fieldset" : "div"}
104
+ disabled={isDisabled}
105
+ error={Boolean(errorMessage)}
106
+ role={isRadioGroup ? "radiogroup" : undefined}
107
+ >
108
+ {fieldType === "group" ? (
109
+ <MuiFormLabel component="legend">{label}</MuiFormLabel>
110
+ ) : (
111
+ <FieldLabel
112
+ hasVisibleLabel={hasVisibleLabel}
113
+ id={labelId}
114
+ inputId={id}
115
+ isOptional={isOptional}
116
+ optionalText={optionalLabel}
117
+ text={label}
118
+ />
119
+ )}
97
120
 
98
121
  {hint && <FieldHint id={hintId} text={hint} />}
99
122
 
@@ -103,7 +126,7 @@ const Field = ({
103
126
  })}
104
127
 
105
128
  {errorMessage && <FieldError id={errorId} text={errorMessage} />}
106
- </FormControl>
129
+ </MuiFormControl>
107
130
  );
108
131
  };
109
132
 
@@ -10,7 +10,7 @@
10
10
  * See the License for the specific language governing permissions and limitations under the License.
11
11
  */
12
12
 
13
- import { InputLabel } from "@mui/material";
13
+ import { InputLabel as MuiInputLabel } from "@mui/material";
14
14
  import { memo, useMemo } from "react";
15
15
 
16
16
  import { ScreenReaderText } from "./ScreenReaderText";
@@ -20,7 +20,7 @@ export type FieldLabelProps = {
20
20
  hasVisibleLabel: boolean;
21
21
  id: string;
22
22
  inputId: string;
23
- isRequired: boolean;
23
+ isOptional: boolean;
24
24
  optionalText?: string;
25
25
  text: string;
26
26
  };
@@ -29,20 +29,20 @@ const FieldLabel = ({
29
29
  hasVisibleLabel,
30
30
  id,
31
31
  inputId,
32
- isRequired,
32
+ isOptional,
33
33
  optionalText,
34
34
  text,
35
35
  }: FieldLabelProps) => {
36
36
  const inputLabel = useMemo(
37
37
  () => (
38
- <InputLabel htmlFor={inputId} id={id}>
38
+ <MuiInputLabel htmlFor={inputId} id={id}>
39
39
  {text}
40
- {!isRequired && (
40
+ {isOptional && (
41
41
  <Typography variant="subtitle1">{optionalText}</Typography>
42
42
  )}
43
- </InputLabel>
43
+ </MuiInputLabel>
44
44
  ),
45
- [id, inputId, isRequired, optionalText, text]
45
+ [id, inputId, isOptional, optionalText, text]
46
46
  );
47
47
 
48
48
  return hasVisibleLabel ? (
package/src/Icon.test.tsx CHANGED
@@ -18,7 +18,7 @@ const name = "check";
18
18
 
19
19
  describe("Icon", () => {
20
20
  it("renders an icon based on name prop", () => {
21
- render(<Icon name={name} titleAccess={title} />);
21
+ render(<Icon name={name} label={title} size="medium" />);
22
22
 
23
23
  const svgElement = screen.getByRole("img");
24
24
  expect(svgElement).toBeVisible();
package/src/Icon.tsx CHANGED
@@ -11,15 +11,26 @@
11
11
  */
12
12
 
13
13
  import { forwardRef } from "react";
14
- import type { SvgIconNoChildrenProps } from "./iconDictionary/types";
15
14
  import { iconDictionary } from "./iconDictionary";
16
15
 
17
- export interface IconProps extends SvgIconNoChildrenProps {
18
- /**
19
- * Name of the icon to render
16
+ export type IconProps = {
17
+ /*
18
+ ** The element whose text describes the icon, if it exists
19
+ */
20
+ ariaLabelledby?: string;
21
+ /*
22
+ ** Text that describes the icon
23
+ */
24
+ label: string;
25
+ /*
26
+ ** Name of the icon to render
20
27
  */
21
28
  name: keyof typeof iconDictionary;
22
- }
29
+ /*
30
+ ** The size of the icon
31
+ */
32
+ size: "small" | "medium" | "large";
33
+ };
23
34
 
24
35
  /**
25
36
  * A system of icons which establishes a visual language
@@ -28,12 +39,18 @@ export interface IconProps extends SvgIconNoChildrenProps {
28
39
  * icon component imports where possible to keep your bundle size smaller.
29
40
  */
30
41
  export const Icon = forwardRef<SVGSVGElement, IconProps>(
31
- ({ name, titleAccess, ...rest }, ref) => {
42
+ ({ ariaLabelledby, label, name, size }) => {
32
43
  if (!(name in iconDictionary)) return null;
33
44
 
34
45
  const NamedIcon = iconDictionary[name];
35
46
 
36
- return <NamedIcon titleAccess={titleAccess} ref={ref} {...rest} />;
47
+ return (
48
+ <NamedIcon
49
+ aria-labelledby={ariaLabelledby}
50
+ fontSize={size}
51
+ titleAccess={label}
52
+ />
53
+ );
37
54
  }
38
55
  );
39
56
 
package/src/Infobox.tsx CHANGED
@@ -14,28 +14,28 @@ import { AlertColor } from "@mui/material";
14
14
  import { memo, ReactNode } from "react";
15
15
  import { Alert, AlertTitle, ScreenReaderText } from ".";
16
16
 
17
- export interface InfoboxProps {
17
+ export type InfoboxProps = {
18
18
  /**
19
19
  * The contents of the alert
20
20
  */
21
21
  children: ReactNode;
22
- /**
23
- * Determine the color and icon of the alert
24
- */
25
- severity: AlertColor;
26
22
  /**
27
23
  * Sets the ARIA role of the alert
28
24
  * ("status" for something that dynamically updates, "alert" for errors, null for something
29
25
  * unchanging)
30
26
  */
31
27
  role?: "status" | "alert";
28
+ /**
29
+ * Determine the color and icon of the alert
30
+ */
31
+ severity: AlertColor;
32
32
  /**
33
33
  * The title of the alert
34
34
  */
35
35
  title?: string;
36
- }
36
+ };
37
37
 
38
- const Infobox = ({ children, severity, role, title }: InfoboxProps) => (
38
+ const Infobox = ({ children, role, severity, title }: InfoboxProps) => (
39
39
  <Alert role={role} severity={severity} variant="infobox">
40
40
  <ScreenReaderText>{severity}: </ScreenReaderText>
41
41
  {title && <AlertTitle>{title}</AlertTitle>}