@bspk/ui 1.3.20 → 1.3.22

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 (290) hide show
  1. package/dist/components/Accordion/Accordion.js +1 -1
  2. package/dist/components/Accordion/Accordion.js.map +1 -1
  3. package/dist/components/Accordion/accordion.css +19 -12
  4. package/dist/components/Accordion/accordion.css.js +19 -12
  5. package/dist/components/BottomNavigation/BottomNavigation.d.ts +0 -1
  6. package/dist/components/BottomNavigation/BottomNavigation.js +0 -1
  7. package/dist/components/BottomNavigation/BottomNavigation.js.map +1 -1
  8. package/dist/components/BottomNavigation/bottom-navigation.css +1 -0
  9. package/dist/components/BottomNavigation/bottom-navigation.css.js +1 -0
  10. package/dist/components/Button/button.css +4 -0
  11. package/dist/components/Button/button.css.js +4 -0
  12. package/dist/components/Checkbox/Checkbox.js +3 -3
  13. package/dist/components/Checkbox/Checkbox.js.map +1 -1
  14. package/dist/components/CheckboxGroup/CheckboxGroup.d.ts +4 -5
  15. package/dist/components/CheckboxGroup/CheckboxGroup.js +8 -13
  16. package/dist/components/CheckboxGroup/CheckboxGroup.js.map +1 -1
  17. package/dist/components/CheckboxGroup/CheckboxGroupExample.js +5 -0
  18. package/dist/components/CheckboxGroup/CheckboxGroupExample.js.map +1 -1
  19. package/dist/components/CheckboxGroup/checkbox-group.css +2 -0
  20. package/dist/components/CheckboxGroup/checkbox-group.css.js +2 -0
  21. package/dist/components/CheckboxGroupField/CheckboxGroupField.d.ts +3 -3
  22. package/dist/components/CheckboxGroupField/CheckboxGroupField.js +6 -4
  23. package/dist/components/CheckboxGroupField/CheckboxGroupField.js.map +1 -1
  24. package/dist/components/ChipGroup/ChipGroup.d.ts +0 -1
  25. package/dist/components/ChipGroup/ChipGroup.js +0 -1
  26. package/dist/components/ChipGroup/ChipGroup.js.map +1 -1
  27. package/dist/components/ChipGroup/chip-group.css +3 -0
  28. package/dist/components/ChipGroup/chip-group.css.js +3 -0
  29. package/dist/components/DatePicker/DatePicker.d.ts +4 -8
  30. package/dist/components/DatePicker/DatePicker.js +6 -18
  31. package/dist/components/DatePicker/DatePicker.js.map +1 -1
  32. package/dist/components/DatePicker/DatePickerExample.js +3 -3
  33. package/dist/components/DatePicker/DatePickerExample.js.map +1 -1
  34. package/dist/components/DatePickerField/DatePickerField.d.ts +4 -4
  35. package/dist/components/DatePickerField/DatePickerField.js +6 -4
  36. package/dist/components/DatePickerField/DatePickerField.js.map +1 -1
  37. package/dist/components/Dialog/Dialog.d.ts +2 -3
  38. package/dist/components/Dialog/Dialog.js +2 -3
  39. package/dist/components/Dialog/Dialog.js.map +1 -1
  40. package/dist/components/Fab/Fab.d.ts +8 -5
  41. package/dist/components/Fab/Fab.js +8 -5
  42. package/dist/components/Fab/Fab.js.map +1 -1
  43. package/dist/components/Fab/fab.css +1 -0
  44. package/dist/components/Fab/fab.css.js +1 -0
  45. package/dist/components/Field/Field.d.ts +32 -18
  46. package/dist/components/Field/Field.js +8 -38
  47. package/dist/components/Field/Field.js.map +1 -1
  48. package/dist/components/Field/FieldExample.d.ts +1 -0
  49. package/dist/components/Field/FieldExample.js +10 -3
  50. package/dist/components/Field/FieldExample.js.map +1 -1
  51. package/dist/components/Field/Fieldset.d.ts +40 -0
  52. package/dist/components/Field/Fieldset.js +44 -0
  53. package/dist/components/Field/Fieldset.js.map +1 -0
  54. package/dist/components/Field/field.css +5 -7
  55. package/dist/components/Field/field.css.js +5 -7
  56. package/dist/components/Field/index.d.ts +1 -3
  57. package/dist/components/Field/index.js +1 -3
  58. package/dist/components/Field/index.js.map +1 -1
  59. package/dist/components/Field/utils.d.ts +8 -38
  60. package/dist/components/Field/utils.js +6 -33
  61. package/dist/components/Field/utils.js.map +1 -1
  62. package/dist/components/FileUpload/FileUpload.js +1 -1
  63. package/dist/components/FileUpload/FileUpload.js.map +1 -1
  64. package/dist/components/FileUploadItem/FileUploadItem.js +1 -1
  65. package/dist/components/FileUploadItem/FileUploadItem.js.map +1 -1
  66. package/dist/components/Flex/Flex.d.ts +11 -7
  67. package/dist/components/Flex/Flex.js +12 -8
  68. package/dist/components/Flex/Flex.js.map +1 -1
  69. package/dist/components/InlineAlert/InlineAlert.d.ts +2 -2
  70. package/dist/components/InlineAlert/InlineAlert.js +2 -2
  71. package/dist/components/InlineAlert/InlineAlert.js.map +1 -1
  72. package/dist/components/Input/Input.d.ts +60 -15
  73. package/dist/components/Input/Input.js +42 -25
  74. package/dist/components/Input/Input.js.map +1 -1
  75. package/dist/components/Input/InputExample.js +4 -4
  76. package/dist/components/Input/InputExample.js.map +1 -1
  77. package/dist/components/Input/index.d.ts +0 -1
  78. package/dist/components/Input/index.js +0 -1
  79. package/dist/components/Input/index.js.map +1 -1
  80. package/dist/components/InputField/InputField.d.ts +4 -4
  81. package/dist/components/InputField/InputField.js +6 -4
  82. package/dist/components/InputField/InputField.js.map +1 -1
  83. package/dist/components/InputNumber/InputNumber.d.ts +8 -7
  84. package/dist/components/InputNumber/InputNumber.js +9 -16
  85. package/dist/components/InputNumber/InputNumber.js.map +1 -1
  86. package/dist/components/InputNumber/InputNumberExample.js +3 -3
  87. package/dist/components/InputNumber/InputNumberExample.js.map +1 -1
  88. package/dist/components/InputNumber/input-number.css +1 -0
  89. package/dist/components/InputNumber/input-number.css.js +1 -0
  90. package/dist/components/InputNumberField/InputNumberField.d.ts +4 -4
  91. package/dist/components/InputNumberField/InputNumberField.js +6 -4
  92. package/dist/components/InputNumberField/InputNumberField.js.map +1 -1
  93. package/dist/components/InputPhone/InputPhone.d.ts +8 -8
  94. package/dist/components/InputPhone/InputPhone.js +12 -18
  95. package/dist/components/InputPhone/InputPhone.js.map +1 -1
  96. package/dist/components/InputPhone/InputPhoneExample.js +3 -3
  97. package/dist/components/InputPhone/InputPhoneExample.js.map +1 -1
  98. package/dist/components/InputPhone/input-phone.css +1 -0
  99. package/dist/components/InputPhone/input-phone.css.js +1 -0
  100. package/dist/components/InputPhoneField/InputPhoneField.d.ts +4 -4
  101. package/dist/components/InputPhoneField/InputPhoneField.js +6 -4
  102. package/dist/components/InputPhoneField/InputPhoneField.js.map +1 -1
  103. package/dist/components/ListItem/list-item.css +1 -0
  104. package/dist/components/ListItem/list-item.css.js +1 -0
  105. package/dist/components/Modal/Modal.js +22 -26
  106. package/dist/components/Modal/Modal.js.map +1 -1
  107. package/dist/components/Modal/ModalExample.js +4 -1
  108. package/dist/components/Modal/ModalExample.js.map +1 -1
  109. package/dist/components/Modal/modal.css +4 -2
  110. package/dist/components/Modal/modal.css.js +4 -2
  111. package/dist/components/OTPInput/otp-input.css +1 -0
  112. package/dist/components/OTPInput/otp-input.css.js +1 -0
  113. package/dist/components/Pagination/Pagination.js +2 -2
  114. package/dist/components/Pagination/Pagination.js.map +1 -1
  115. package/dist/components/Password/Password.d.ts +9 -7
  116. package/dist/components/Password/Password.js +13 -17
  117. package/dist/components/Password/Password.js.map +1 -1
  118. package/dist/components/Password/PasswordExample.js +3 -3
  119. package/dist/components/Password/PasswordExample.js.map +1 -1
  120. package/dist/components/PasswordField/PasswordField.d.ts +4 -4
  121. package/dist/components/PasswordField/PasswordField.js +6 -4
  122. package/dist/components/PasswordField/PasswordField.js.map +1 -1
  123. package/dist/components/Popover/Popover.d.ts +0 -1
  124. package/dist/components/Popover/Popover.js +0 -1
  125. package/dist/components/Popover/Popover.js.map +1 -1
  126. package/dist/components/RadioGroup/RadioGroup.d.ts +1 -2
  127. package/dist/components/RadioGroup/RadioGroup.js +5 -11
  128. package/dist/components/RadioGroup/RadioGroup.js.map +1 -1
  129. package/dist/components/RadioGroupField/RadioGroupField.d.ts +3 -3
  130. package/dist/components/RadioGroupField/RadioGroupField.js +6 -4
  131. package/dist/components/RadioGroupField/RadioGroupField.js.map +1 -1
  132. package/dist/components/SearchBar/SearchBar.d.ts +0 -1
  133. package/dist/components/SearchBar/SearchBar.js +0 -1
  134. package/dist/components/SearchBar/SearchBar.js.map +1 -1
  135. package/dist/components/SegmentedControl/SegmentedControl.d.ts +0 -1
  136. package/dist/components/SegmentedControl/SegmentedControl.js +0 -1
  137. package/dist/components/SegmentedControl/SegmentedControl.js.map +1 -1
  138. package/dist/components/Select/Select.d.ts +7 -6
  139. package/dist/components/Select/Select.js +10 -15
  140. package/dist/components/Select/Select.js.map +1 -1
  141. package/dist/components/Select/SelectExample.js +3 -3
  142. package/dist/components/Select/SelectExample.js.map +1 -1
  143. package/dist/components/SelectField/SelectField.d.ts +4 -4
  144. package/dist/components/SelectField/SelectField.js +6 -4
  145. package/dist/components/SelectField/SelectField.js.map +1 -1
  146. package/dist/components/Slider/Slider.d.ts +1 -2
  147. package/dist/components/Slider/Slider.js +1 -2
  148. package/dist/components/Slider/Slider.js.map +1 -1
  149. package/dist/components/Snackbar/Snackbar.d.ts +0 -1
  150. package/dist/components/Snackbar/Snackbar.js +0 -1
  151. package/dist/components/Snackbar/Snackbar.js.map +1 -1
  152. package/dist/components/Switch/Switch.d.ts +0 -1
  153. package/dist/components/Switch/Switch.js +0 -1
  154. package/dist/components/Switch/Switch.js.map +1 -1
  155. package/dist/components/TabGroup/TabGroup.d.ts +0 -1
  156. package/dist/components/TabGroup/TabGroup.js +0 -1
  157. package/dist/components/TabGroup/TabGroup.js.map +1 -1
  158. package/dist/components/TabList/TabList.d.ts +0 -1
  159. package/dist/components/TabList/TabList.js +0 -1
  160. package/dist/components/TabList/TabList.js.map +1 -1
  161. package/dist/components/TabList/tab-list.css +1 -0
  162. package/dist/components/TabList/tab-list.css.js +1 -0
  163. package/dist/components/Table/table.css +2 -1
  164. package/dist/components/Table/table.css.js +2 -1
  165. package/dist/components/Textarea/Textarea.d.ts +4 -7
  166. package/dist/components/Textarea/Textarea.js +5 -16
  167. package/dist/components/Textarea/Textarea.js.map +1 -1
  168. package/dist/components/Textarea/TextareaExample.js +3 -3
  169. package/dist/components/Textarea/TextareaExample.js.map +1 -1
  170. package/dist/components/TextareaField/TextareaField.d.ts +4 -4
  171. package/dist/components/TextareaField/TextareaField.js +6 -4
  172. package/dist/components/TextareaField/TextareaField.js.map +1 -1
  173. package/dist/components/TimePicker/TimePicker.d.ts +8 -6
  174. package/dist/components/TimePicker/TimePicker.js +10 -14
  175. package/dist/components/TimePicker/TimePicker.js.map +1 -1
  176. package/dist/components/TimePicker/TimePickerExample.js +3 -3
  177. package/dist/components/TimePicker/TimePickerExample.js.map +1 -1
  178. package/dist/components/TimePickerField/TimePickerField.d.ts +4 -4
  179. package/dist/components/TimePickerField/TimePickerField.js +6 -4
  180. package/dist/components/TimePickerField/TimePickerField.js.map +1 -1
  181. package/dist/types/common.d.ts +2 -0
  182. package/dist/types/common.js.map +1 -1
  183. package/dist/utils/demo.js +1 -1
  184. package/dist/utils/demo.js.map +1 -1
  185. package/package.json +3 -4
  186. package/src/components/Accordion/Accordion.tsx +2 -2
  187. package/src/components/Accordion/accordion.scss +10 -1
  188. package/src/components/BottomNavigation/BottomNavigation.tsx +0 -1
  189. package/src/components/BottomNavigation/bottom-navigation.scss +1 -0
  190. package/src/components/Button/button.scss +4 -0
  191. package/src/components/Checkbox/Checkbox.tsx +3 -3
  192. package/src/components/CheckboxGroup/CheckboxGroup.tsx +37 -52
  193. package/src/components/CheckboxGroup/CheckboxGroupExample.tsx +6 -0
  194. package/src/components/CheckboxGroup/checkbox-group.scss +2 -0
  195. package/src/components/CheckboxGroupField/CheckboxGroupField.tsx +15 -11
  196. package/src/components/ChipGroup/ChipGroup.tsx +0 -1
  197. package/src/components/ChipGroup/chip-group.scss +4 -0
  198. package/src/components/DatePicker/DatePicker.tsx +9 -20
  199. package/src/components/DatePicker/DatePickerExample.tsx +3 -5
  200. package/src/components/DatePickerField/DatePickerField.rtl.test.tsx +1 -1
  201. package/src/components/DatePickerField/DatePickerField.tsx +10 -6
  202. package/src/components/Dialog/Dialog.tsx +2 -3
  203. package/src/components/Fab/Fab.tsx +8 -5
  204. package/src/components/Fab/fab.scss +1 -0
  205. package/src/components/Field/Field.rtl.test.tsx +8 -6
  206. package/src/components/Field/Field.tsx +64 -61
  207. package/src/components/Field/FieldExample.tsx +27 -5
  208. package/src/components/Field/Fieldset.tsx +78 -0
  209. package/src/components/Field/field.scss +23 -27
  210. package/src/components/Field/index.tsx +1 -3
  211. package/src/components/Field/utils.ts +15 -77
  212. package/src/components/FileUpload/FileUpload.tsx +1 -1
  213. package/src/components/FileUploadItem/FileUploadItem.tsx +1 -1
  214. package/src/components/Flex/Flex.tsx +12 -7
  215. package/src/components/InlineAlert/InlineAlert.rtl.test.tsx +1 -1
  216. package/src/components/InlineAlert/InlineAlert.tsx +3 -3
  217. package/src/components/Input/Input.tsx +140 -48
  218. package/src/components/Input/InputExample.tsx +4 -6
  219. package/src/components/Input/index.tsx +0 -1
  220. package/src/components/InputField/InputField.tsx +10 -6
  221. package/src/components/InputNumber/InputNumber.tsx +11 -16
  222. package/src/components/InputNumber/InputNumberExample.tsx +7 -4
  223. package/src/components/InputNumber/input-number.scss +1 -0
  224. package/src/components/InputNumberField/InputNumberField.tsx +10 -6
  225. package/src/components/InputPhone/InputPhone.tsx +14 -18
  226. package/src/components/InputPhone/InputPhoneExample.tsx +7 -6
  227. package/src/components/InputPhone/input-phone.scss +1 -0
  228. package/src/components/InputPhoneField/InputPhoneField.tsx +10 -6
  229. package/src/components/ListItem/list-item.scss +1 -0
  230. package/src/components/Modal/Modal.tsx +26 -30
  231. package/src/components/Modal/ModalExample.tsx +7 -2
  232. package/src/components/Modal/modal.scss +1 -1
  233. package/src/components/OTPInput/otp-input.scss +1 -0
  234. package/src/components/Pagination/Pagination.tsx +2 -2
  235. package/src/components/Password/Password.tsx +15 -17
  236. package/src/components/Password/PasswordExample.tsx +13 -5
  237. package/src/components/PasswordField/PasswordField.tsx +10 -6
  238. package/src/components/Popover/Popover.tsx +0 -1
  239. package/src/components/RadioGroup/RadioGroup.tsx +14 -20
  240. package/src/components/RadioGroupField/RadioGroupField.tsx +16 -11
  241. package/src/components/SearchBar/SearchBar.tsx +0 -1
  242. package/src/components/SegmentedControl/SegmentedControl.tsx +0 -1
  243. package/src/components/Select/Select.tsx +13 -14
  244. package/src/components/Select/SelectExample.tsx +7 -4
  245. package/src/components/SelectField/SelectField.rtl.test.tsx +7 -18
  246. package/src/components/SelectField/SelectField.tsx +10 -6
  247. package/src/components/Slider/Slider.tsx +1 -2
  248. package/src/components/Snackbar/Snackbar.tsx +0 -1
  249. package/src/components/Switch/Switch.tsx +0 -1
  250. package/src/components/TabGroup/TabGroup.tsx +0 -1
  251. package/src/components/TabList/TabList.tsx +0 -1
  252. package/src/components/TabList/tab-list.scss +1 -0
  253. package/src/components/Table/table.scss +2 -1
  254. package/src/components/Textarea/Textarea.tsx +8 -17
  255. package/src/components/Textarea/TextareaExample.tsx +3 -5
  256. package/src/components/TextareaField/TextareaField.tsx +10 -6
  257. package/src/components/TimePicker/TimePicker.tsx +12 -15
  258. package/src/components/TimePicker/TimePickerExample.tsx +3 -5
  259. package/src/components/TimePickerField/TimePickerField.tsx +10 -6
  260. package/src/types/common.ts +8 -0
  261. package/src/utils/demo.ts +1 -1
  262. package/dist/components/Field/FieldDescription.d.ts +0 -9
  263. package/dist/components/Field/FieldDescription.js +0 -13
  264. package/dist/components/Field/FieldDescription.js.map +0 -1
  265. package/dist/components/Field/FieldError.d.ts +0 -11
  266. package/dist/components/Field/FieldError.js +0 -14
  267. package/dist/components/Field/FieldError.js.map +0 -1
  268. package/dist/components/Field/FieldLabel.d.ts +0 -21
  269. package/dist/components/Field/FieldLabel.js +0 -14
  270. package/dist/components/Field/FieldLabel.js.map +0 -1
  271. package/dist/components/FormField/FormField.d.ts +0 -66
  272. package/dist/components/FormField/FormField.js +0 -31
  273. package/dist/components/FormField/FormField.js.map +0 -1
  274. package/dist/components/FormField/FormFieldExample.d.ts +0 -9
  275. package/dist/components/FormField/FormFieldExample.js +0 -99
  276. package/dist/components/FormField/FormFieldExample.js.map +0 -1
  277. package/dist/components/FormField/index.d.ts +0 -1
  278. package/dist/components/FormField/index.js +0 -2
  279. package/dist/components/FormField/index.js.map +0 -1
  280. package/dist/components/Input/InputElement.d.ts +0 -82
  281. package/dist/components/Input/InputElement.js +0 -64
  282. package/dist/components/Input/InputElement.js.map +0 -1
  283. package/src/components/Field/FieldDescription.tsx +0 -17
  284. package/src/components/Field/FieldError.tsx +0 -25
  285. package/src/components/Field/FieldLabel.tsx +0 -44
  286. package/src/components/FormField/FormField.rtl.test.tsx +0 -20
  287. package/src/components/FormField/FormField.tsx +0 -95
  288. package/src/components/FormField/FormFieldExample.tsx +0 -277
  289. package/src/components/FormField/index.tsx +0 -1
  290. package/src/components/Input/InputElement.tsx +0 -192
