@okta/odyssey-react-mui 1.0.2 → 1.1.1

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 (204) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +1 -1
  3. package/dist/Autocomplete.js +9 -3
  4. package/dist/Autocomplete.js.map +1 -1
  5. package/dist/Banner.js +3 -1
  6. package/dist/Banner.js.map +1 -1
  7. package/dist/Box.js +8 -4
  8. package/dist/Box.js.map +1 -1
  9. package/dist/Button.js +3 -1
  10. package/dist/Button.js.map +1 -1
  11. package/dist/Callout.js +2 -0
  12. package/dist/Callout.js.map +1 -1
  13. package/dist/Checkbox.js +6 -2
  14. package/dist/Checkbox.js.map +1 -1
  15. package/dist/CheckboxGroup.js +5 -7
  16. package/dist/CheckboxGroup.js.map +1 -1
  17. package/dist/CircularProgress.js +2 -0
  18. package/dist/CircularProgress.js.map +1 -1
  19. package/dist/Dialog.js +2 -0
  20. package/dist/Dialog.js.map +1 -1
  21. package/dist/Field.js.map +1 -1
  22. package/dist/FieldError.js +2 -0
  23. package/dist/FieldError.js.map +1 -1
  24. package/dist/FieldHint.js +2 -0
  25. package/dist/FieldHint.js.map +1 -1
  26. package/dist/FieldLabel.js +3 -1
  27. package/dist/FieldLabel.js.map +1 -1
  28. package/dist/Fieldset.js +3 -1
  29. package/dist/Fieldset.js.map +1 -1
  30. package/dist/Form.js +5 -3
  31. package/dist/Form.js.map +1 -1
  32. package/dist/Link.js +3 -1
  33. package/dist/Link.js.map +1 -1
  34. package/dist/MenuButton.js +8 -2
  35. package/dist/MenuButton.js.map +1 -1
  36. package/dist/MenuItem.js +6 -2
  37. package/dist/MenuItem.js.map +1 -1
  38. package/dist/NativeSelect.js +3 -1
  39. package/dist/NativeSelect.js.map +1 -1
  40. package/dist/OdysseyI18n.js +2 -0
  41. package/dist/OdysseyI18n.js.map +1 -1
  42. package/dist/OdysseyProvider.js +7 -4
  43. package/dist/OdysseyProvider.js.map +1 -1
  44. package/dist/OdysseyThemeProvider.js +3 -6
  45. package/dist/OdysseyThemeProvider.js.map +1 -1
  46. package/dist/OdysseyTranslationProvider.types.js +1 -1
  47. package/dist/OdysseyTranslationProvider.types.js.map +1 -1
  48. package/dist/PasswordField.js +9 -8
  49. package/dist/PasswordField.js.map +1 -1
  50. package/dist/Radio.js +2 -0
  51. package/dist/Radio.js.map +1 -1
  52. package/dist/RadioGroup.js +5 -2
  53. package/dist/RadioGroup.js.map +1 -1
  54. package/dist/SearchField.js +11 -10
  55. package/dist/SearchField.js.map +1 -1
  56. package/dist/Select.js +8 -5
  57. package/dist/Select.js.map +1 -1
  58. package/dist/SeleniumProps.js +2 -0
  59. package/dist/SeleniumProps.js.map +1 -0
  60. package/dist/Status.js +4 -2
  61. package/dist/Status.js.map +1 -1
  62. package/dist/Tabs.js +11 -4
  63. package/dist/Tabs.js.map +1 -1
  64. package/dist/Tag.js +4 -2
  65. package/dist/Tag.js.map +1 -1
  66. package/dist/TagList.js +3 -1
  67. package/dist/TagList.js.map +1 -1
  68. package/dist/TextField.js +6 -2
  69. package/dist/TextField.js.map +1 -1
  70. package/dist/Toast.js +2 -0
  71. package/dist/Toast.js.map +1 -1
  72. package/dist/Tooltip.js +2 -0
  73. package/dist/Tooltip.js.map +1 -1
  74. package/dist/Typography.js +71 -37
  75. package/dist/Typography.js.map +1 -1
  76. package/dist/labs/DatePicker.js +4 -2
  77. package/dist/labs/DatePicker.js.map +1 -1
  78. package/dist/labs/PaginatedTable.js +6 -4
  79. package/dist/labs/PaginatedTable.js.map +1 -1
  80. package/dist/labs/StaticTable.js +9 -4
  81. package/dist/labs/StaticTable.js.map +1 -1
  82. package/dist/src/Autocomplete.d.ts +7 -2
  83. package/dist/src/Autocomplete.d.ts.map +1 -1
  84. package/dist/src/Banner.d.ts +3 -2
  85. package/dist/src/Banner.d.ts.map +1 -1
  86. package/dist/src/Box.d.ts +9 -2
  87. package/dist/src/Box.d.ts.map +1 -1
  88. package/dist/src/Button.d.ts +3 -2
  89. package/dist/src/Button.d.ts.map +1 -1
  90. package/dist/src/Callout.d.ts +3 -2
  91. package/dist/src/Callout.d.ts.map +1 -1
  92. package/dist/src/Checkbox.d.ts +8 -3
  93. package/dist/src/Checkbox.d.ts.map +1 -1
  94. package/dist/src/CheckboxGroup.d.ts +3 -6
  95. package/dist/src/CheckboxGroup.d.ts.map +1 -1
  96. package/dist/src/CircularProgress.d.ts +3 -2
  97. package/dist/src/CircularProgress.d.ts.map +1 -1
  98. package/dist/src/Dialog.d.ts +3 -2
  99. package/dist/src/Dialog.d.ts.map +1 -1
  100. package/dist/src/Field.d.ts +2 -1
  101. package/dist/src/Field.d.ts.map +1 -1
  102. package/dist/src/FieldError.d.ts +3 -2
  103. package/dist/src/FieldError.d.ts.map +1 -1
  104. package/dist/src/FieldHint.d.ts +3 -2
  105. package/dist/src/FieldHint.d.ts.map +1 -1
  106. package/dist/src/FieldLabel.d.ts +3 -2
  107. package/dist/src/FieldLabel.d.ts.map +1 -1
  108. package/dist/src/Fieldset.d.ts +3 -2
  109. package/dist/src/Fieldset.d.ts.map +1 -1
  110. package/dist/src/Form.d.ts +3 -2
  111. package/dist/src/Form.d.ts.map +1 -1
  112. package/dist/src/Link.d.ts +3 -2
  113. package/dist/src/Link.d.ts.map +1 -1
  114. package/dist/src/MenuButton.d.ts +12 -3
  115. package/dist/src/MenuButton.d.ts.map +1 -1
  116. package/dist/src/MenuItem.d.ts +5 -4
  117. package/dist/src/MenuItem.d.ts.map +1 -1
  118. package/dist/src/NativeSelect.d.ts +56 -2
  119. package/dist/src/NativeSelect.d.ts.map +1 -1
  120. package/dist/src/OdysseyI18n.d.ts +15 -0
  121. package/dist/src/OdysseyI18n.d.ts.map +1 -1
  122. package/dist/src/OdysseyProvider.d.ts.map +1 -1
  123. package/dist/src/OdysseyThemeProvider.d.ts.map +1 -1
  124. package/dist/src/OdysseyTranslationProvider.types.d.ts +1 -1
  125. package/dist/src/OdysseyTranslationProvider.types.d.ts.map +1 -1
  126. package/dist/src/PasswordField.d.ts +70 -2
  127. package/dist/src/PasswordField.d.ts.map +1 -1
  128. package/dist/src/Radio.d.ts +3 -2
  129. package/dist/src/Radio.d.ts.map +1 -1
  130. package/dist/src/RadioGroup.d.ts +8 -3
  131. package/dist/src/RadioGroup.d.ts.map +1 -1
  132. package/dist/src/SearchField.d.ts +58 -2
  133. package/dist/src/SearchField.d.ts.map +1 -1
  134. package/dist/src/Select.d.ts +60 -2
  135. package/dist/src/Select.d.ts.map +1 -1
  136. package/dist/src/SeleniumProps.d.ts +20 -0
  137. package/dist/src/SeleniumProps.d.ts.map +1 -0
  138. package/dist/src/Status.d.ts +3 -2
  139. package/dist/src/Status.d.ts.map +1 -1
  140. package/dist/src/Tabs.d.ts +9 -3
  141. package/dist/src/Tabs.d.ts.map +1 -1
  142. package/dist/src/Tag.d.ts +3 -2
  143. package/dist/src/Tag.d.ts.map +1 -1
  144. package/dist/src/TagList.d.ts +3 -2
  145. package/dist/src/TagList.d.ts.map +1 -1
  146. package/dist/src/TextField.d.ts +86 -2
  147. package/dist/src/TextField.d.ts.map +1 -1
  148. package/dist/src/Toast.d.ts +3 -2
  149. package/dist/src/Toast.d.ts.map +1 -1
  150. package/dist/src/Tooltip.d.ts +3 -2
  151. package/dist/src/Tooltip.d.ts.map +1 -1
  152. package/dist/src/Typography.d.ts +14 -45
  153. package/dist/src/Typography.d.ts.map +1 -1
  154. package/dist/src/labs/DatePicker.d.ts +5 -1
  155. package/dist/src/labs/DatePicker.d.ts.map +1 -1
  156. package/dist/src/labs/PaginatedTable.d.ts.map +1 -1
  157. package/dist/src/labs/StaticTable.d.ts.map +1 -1
  158. package/dist/src/theme/components.d.ts.map +1 -1
  159. package/dist/theme/components.js +38 -10
  160. package/dist/theme/components.js.map +1 -1
  161. package/dist/tsconfig.production.tsbuildinfo +1 -1
  162. package/package.json +6 -5
  163. package/src/Autocomplete.tsx +13 -2
  164. package/src/Banner.tsx +11 -2
  165. package/src/Box.tsx +11 -5
  166. package/src/Button.tsx +6 -1
  167. package/src/Callout.tsx +5 -3
  168. package/src/Checkbox.tsx +14 -4
  169. package/src/CheckboxGroup.tsx +6 -10
  170. package/src/CircularProgress.tsx +5 -1
  171. package/src/Dialog.tsx +5 -2
  172. package/src/Field.tsx +2 -0
  173. package/src/FieldError.tsx +5 -3
  174. package/src/FieldHint.tsx +9 -3
  175. package/src/FieldLabel.tsx +5 -3
  176. package/src/Fieldset.tsx +4 -1
  177. package/src/Form.tsx +7 -4
  178. package/src/Link.tsx +18 -3
  179. package/src/MenuButton.tsx +33 -4
  180. package/src/MenuItem.tsx +11 -6
  181. package/src/NativeSelect.tsx +7 -2
  182. package/src/OdysseyI18n.ts +2 -0
  183. package/src/OdysseyProvider.tsx +9 -6
  184. package/src/OdysseyThemeProvider.tsx +4 -6
  185. package/src/OdysseyTranslationProvider.types.ts +1 -0
  186. package/src/PasswordField.tsx +18 -10
  187. package/src/Radio.tsx +5 -1
  188. package/src/RadioGroup.tsx +12 -4
  189. package/src/SearchField.tsx +23 -15
  190. package/src/Select.tsx +16 -6
  191. package/src/SeleniumProps.ts +20 -0
  192. package/src/Status.tsx +15 -3
  193. package/src/Tabs.tsx +18 -4
  194. package/src/Tag.tsx +12 -3
  195. package/src/TagList.tsx +4 -2
  196. package/src/TextField.tsx +14 -2
  197. package/src/Toast.tsx +4 -1
  198. package/src/Tooltip.tsx +4 -1
  199. package/src/Typography.tsx +76 -28
  200. package/src/labs/DatePicker.tsx +15 -7
  201. package/src/labs/PaginatedTable.tsx +12 -3
  202. package/src/labs/README.md +2 -2
  203. package/src/labs/StaticTable.tsx +13 -3
  204. package/src/theme/components.tsx +43 -9