@@ -3,12 +3,12 @@ import { SvgIcon } from '@bspk/icons/SvgIcon';
3
3
  import { AsYouType, getCountryCallingCode } from 'libphonenumber-js';
4
4
  import { useMemo, useRef, useState } from 'react';
5
5
  import { Button } from '-/components/Button';
6
- import { useFieldInit } from '-/components/Field';
7
- import { InputElement, InputProps } from '-/components/Input';
6
+ import { Input, InputProps } from '-/components/Input';
8
7
  import { ListItem } from '-/components/ListItem';
9
8
  import { Menu } from '-/components/Menu';
10
9
  import { useArrowNavigation } from '-/hooks/useArrowNavigation';
11
10
  import { useFloating } from '-/hooks/useFloating';
11
+ import { useId } from '-/hooks/useId';
12
12
  import { useOutsideClick } from '-/hooks/useOutsideClick';
13
13
  import { FieldControlProps } from '-/types/common';
14
14
  import { countryCodeData, countryCodes, SupportedCountryCode } from '-/utils/countryCodes';
@@ -57,26 +57,26 @@ export type InputPhoneProps = FieldControlProps<string, SupportedCountryCode> &
57
57
  * For a more complete example with field usage, see the InputPhoneField component.
58
58
  *
59
59
  * @example