@@ -10,13 +10,20 @@
10
10
  * See the License for the specific language governing permissions and limitations under the License.
11
11
  */
12
12
 
13
- import { Button, buttonVariantValues, MenuItem, useUniqueId } from "./";
13
+ import {
14
+ Button,
15
+ buttonSizeValues,
16
+ buttonVariantValues,
17
+ MenuItem,
18
+ useUniqueId,
19
+ } from "./";
14
20
  import { Divider, ListSubheader, Menu } from "@mui/material";
15
- import { ChevronDownIcon } from "./icons.generated";
21
+ import { ChevronDownIcon, MoreIcon } from "./icons.generated";
16
22
  import { memo, type ReactElement, useCallback, useMemo, useState } from "react";
17
23
 
18
24
  import { MenuContext, MenuContextType } from "./MenuContext";
19
25
  import { NullElement } from "./NullElement";
26
+ import type { SeleniumProps } from "./SeleniumProps";
20
27
 
21
28
  export type MenuButtonProps = {
22
29
  /**
@@ -55,6 +62,14 @@ export type MenuButtonProps = {
55
62
  * The id of the Button
56
63
  */
57
64
  id?: string;
65
+ /**
66
+ * If the MenuButton is an overflow menu or standard menu.
67
+ */
68
+ isOverflow?: boolean;
69
+ /**
70
+ * The size of the button
71
+ */
72
+ size?: (typeof buttonSizeValues)[number];
58
73
  /**
59
74
  * The tooltip text for the Button if it's icon-only
60
75
  */
@@ -75,7 +90,8 @@ export type MenuButtonProps = {
75
90
  ariaLabelledBy: string;
76
91
  buttonLabel?: undefined | "";
77
92
  }
78
- );
93
+ ) &
94
+ SeleniumProps;
79
95
 
80
96
  const MenuButton = ({
81
97
  ariaLabel,
@@ -84,8 +100,11 @@ const MenuButton = ({
84
100
  buttonLabel = "",
85
101
  buttonVariant = "secondary",
86
102
  children,
87
- endIcon = <ChevronDownIcon />,
103
+ endIcon: endIconProp,
88
104
  id: idOverride,
105
+ isOverflow,
106
+ size,
107
+ testId,
89
108
  tooltipText,
90
109
  }: MenuButtonProps) => {
91
110
  const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
@@ -115,6 +134,14 @@ const MenuButton = ({
115
134
  [closeMenu, openMenu]
116
135
  );
117
136
 
137
+ const endIcon = endIconProp ? (
138
+ endIconProp
139
+ ) : isOverflow ? (
140
+ <MoreIcon />
141
+ ) : (
142
+ <ChevronDownIcon />
143
+ );
144
+
118
145
  return (
119
146
  <div>
120
147
  <Button
@@ -124,10 +151,12 @@ const MenuButton = ({
124
151
  ariaDescribedBy={ariaDescribedBy}
125
152
  ariaLabel={ariaLabel}
126
153
  ariaLabelledBy={ariaLabelledBy}
154
+ data-se={testId}
127
155
  endIcon={endIcon}
128
156
  id={`${uniqueId}-button`}
129
157
  label={buttonLabel}
130
158
  onClick={openMenu}
159
+ size={size}
131
160
  tooltipText={tooltipText}
132
161
  variant={buttonVariant}
133
162
  />
package/src/MenuItem.tsx CHANGED
@@ -18,6 +18,7 @@ import { menuItemClasses } from "@mui/material/MenuItem";
18
18
  import { memo, useCallback, useContext, type ReactNode } from "react";
19
19
 
20
20
  import { MenuContext } from "./MenuContext";
21
+ import type { SeleniumProps } from "./SeleniumProps";
21
22
 
22
23
  export type MenuItemProps = {
23
24
  /**
@@ -33,9 +34,9 @@ export type MenuItemProps = {
33
34
  */
34
35
  isSelected?: boolean;
35
36
  /**
36
- * If `true`, the menu item will be visually marked as destructive.
37
+ * If `true`, the menu item will be visually marked as disabled.
37
38
  */
38
- isDestructive?: boolean;
39
+ isDisabled?: boolean;
39
40
  /**
40
41
  * Callback fired when the menu item is clicked.
41
42
  */
@@ -50,13 +51,15 @@ export type MenuItemProps = {
50
51
  * - "destructive": A variant indicating a destructive action.
51
52
  */
52
53
  variant?: "default" | "destructive";
53
- };
54
+ } & SeleniumProps;
54
55
 
55
56
  const MenuItem = ({
56
57
  children,
57
58
  hasInitialFocus,
58
59
  isSelected,
60
+ isDisabled,
59
61
  onClick: onClickProp,
62
+ testId,
60
63
  value,
61
64
  variant = "default",
62
65
  }: MenuItemProps) => {
@@ -74,14 +77,16 @@ const MenuItem = ({
74
77
  <MuiMenuItem
75
78
  /* eslint-disable-next-line jsx-a11y/no-autofocus */
76
79
  autoFocus={hasInitialFocus}
77
- selected={isSelected}
78
- value={value}
79
- onClick={onClick}
80
80
  className={
81
81
  variant === "destructive"
82
82
  ? `${menuItemClasses.root}-destructive`
83
83
  : undefined
84
84
  }
85
+ data-se={testId}
86
+ disabled={isDisabled}
87
+ onClick={onClick}
88
+ selected={isSelected}
89
+ value={value}
85
90
  >
86
91
  {children}
87
92
  </MuiMenuItem>
@@ -15,6 +15,8 @@ import { Select as MuiSelect } from "@mui/material";
15
15
  import { SelectProps as MuiSelectProps } from "@mui/material";
16
16
  import { Field } from "./Field";
17
17
 
18
+ import type { SeleniumProps } from "./SeleniumProps";
19
+
18
20
  export type NativeSelectOption = {
19
21
  text: string;
20
22
  value?: string;
@@ -74,7 +76,7 @@ export type NativeSelectProps = {
74
76
  * The value or values selected in the NativeSelect
75
77
  */
76
78
  value?: string | string[];
77
- };
79
+ } & SeleniumProps;
78
80
 
79
81
  const NativeSelect = forwardRef<HTMLSelectElement, NativeSelectProps>(
80
82
  (
@@ -90,6 +92,7 @@ const NativeSelect = forwardRef<HTMLSelectElement, NativeSelectProps>(
90
92
  onBlur,
91
93
  onChange,
92
94
  onFocus,
95
+ testId,
93
96
  value,
94
97
  children,
95
98
  },
@@ -98,6 +101,7 @@ const NativeSelect = forwardRef<HTMLSelectElement, NativeSelectProps>(
98
101
  const renderFieldComponent = useCallback(
99
102
  () => (
100
103
  <MuiSelect
104
+ data-se={testId}
101
105
  defaultValue={defaultValue}
102
106
  id={idOverride}
103
107
  name={idOverride}
@@ -112,6 +116,7 @@ const NativeSelect = forwardRef<HTMLSelectElement, NativeSelectProps>(
112
116
  />
113
117
  ),
114
118
  [
119
+ children,
115
120
  defaultValue,
116
121
  idOverride,
117
122
  isMultiSelect,
@@ -119,7 +124,7 @@ const NativeSelect = forwardRef<HTMLSelectElement, NativeSelectProps>(
119
124
  onChange,
120
125
  onFocus,
121
126
  ref,
122
- children,
127
+ testId,
123
128
  value,
124
129
  ]
125
130
  );
@@ -39,6 +39,7 @@ import { translation as sv } from "./properties/ts/odyssey-react-mui_sv";
39
39
  import { translation as th } from "./properties/ts/odyssey-react-mui_th";
40
40
  import { translation as tr } from "./properties/ts/odyssey-react-mui_tr";
41
41
  import { translation as uk } from "./properties/ts/odyssey-react-mui_uk";
42
+ import { translation as vi } from "./properties/ts/odyssey-react-mui_vi";
42
43
  import { translation as zhCN } from "./properties/ts/odyssey-react-mui_zh_CN";
43
44
  import { translation as znTW } from "./properties/ts/odyssey-react-mui_zh_TW";
44
45
 
@@ -76,6 +77,7 @@ export const resources = {
76
77
  th,
77
78
  tr,
78
79
  uk,
80
+ vi,
79
81
  zh_CN: zhCN,
80
82
  zh_TW: znTW,
81
83
  };
@@ -11,6 +11,7 @@
11
11
  */
12
12
 
13
13
  import { memo, ReactNode } from "react";
14
+ import { ScopedCssBaseline } from "@mui/material";
14
15
 
15
16
  import {
16
17
  OdysseyCacheProvider,
@@ -45,12 +46,14 @@ const OdysseyProvider = ({
45
46
  themeOverride={themeOverride}
46
47
  designTokensOverride={designTokensOverride}
47
48
  >
48
- <OdysseyTranslationProvider
49
- languageCode={languageCode}
50
- translationOverrides={translationOverrides}
51
- >
52
- {children}
53
- </OdysseyTranslationProvider>
49
+ <ScopedCssBaseline>
50
+ <OdysseyTranslationProvider
51
+ languageCode={languageCode}
52
+ translationOverrides={translationOverrides}
53
+ >
54
+ {children}
55
+ </OdysseyTranslationProvider>
56
+ </ScopedCssBaseline>
54
57
  </OdysseyThemeProvider>
55
58
  </OdysseyCacheProvider>
56
59
  );
@@ -16,7 +16,7 @@ import {
16
16
  } from "@mui/material/styles";
17
17
  import { memo, ReactNode, useMemo } from "react";
18
18
 
19
- import { ScopedCssBaseline, ThemeOptions } from "@mui/material";
19
+ import { ThemeOptions } from "@mui/material";
20
20
  import { deepmerge } from "@mui/utils";
21
21
  import { createOdysseyMuiTheme, DesignTokensOverride } from "./theme";
22
22
  import * as Tokens from "@okta/odyssey-design-tokens";
@@ -49,11 +49,9 @@ const OdysseyThemeProvider = ({
49
49
 
50
50
  return (
51
51
  <MuiThemeProvider theme={customOdysseyTheme ?? odysseyTheme}>
52
- <ScopedCssBaseline>
53
- <OdysseyDesignTokensContext.Provider value={odysseyTokens}>
54
- {children}
55
- </OdysseyDesignTokensContext.Provider>
56
- </ScopedCssBaseline>
52
+ <OdysseyDesignTokensContext.Provider value={odysseyTokens}>
53
+ {children}
54
+ </OdysseyDesignTokensContext.Provider>
57
55
  </MuiThemeProvider>
58
56
  );
59
57
  };
@@ -37,6 +37,7 @@ export const supportedLanguages = [
37
37
  "th", // Thai
38
38
  "tr", // Turkish
39
39
  "uk", // Ukrainian
40
+ "vi", // Vietnamese
40
41
  "zh_CN", // Chinese (PRC)
41
42
  "zh_TW", // Chinese
42
43
  ] as const;
@@ -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 { InputAdornment, InputBase } from "@mui/material";
13
+ import { InputAdornment, InputBase, IconButton } from "@mui/material";
14
14
  import {
15
15
  ChangeEventHandler,
16
16
  FocusEventHandler,
@@ -21,8 +21,8 @@ import {
21
21
  } from "react";
22
22
 
23
23
  import { ShowIcon, HideIcon } from "./icons.generated";
24
- import { Button } from "./Button";
25
24
  import { Field } from "./Field";
25
+ import type { SeleniumProps } from "./SeleniumProps";
26
26
 
27
27
  export type PasswordFieldProps = {
28
28
  /**
@@ -63,6 +63,10 @@ export type PasswordFieldProps = {
63
63
  * The label for the `input` element.
64
64
  */
65
65
  label: string;
66
+ /**
67
+ * The name of the `input` element. Defaults to the `id` if not set.
68
+ */
69
+ name?: string;
66
70
  /**
67
71
  * Callback fired when the `input` element loses focus.
68
72
  */
@@ -83,7 +87,7 @@ export type PasswordFieldProps = {
83
87
  * The value of the `input` element, required for a controlled component.
84
88
  */
85
89
  value?: string;
86
- };
90
+ } & SeleniumProps;
87
91
 
88
92
  const PasswordField = forwardRef<HTMLInputElement, PasswordFieldProps>(
89
93
  (
@@ -97,10 +101,12 @@ const PasswordField = forwardRef<HTMLInputElement, PasswordFieldProps>(
97
101
  isOptional = false,
98
102
  isReadOnly,
99
103
  label,
104
+ name: nameOverride,
100
105
  onChange,
101
106
  onFocus,
102
107
  onBlur,
103
108
  placeholder,
109
+ testId,
104
110
  value,
105
111
  },
106
112
  ref
@@ -120,19 +126,19 @@ const PasswordField = forwardRef<HTMLInputElement, PasswordFieldProps>(
120
126
  autoComplete={autoCompleteType}
121
127
  /* eslint-disable-next-line jsx-a11y/no-autofocus */
122
128
  autoFocus={hasInitialFocus}
129
+ data-se={testId}
123
130
  endAdornment={
124
131
  <InputAdornment position="end">
125
- <Button
126
- ariaLabel="toggle password visibility"
127
- endIcon={inputType === "password" ? <ShowIcon /> : <HideIcon />}
132
+ <IconButton
133
+ aria-label="toggle password visibility"
128
134
  onClick={togglePasswordVisibility}
129
- size="small"
130
- variant="floating"
131
- />
135
+ >
136
+ {inputType === "password" ? <ShowIcon /> : <HideIcon />}
137
+ </IconButton>
132
138
  </InputAdornment>
133
139
  }
134
140
  id={id}
135
- name={id}
141
+ name={nameOverride ?? id}
136
142
  onChange={onChange}
137
143
  onFocus={onFocus}
138
144
  onBlur={onBlur}
@@ -149,6 +155,7 @@ const PasswordField = forwardRef<HTMLInputElement, PasswordFieldProps>(
149
155
  hasInitialFocus,
150
156
  togglePasswordVisibility,
151
157
  inputType,
158
+ nameOverride,
152
159
  onChange,
153
160
  onFocus,
154
161
  onBlur,
@@ -156,6 +163,7 @@ const PasswordField = forwardRef<HTMLInputElement, PasswordFieldProps>(
156
163
  isOptional,
157
164
  isReadOnly,
158
165
  ref,
166
+ testId,
159
167
  value,
160
168
  ]
161
169
  );
package/src/Radio.tsx CHANGED
@@ -15,6 +15,8 @@ import { memo } from "react";
15
15
 
16
16
  import { FormControlLabel } from "@mui/material";
17
17
 
18
+ import type { SeleniumProps } from "./SeleniumProps";
19
+
18
20
  export type RadioProps = {
19
21
  /**
20
22
  * If `true`, the Radio is selected
@@ -40,7 +42,7 @@ export type RadioProps = {
40
42
  * The value attribute of the Radio
41
43
  */
42
44
  value: string;
43
- };
45
+ } & SeleniumProps;
44
46
 
45
47
  const Radio = ({
46
48
  isChecked,
@@ -48,12 +50,14 @@ const Radio = ({
48
50
  isInvalid,
49
51
  label,
50
52
  name,
53
+ testId,
51
54
  value,
52
55
  }: RadioProps) => (
53
56
  <FormControlLabel
54
57
  checked={isChecked}
55
58
  className={isInvalid ? "Mui-error" : ""}
56
59
  control={<MuiRadio />}
60
+ data-se={testId}
57
61
  disabled={isDisabled}
58
62
  label={label}
59
63
  name={name}
@@ -15,6 +15,7 @@ import { ChangeEventHandler, memo, ReactElement, useCallback } from "react";
15
15
 
16
16
  import { Radio, RadioProps } from "./Radio";
17
17
  import { Field } from "./Field";
18
+ import type { SeleniumProps } from "./SeleniumProps";
18
19
 
19
20
  export type RadioGroupProps = {
20
21
  /**
@@ -34,7 +35,7 @@ export type RadioGroupProps = {
34
35
  */
35
36
  hint?: string;
36
37
  /**
37
- * The id of the `input` element. This will also be the input's `name` field.
38
+ * The id of the `input` element.
38
39
  */
39
40
  id?: string;
40
41
  /**
@@ -45,6 +46,10 @@ export type RadioGroupProps = {
45
46
  * The text label for the RadioGroup
46
47
  */
47
48
  label: string;
49
+ /**
50
+ * The name of the `input` element. Defaults to the `id` if not set.
51
+ */
52
+ name?: string;
48
53
  /**
49
54
  * Listen for changes in the browser that change `value`
50
55
  */
@@ -53,7 +58,7 @@ export type RadioGroupProps = {
53
58
  * The `value` on the selected Radio
54
59
  */
55
60
  value?: RadioProps["value"];
56
- };
61
+ } & SeleniumProps;
57
62
 
58
63
  const RadioGroup = ({
59
64
  children,
@@ -63,23 +68,26 @@ const RadioGroup = ({
63
68
  id: idOverride,
64
69
  isDisabled,
65
70
  label,
71
+ name: nameOverride,
66
72
  onChange,
73
+ testId,
67
74
  value,
68
75
  }: RadioGroupProps) => {
69
76
  const renderFieldComponent = useCallback(
70
77
  ({ ariaDescribedBy, id }) => (
71
78
  <MuiRadioGroup
72
79
  aria-describedby={ariaDescribedBy}
80
+ data-se={testId}
73
81
  defaultValue={defaultValue}
74
82
  id={id}
75
- name={id}
83
+ name={nameOverride ?? id}
76
84
  onChange={onChange}
77
85
  value={value}
78
86
  >
79
87
  {children}
80
88
  </MuiRadioGroup>
81
89
  ),
82
- [children, defaultValue, onChange, value]
90
+ [children, defaultValue, nameOverride, onChange, testId, value]
83
91
  );
84
92
 
85
93
  return (
@@ -11,7 +11,7 @@
11
11
  */
12
12
 
13
13
  import { useState, useEffect } from "react";
14
- import { InputAdornment, InputBase } from "@mui/material";
14
+ import { InputAdornment, InputBase, IconButton } from "@mui/material";
15
15
  import {
16
16
  ChangeEventHandler,
17
17
  FocusEventHandler,
@@ -23,7 +23,7 @@ import {
23
23
 
24
24
  import { CloseCircleFilledIcon, SearchIcon } from "./icons.generated";
25
25
  import { Field } from "./Field";
26
- import { Button } from "./Button";
26
+ import type { SeleniumProps } from "./SeleniumProps";
27
27
 
28
28
  export type SearchFieldProps = {
29
29
  /**
@@ -48,6 +48,10 @@ export type SearchFieldProps = {
48
48
  * This label won't show up visually, but it's required for accessibility.
49
49
  */
50
50
  label: string;
51
+ /**
52
+ * The name of the `input` element. Defaults to the `id` if not set.
53
+ */
54
+ name?: string;
51
55
  /**
52
56
  * Callback fired when the `input` element loses focus.
53
57
  */
@@ -72,7 +76,7 @@ export type SearchFieldProps = {
72
76
  * The value of the `input` element, required for a controlled component.
73
77
  */
74
78
  value?: string;
75
- };
79
+ } & SeleniumProps;
76
80
 
77
81
  const SearchField = forwardRef<HTMLInputElement, SearchFieldProps>(
78
82
  (
@@ -82,11 +86,13 @@ const SearchField = forwardRef<HTMLInputElement, SearchFieldProps>(
82
86
  id: idOverride,
83
87
  isDisabled = false,
84
88
  label,
89
+ name: nameOverride,
85
90
  onChange: onChangeProp,
86
91
  onFocus,
87
92
  onBlur,
88
93
  onClear: onClearProp,
89
94
  placeholder,
95
+ testId,
90
96
  value: controlledValue,
91
97
  },
92
98
  ref
@@ -120,26 +126,26 @@ const SearchField = forwardRef<HTMLInputElement, SearchFieldProps>(
120
126
  autoComplete={autoCompleteType}
121
127
  /* eslint-disable-next-line jsx-a11y/no-autofocus */
122
128
  autoFocus={hasInitialFocus}
129
+ data-se={testId}
123
130
  endAdornment={
124
131
  uncontrolledValue && (
125
132
  <InputAdornment position="end">
126
- <Button
127
- ariaLabel="Clear"
128
- isDisabled={isDisabled}
129
- label=""
133
+ <IconButton
134
+ aria-label="Clear"
135
+ disabled={isDisabled}
130
136
  onClick={onClear}
131
137
  size="small"
132
- startIcon={<CloseCircleFilledIcon />}
133
- variant="floating"
134
- />
138
+ >
139
+ <CloseCircleFilledIcon />
140
+ </IconButton>
135
141
  </InputAdornment>
136
142
  )
137
143
  }
138
144
  id={id}
139
- name={id}
145
+ name={nameOverride ?? id}
146
+ onBlur={onBlur}
140
147
  onChange={onChange}
141
148
  onFocus={onFocus}
142
- onBlur={onBlur}
143
149
  placeholder={placeholder}
144
150
  ref={ref}
145
151
  startAdornment={
@@ -155,15 +161,17 @@ const SearchField = forwardRef<HTMLInputElement, SearchFieldProps>(
155
161
  ),
156
162
  [
157
163
  autoCompleteType,
164
+ controlledValue,
158
165
  hasInitialFocus,
159
166
  isDisabled,
160
- onClear,
167
+ nameOverride,
168
+ onBlur,
161
169
  onChange,
170
+ onClear,
162
171
  onFocus,
163
- onBlur,
164
172
  placeholder,
165
173
  ref,
166
- controlledValue,
174
+ testId,
167
175
  uncontrolledValue,
168
176
  ]
169
177
  );
package/src/Select.tsx CHANGED
@@ -14,14 +14,15 @@ import { ReactNode, forwardRef, memo, useCallback, useState } from "react";
14
14
  import {
15
15
  Box,
16
16
  Chip,
17
+ Checkbox as MuiCheckbox,
17
18
  ListSubheader,
18
19
  MenuItem,
19
20
  Select as MuiSelect,
20
21
  SelectChangeEvent,
21
22
  } from "@mui/material";
22
23
  import { SelectProps as MuiSelectProps } from "@mui/material";
23
- import { Checkbox } from "./Checkbox";
24
24
  import { Field } from "./Field";
25
+ import type { SeleniumProps } from "./SeleniumProps";
25
26
 
26
27
  export type SelectOption = {
27
28
  text: string;
@@ -58,6 +59,10 @@ export type SelectProps = {
58
59
  * The label text for the Select
59
60
  */
60
61
  label: string;
62
+ /**
63
+ * The name of the `input` element. Defaults to the `id` if not set.
64
+ */
65
+ name?: string;
61
66
  /**
62
67
  * Callback fired when the Select loses focus
63
68
  */
@@ -78,7 +83,7 @@ export type SelectProps = {
78
83
  * The value or values selected in the Select
79
84
  */
80
85
  value?: string | string[];
81
- };
86
+ } & SeleniumProps;
82
87
 
83
88
  /**
84
89
  * Options in Odyssey <Select> are passed as an array, which can contain any combination
@@ -105,10 +110,12 @@ const Select = forwardRef<HTMLSelectElement, SelectProps>(
105
110
  isMultiSelect = false,
106
111
  isOptional = false,
107
112
  label,
113
+ name: nameOverride,
108
114
  onBlur,
109
115
  onChange: onChangeProp,
110
116
  onFocus,
111
117
  value,
118
+ testId,
112
119
  options,
113
120
  },
114
121
  ref
@@ -205,7 +212,7 @@ const Select = forwardRef<HTMLSelectElement, SelectProps>(
205
212
  return (
206
213
  <MenuItem key={option.value} value={option.value}>
207
214
  {isMultiSelect && (
208
- <Checkbox isDefaultChecked={selectedValue.includes(option.value)} />
215
+ <MuiCheckbox checked={selectedValue.includes(option.value)} />
209
216
  )}
210
217
  {option.text}
211
218
  </MenuItem>
@@ -216,9 +223,10 @@ const Select = forwardRef<HTMLSelectElement, SelectProps>(
216
223
  () => (
217
224
  <MuiSelect
218
225
  children={children}
226
+ data-se={testId}
219
227
  id={idOverride}
220
228
  multiple={isMultiSelect}
221
- name={idOverride}
229
+ name={nameOverride ?? idOverride}
222
230
  onBlur={onBlur}
223
231
  onChange={onChange}
224
232
  onFocus={onFocus}
@@ -229,16 +237,18 @@ const Select = forwardRef<HTMLSelectElement, SelectProps>(
229
237
  />
230
238
  ),
231
239
  [
240
+ children,
232
241
  idOverride,
233
242
  isMultiSelect,
243
+ label,
244
+ nameOverride,
234
245
  onBlur,
235
246
  onChange,
236
247
  onFocus,
237
248
  ref,
238
- children,
239
249
  renderValue,
240
250
  selectedValue,
241
- label,
251
+ testId,
242
252
  ]
243
253
  );
244
254
 
@@ -0,0 +1,20 @@
1
+ /*!
2
+ * Copyright (c) 2023-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
+ export type SeleniumProps = {
14
+ /**
15
+ * This prop puts a `data` attribute on an HTML element in this component with the value provided.
16
+ *
17
+ * @deprecated **WARNING:** You should be using Semantic Selectors instead of this property. This is a temporary measure for backwards compatibility with existing Selenium tests.
18
+ */
19
+ testId?: string;
20
+ };