60
- * import { InputPhone } from '@bspk/ui/InputPhone';
61
- * import { Field, FieldDescription, FieldLabel } from '@bspk/ui/Field';
60
+ * import { InputPhone } from '-/components/InputPhone';
62
61
  *
63
62
  * () => {
64
63
  * const [value, onChange] = useState<string | undefined>();
65
64
  *
66
65
  * return (
67
66
  * <div style={{ width: 320 }}>
68
- * <Field>
69
- * <FieldLabel>Example Input Phone</FieldLabel>
67
+ * <Field
68
+ * controlId="example-input-phone"
69
+ * helperText="The phone input allows you to enter a phone number with country code."
70
+ * label="Example Input Phone"
71
+ * >
70
72
  * <InputPhone
71
73
  * aria-label="Phone Number"
74
+ * id="example-input-phone"
72
75
  * initialCountryCode="US"
73
76
  * name="example-name"
74
77
  * onChange={onChange}
75
78
  * value={value}
76
79
  * />
77
- * <FieldDescription>
78
- * The phone input allows you to enter a phone number with country code.
79
- * </FieldDescription>
80
80
  * </Field>
81
81
  * </div>
82
82
  * );
@@ -94,20 +94,16 @@ export function InputPhone({
94
94
  readOnly,
95
95
  name,
96
96
  id: idProp,
97
- invalid: invalidProp,
97
+ invalid = false,
98
98
  required = false,
99
99
  size = 'medium',
100
100
  inputRef,
101
101
  scrollLimit = 5,
102
102
  'aria-label': ariaLabel = 'Phone number input',
103
+ 'aria-describedby': ariaDescribedBy,
104
+ 'aria-errormessage': ariaErrorMessage,
103
105
  }: InputPhoneProps) {
104
- const { id, ariaDescribedBy, ariaErrorMessage, invalid } = useFieldInit({
105
- idProp,
106
- required,
107
- disabled,
108
- readOnly,
109
- invalidProp,
110
- });
106
+ const id = useId(idProp);
111
107
  const menuId = useMemo(() => `${id}-menu`, [id]);
112
108
 
113
109
  const items = useIds(`input-phone-${id}`, SELECT_OPTIONS);
@@ -174,7 +170,7 @@ export function InputPhone({
174
170
  },
175
171
  })}
176
172
  >
177
- <InputElement
173
+ <Input
178
174
  aria-describedby={ariaDescribedBy}
179
175
  aria-errormessage={ariaErrorMessage}
180
176
  aria-label={ariaLabel || undefined}
@@ -1,6 +1,6 @@
1
1
  import { useState } from 'react';
2
2
  import { InputPhone, InputPhoneProps } from '.';
3
- import { Field, FieldDescription, FieldLabel } from '-/components/Field';
3
+ import { Field } from '-/components/Field';
4
4
  import { Preset, ComponentExample } from '-/utils/demo';
5
5
 
6
6
  export const presets: Preset<InputPhoneProps>[] = [];
@@ -19,18 +19,19 @@ export const Usage = () => {
19
19
 
20
20
  return (
21
21
  <div style={{ width: 320 }}>
22
- <Field>
23
- <FieldLabel>Example Input Phone</FieldLabel>
22
+ <Field
23
+ controlId="example-input-phone"
24
+ helperText="The phone input allows you to enter a phone number with country code."
25
+ label="Example Input Phone"
26
+ >
24
27
  <InputPhone
25
28
  aria-label="Phone Number"
29
+ id="example-input-phone"
26
30
  initialCountryCode="US"
27
31
  name="example-name"
28
32
  onChange={onChange}
29
33
  value={value}
30
34
  />
31
- <FieldDescription>
32
- The phone input allows you to enter a phone number with country code.
33
- </FieldDescription>
34
35
  </Field>
35
36
  </div>
36
37
  );
@@ -12,6 +12,7 @@
12
12
 
13
13
  input:focus-visible {
14
14
  outline: solid 2px var(--stroke-neutral-focus);
15
+ isolation: isolate;
15
16
  border-radius: var(--radius-sm);
16
17
  }
17
18
 
@@ -1,7 +1,8 @@
1
- import { FormField, FormFieldControlProps } from '-/components/FormField';
1
+ import { Field, FieldControlProps, propsWithAria } from '-/components/Field';
2
2
  import { InputPhone, InputPhoneProps } from '-/components/InputPhone';
3
+ import { useId } from '-/hooks/useId';
3
4
 
4
- export type InputPhoneFieldProps = FormFieldControlProps<InputPhoneProps>;
5
+ export type InputPhoneFieldProps = FieldControlProps<InputPhoneProps>;
5
6
 
6
7
  /**
7
8
  * A field wrapper for the InputPhone component.
@@ -9,7 +10,7 @@ export type InputPhoneFieldProps = FormFieldControlProps<InputPhoneProps>;
9
10
  * This component takes properties from the FormField and InputPhone components.
10
11
  *
11
12
  * @name InputPhoneField
12
- * @phase Stable
13
+ * @phase UXReview
13
14
  *
14
15
  * @generated
15
16
  */
@@ -19,18 +20,21 @@ export function InputPhoneField({
19
20
  labelTrailing,
20
21
  errorMessage,
21
22
  style,
23
+ id: idProp,
22
24
  ...controlProps
23
25
  }: InputPhoneFieldProps) {
26
+ const id = useId(idProp);
24
27
  return (
25
- <FormField
28
+ <Field
29
+ controlId={id}
26
30
  errorMessage={errorMessage}
27
31
  helperText={helperText}
28
32
  label={label}
29
33
  labelTrailing={labelTrailing}
30
34
  style={style}
31
35
  >
32
- <InputPhone {...controlProps} />
33
- </FormField>
36
+ <InputPhone {...propsWithAria({ id, controlProps, errorMessage, helperText })} />
37
+ </Field>
34
38
  );
35
39
  }
36
40
 
@@ -24,6 +24,7 @@
24
24
  &:focus-visible,
25
25
  &:has(*:focus-visible) {
26
26
  outline: solid 2px var(--stroke-neutral-focus);
27
+ isolation: isolate;
27
28
 
28
29
  [data-inner] {
29
30
  border-color: transparent;
@@ -3,40 +3,30 @@ import { SvgClose } from '@bspk/icons/Close';
3
3
  import { ReactNode, useMemo, useRef } from 'react';
4
4
  import { Button, ButtonProps } from '-/components/Button';
5
5
  import { DialogProps, Dialog } from '-/components/Dialog';
6
- import { useDebounceCallback } from '-/hooks/useDebounceCallback';
7
6
  import { useEventListener } from '-/hooks/useEventListener';
8
7
  import { useUIContext } from '-/hooks/useUIContext';
9
8
  import { CallToActionButton } from '-/types/common';
10
9
 
11
- // This hook is used to set the height of the modal based on the dialog box height.
12
- // It listens to the resize event and updates the modal height accordingly.
13
- function useDialogHeight() {
14
- const onResize = () => {
15
- const { dialogBox, modal } = modalRefs.current || {};
16
- if (!dialogBox || !modal) return;
17
- modal.style.height = `${dialogBox.offsetHeight}px`;
18
- modal.style.visibility = '';
10
+ function useMatchParentHeight() {
11
+ const elementRef = useRef<HTMLDivElement | null>(null);
12
+ const updateHeight = () => {
13
+ const element = elementRef.current;
14
+ const parentElement = element?.parentElement;
15
+ if (!element || !parentElement) return;
16
+ // Reset height to allow shrinking or growing
17
+ element.style.height = '';
18
+ // Apply new height on next frame
19
+ requestAnimationFrame(() => {
20
+ element.style.height = `${parentElement.clientHeight}px`;
21
+ });
19
22
  };
20
-
21
- useEventListener('resize', useDebounceCallback(onResize, 100));
22
-
23
- const modalRefs = useRef<{
24
- dialogBox: HTMLDivElement | null;
25
- modal: HTMLDivElement | null;
26
- } | null>(null);
23
+ useEventListener('resize', updateHeight);
24
+ useEventListener('orientationchange', updateHeight);
27
25
 
28
26
  return {
29
- setModalRefs: (node: HTMLElement | null) => {
30
- if (!node) return;
31
- const dialogBox = node.querySelector<HTMLDivElement>('[data-dialog-box]');
32
- const modal = node.querySelector<HTMLDivElement>('[data-bspk="modal"]');
33
- modalRefs.current = {
34
- dialogBox,
35
- modal,
36
- };
37
- if (!dialogBox || !modal) return;
38
- modal.style.height = `${dialogBox.offsetHeight}px`;
39
- modal.style.visibility = '';
27
+ setElement: (el: HTMLDivElement | null) => {
28
+ elementRef.current = el;
29
+ updateHeight();
40
30
  },
41
31
  };
42
32
  }
@@ -168,7 +158,7 @@ export function Modal({
168
158
  return nextButtons;
169
159
  }, [callToAction, cancelButton, dialogProps.onClose, isMobile]);
170
160
 
171
- const { setModalRefs } = useDialogHeight();
161
+ const { setElement } = useMatchParentHeight();
172
162
 
173
163
  return (
174
164
  <Dialog
@@ -176,11 +166,16 @@ export function Modal({
176
166
  aria-description={description}
177
167
  aria-label={header}
178
168
  disableFocusTrap={disableFocusTrap}
179
- innerRef={setModalRefs}
180
169
  placement="center"
181
170
  showScrim
182
171
  >
183
- <div data-bspk="modal" ref={(node) => innerRef?.(node)} style={{ visibility: 'hidden' }}>
172
+ <div
173
+ data-bspk="modal"
174
+ ref={(node) => {
175
+ innerRef?.(node);
176
+ setElement(node);
177
+ }}
178
+ >
184
179
  <div data-modal-header>
185
180
  <div data-modal-title>{header}</div>
186
181
  <Button
@@ -188,6 +183,7 @@ export function Modal({
188
183
  iconOnly
189
184
  label="close"
190
185
  onClick={dialogProps.onClose}
186
+ size={isMobile ? 'medium' : 'small'}
191
187
  variant="tertiary"
192
188
  />
193
189
  </div>
@@ -47,7 +47,12 @@ export const ModalExample: ComponentExampleFn<ModalProps> = ({ action }) => ({
47
47
  header: 'Header Only',
48
48
  description: 'This modal has no buttons.',
49
49
  children: (
50
- <>
50
+ <div
51
+ style={{
52
+ display: 'flex',
53
+ flexDirection: 'column',
54
+ }}
55
+ >
51
56
  <p>
52
57
  This is a demo of a scrolling modal. Most modals won&apos;t scroll but mobile uses modals as
53
58
  dropdowns which may have more items than can fit in the screen.
@@ -63,7 +68,7 @@ export const ModalExample: ComponentExampleFn<ModalProps> = ({ action }) => ({
63
68
  trailing={<Checkbox aria-label="" name="" onChange={() => {}} value="" />}
64
69
  />
65
70
  ))}
66
- </>
71
+ </div>
67
72
  ),
68
73
  },
69
74
  },
@@ -5,7 +5,7 @@
5
5
  gap: var(--spacing-sizing-02);
6
6
  padding: var(--spacing-sizing-05);
7
7
 
8
- [data-screen-size='small'] & {
8
+ @media (width < 640px) {
9
9
  padding: var(--spacing-sizing-04);
10
10
  }
11
11
 
@@ -40,6 +40,7 @@
40
40
  [data-digit] {
41
41
  &[data-active] {
42
42
  outline: solid 2px var(--stroke-neutral-focus);
43
+ isolation: isolate;
43
44
 
44
45
  &:empty::before {
45
46
  // caret
@@ -3,7 +3,7 @@ import { SvgIcon } from '@bspk/icons/SvgIcon';
3
3
  import { AriaAttributes, useEffect, useState } from 'react';
4
4
  import { PageList } from './PageList';
5
5
  import { Button } from '-/components/Button';
6
- import { InputElement } from '-/components/Input';
6
+ import { Input } from '-/components/Input';
7
7
  import { sendAriaLiveMessage } from '-/utils/sendAriaLiveMessage';
8
8
 
9
9
  // After this point the manual input renders. With equal or fewer pages the individual page buttons render instead.
@@ -104,7 +104,7 @@ export function Pagination({
104
104
  submitInputChange();
105
105
  }}
106
106
  >
107
- <InputElement
107
+ <Input
108
108
  name="page-number"
109
109
  onBlur={() => submitInputChange()}
110
110
  onChange={setInputValue}
@@ -1,8 +1,8 @@
1
1
  import './password.scss';
2
2
  import { useState } from 'react';
3
3
  import { Button } from '-/components/Button';
4
- import { useFieldInit } from '-/components/Field';
5
- import { InputElement, InputProps } from '-/components/Input';
4
+ import { Input, InputProps } from '-/components/Input';
5
+ import { useId } from '-/hooks/useId';
6
6
  import { FieldControlProps } from '-/types/common';
7
7
 
8
8
  export type PasswordProps = FieldControlProps & Pick<InputProps, 'containerRef' | 'inputProps' | 'inputRef' | 'size'>;
@@ -13,23 +13,25 @@ export type PasswordProps = FieldControlProps & Pick<InputProps, 'containerRef'
13
13
  * For a more complete example with field usage, see the PasswordField component.
14
14
  *
15
15
  * @example
16
- * import { Password } from '@bspk/ui/Password';
17
- * import { Field, FieldLabel, FieldDescription } from '-/components/Field';
16
+ * import { Password } from '-/components/Password';
18
17
  *
19
18
  * () => {
20
19
  * const [value, setValue] = useState<string | undefined>('');
21
20
  *
22
21
  * return (
23
- * <div style={{ width: 320 }}>
24
- * <Field>
25
- * <FieldLabel>Password</FieldLabel>
22
+ * <div>
23
+ * <Field
24
+ * controlId="example-password"
25
+ * helperText="The password field allows you to enter a secure password."
26
+ * label="Password"
27
+ * >
26
28
  * <Password
27
29
  * aria-label="password"
30
+ * id="example-password"
28
31
  * name="password"
29
32
  * onChange={(next) => setValue(next)}
30
33
  * value={value}
31
34
  * />
32
- * <FieldDescription>The password field allows you to enter a secure password.</FieldDescription>
33
35
  * </Field>
34
36
  * </div>
35
37
  * );
@@ -45,20 +47,16 @@ export function Password({
45
47
  onChange,
46
48
  required = false,
47
49
  containerRef,
48
- invalid: invalidProp,
50
+ invalid = false,
49
51
  readOnly,
50
52
  disabled,
51
53
  id: idProp,
52
54
  'aria-label': ariaLabel,
55
+ 'aria-describedby': ariaDescribedBy,
56
+ 'aria-errormessage': ariaErrorMessage,
53
57
  ...props
54
58
  }: PasswordProps) {
55
- const { id, ariaDescribedBy, ariaErrorMessage, invalid } = useFieldInit({
56
- idProp,
57
- required,
58
- disabled,
59
- readOnly,
60
- invalidProp,
61
- });
59
+ const id = useId(idProp);
62
60
 
63
61
  const [isShowingPassword, setIsShowingPassword] = useState(false);
64
62
 
@@ -68,7 +66,7 @@ export function Password({
68
66
  };
69
67
 
70
68
  return (
71
- <InputElement
69
+ <Input
72
70
  {...props}
73
71
  aria-describedby={ariaDescribedBy}
74
72
  aria-errormessage={ariaErrorMessage}
@@ -1,6 +1,6 @@
1
1
  import { useState } from 'react';
2
2
  import { Password, PasswordProps } from '.';
3
- import { Field, FieldLabel, FieldDescription } from '-/components/Field';
3
+ import { Field } from '-/components/Field';
4
4
  import { ComponentExample } from '-/utils/demo';
5
5
 
6
6
  export const PasswordExample: ComponentExample<PasswordProps> = {
@@ -15,10 +15,18 @@ export const Usage = () => {
15
15
 
16
16
  return (
17
17
  <div>
18
- <Field>
19
- <FieldLabel>Password</FieldLabel>
20
- <Password aria-label="password" name="password" onChange={(next) => setValue(next)} value={value} />
21
- <FieldDescription>The password field allows you to enter a secure password.</FieldDescription>
18
+ <Field
19
+ controlId="example-password"
20
+ helperText="The password field allows you to enter a secure password."
21
+ label="Password"
22
+ >
23
+ <Password
24
+ aria-label="password"
25
+ id="example-password"
26
+ name="password"
27
+ onChange={(next) => setValue(next)}
28
+ value={value}
29
+ />
22
30
  </Field>
23
31
  </div>
24
32
  );
@@ -1,7 +1,8 @@
1
- import { FormField, FormFieldControlProps } from '-/components/FormField';
1
+ import { Field, FieldControlProps, propsWithAria } from '-/components/Field';
2
2
  import { Password, PasswordProps } from '-/components/Password';
3
+ import { useId } from '-/hooks/useId';
3
4
 
4
- export type PasswordFieldProps = FormFieldControlProps<PasswordProps>;
5
+ export type PasswordFieldProps = FieldControlProps<PasswordProps>;
5
6
 
6
7
  /**
7
8
  * A field wrapper for the Password component.
@@ -9,7 +10,7 @@ export type PasswordFieldProps = FormFieldControlProps<PasswordProps>;
9
10
  * This component takes properties from the FormField and Password components.
10
11
  *
11
12
  * @name PasswordField
12
- * @phase Stable
13
+ * @phase UXReview
13
14
  *
14
15
  * @generated
15
16
  */
@@ -19,18 +20,21 @@ export function PasswordField({
19
20
  labelTrailing,
20
21
  errorMessage,
21
22
  style,
23
+ id: idProp,
22
24
  ...controlProps
23
25
  }: PasswordFieldProps) {
26
+ const id = useId(idProp);
24
27
  return (
25
- <FormField
28
+ <Field
29
+ controlId={id}
26
30
  errorMessage={errorMessage}
27
31
  helperText={helperText}
28
32
  label={label}
29
33
  labelTrailing={labelTrailing}
30
34
  style={style}
31
35
  >
32
- <Password {...controlProps} />
33
- </FormField>
36
+ <Password {...propsWithAria({ id, controlProps, errorMessage, helperText })} />
37
+ </Field>
34
38
  );
35
39
  }
36
40
 
@@ -56,7 +56,6 @@ export type PopoverProps = CommonProps<'disabled'> &
56
56
  * Brief message that provide additional guidance and helps users perform an action if needed.
57
57
  *
58
58
  * @example
59
- * import { useState } from 'react';
60
59
  * import { Popover } from '@bspk/ui/Popover';
61
60
  * import { Button } from '@bspk/ui/Button';
62
61
  *
@@ -1,7 +1,7 @@
1
1
  import './radio-group.scss';
2
- import { useFieldInit } from '-/components/Field';
3
2
  import { RadioProps } from '-/components/Radio';
4
3
  import { RadioOption, RadioOptionProps } from '-/components/RadioOption';
4
+ import { useId } from '-/hooks/useId';
5
5
  import { ElementProps, FieldControlProps } from '-/types/common';
6
6
 
7
7
  export type RadioGroupOption = Pick<RadioOptionProps, 'checked' | 'description' | 'disabled' | 'label'> &
@@ -37,7 +37,6 @@ export type RadioGroupProps = Omit<FieldControlProps, 'readOnly'> & {
37
37
  * For a more complete example with field usage, see the RadioGroupField component.
38
38
  *
39
39
  * @example
40
- * import { useState } from 'react';
41
40
  * import { RadioGroup } from '@bspk/ui/RadioGroup';
42
41
  *
43
42
  * () => {
@@ -68,45 +67,40 @@ export function RadioGroup({
68
67
  onChange,
69
68
  options = [],
70
69
  name,
71
- value: groupValue,
70
+ value,
72
71
  disabled = false,
73
- invalid: invalidProp,
74
72
  required,
73
+ invalid = false,
75
74
  id: idProp,
76
- 'aria-describedby': ariaDescribedByProp,
77
- 'aria-errormessage': ariaErrorMessageProp,
75
+ 'aria-describedby': ariaDescribedBy,
76
+ 'aria-errormessage': ariaErrorMessage,
78
77
  ...props
79
78
  }: ElementProps<RadioGroupProps, 'div'>) {
80
- const { id, ariaDescribedBy, ariaErrorMessage, invalid } = useFieldInit({
81
- idProp,
82
- required,
83
- disabled,
84
- invalidProp,
85
- });
79
+ const id = useId(idProp);
86
80
 
87
81
  return (
88
82
  <div
89
83
  {...props}
90
- aria-describedby={ariaDescribedByProp || ariaDescribedBy || undefined}
84
+ aria-describedby={ariaDescribedBy || undefined}
91
85
  data-bspk="radio-group"
92
86
  id={id}
93
87
  role="radiogroup"
94
88
  >
95
- {options.map(({ label, description, value, ...option }, index) => {
89
+ {options.map(({ label, description, value: optionValue, ...option }) => {
96
90
  return (
97
91
  <RadioOption
98
- aria-describedby={ariaDescribedByProp || ariaDescribedBy || undefined}
99
- aria-errormessage={ariaErrorMessageProp || ariaErrorMessage || undefined}
100
- checked={groupValue === value}
92
+ aria-describedby={ariaDescribedBy || undefined}
93
+ aria-errormessage={ariaErrorMessage || undefined}
94
+ checked={value === optionValue}
101
95
  description={description}
102
96
  disabled={disabled || option.disabled}
103
97
  invalid={invalid || undefined}
104
- key={`radio-option-${value || index}`}
98
+ key={optionValue}
105
99
  label={label}
106
100
  name={name}
107
- onChange={(checked) => checked && onChange(value)}
101
+ onChange={(checked) => checked && onChange(optionValue)}
108
102
  required={required}
109
- value={value}
103
+ value={optionValue}
110
104
  />
111
105
  );
112
106
  })}
@@ -1,8 +1,8 @@
1
- import { Field, FieldDescription, FieldError, FieldLabel } from '-/components/Field';
2
- import { FormFieldControlProps } from '-/components/FormField';
1
+ import { FieldControlProps, Fieldset, propsWithAria } from '-/components/Field';
3
2
  import { RadioGroup, RadioGroupProps } from '-/components/RadioGroup';
3
+ import { useId } from '-/hooks/useId';
4
4
 
5
- export type RadioGroupFieldProps = FormFieldControlProps<RadioGroupProps>;
5
+ export type RadioGroupFieldProps = FieldControlProps<RadioGroupProps>;
6
6
 
7
7
  /**
8
8
  * A field wrapper for the RadioGroup component.
@@ -20,17 +20,22 @@ export function RadioGroupField({
20
20
  labelTrailing,
21
21
  errorMessage,
22
22
  style,
23
+ id: idProp,
23
24
  ...controlProps
24
25
  }: RadioGroupFieldProps) {
26
+ const id = useId(idProp);
25
27
  return (
26
- <Field as="fieldset">
27
- <FieldLabel as="legend" labelTrailing={labelTrailing} style={style}>
28
- {label}
29
- </FieldLabel>
30
- <RadioGroup {...controlProps} />
31
- {!errorMessage && helperText && <FieldDescription>{helperText}</FieldDescription>}
32
- {errorMessage && <FieldError>{errorMessage}</FieldError>}
33
- </Field>
28
+ <Fieldset
29
+ controlId={id}
30
+ errorMessage={errorMessage}
31
+ helperText={helperText}
32
+ label={label}
33
+ labelTrailing={labelTrailing}
34
+ required={controlProps.required}
35
+ style={style}
36
+ >
37
+ <RadioGroup {...propsWithAria({ id, controlProps, errorMessage, helperText })} />
38
+ </Fieldset>
34
39
  );
35
40
  }
36
41
 
@@ -69,7 +69,6 @@ export type SearchBarProps<O extends SearchBarOption = SearchBarOption> = Omit<
69
69
  * An input field that allows customers to input search queries and retrieve results.
70
70
  *
71
71
  * @example
72
- * import { useState } from 'react';
73
72
  * import { SearchBar } from '@bspk/ui/SearchBar';
74
73
  *
75
74
  * () => {
@@ -9,7 +9,6 @@ export type SegmentedControlProps = TabListProps<SegmentedControlOption>;
9
9
  * Navigation tool that organizes content across different screens and views.
10
10
  *
11
11
  * @example
12
- * import { useState } from 'react';
13
12
  * import { SegmentedControl } from '@bspk/ui/SegmentedControl';
14
13
  *
15
14
  * () => {