@utilitywarehouse/hearth-react 0.28.6 → 0.29.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 (104) hide show
  1. package/README.md +34 -20
  2. package/SKILL.md +355 -0
  3. package/dist/{chunk-O7RBVBMN.cjs → chunk-LWHIBSW2.cjs} +2 -2
  4. package/dist/{chunk-O7RBVBMN.cjs.map → chunk-LWHIBSW2.cjs.map} +1 -1
  5. package/dist/{chunk-JRVYOIXR.js → chunk-MIVYZGEV.js} +2 -2
  6. package/dist/components/CardAccordion/CardAccordion.context.d.ts.map +1 -1
  7. package/dist/components/Combobox/Combobox.cjs +1 -1
  8. package/dist/components/Combobox/Combobox.js +1 -1
  9. package/dist/components/ExpandableCard/ExpandableCard.cjs +1 -1
  10. package/dist/components/ExpandableCard/ExpandableCard.js +1 -1
  11. package/dist/helpers/get-classname-styles.d.ts.map +1 -1
  12. package/dist/helpers/logger.d.ts.map +1 -1
  13. package/dist/helpers/merge-ids.d.ts.map +1 -1
  14. package/dist/hooks/use-ids.d.ts.map +1 -1
  15. package/dist/index.cjs +1 -1
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.js +1 -1
  18. package/package.json +18 -12
  19. package/public/llms/components/accordion.md +321 -0
  20. package/public/llms/components/alert.md +217 -0
  21. package/public/llms/components/avatar.md +112 -0
  22. package/public/llms/components/badge.md +158 -0
  23. package/public/llms/components/body-text.md +200 -0
  24. package/public/llms/components/box.md +148 -0
  25. package/public/llms/components/breadcrumbs.md +97 -0
  26. package/public/llms/components/button.md +595 -0
  27. package/public/llms/components/card-accordion.md +277 -0
  28. package/public/llms/components/card.md +985 -0
  29. package/public/llms/components/checkbox-group.md +193 -0
  30. package/public/llms/components/checkbox-tile.md +116 -0
  31. package/public/llms/components/checkbox.md +108 -0
  32. package/public/llms/components/combobox.md +360 -0
  33. package/public/llms/components/container.md +162 -0
  34. package/public/llms/components/currency-input.md +85 -0
  35. package/public/llms/components/date-input.md +90 -0
  36. package/public/llms/components/date-picker.md +159 -0
  37. package/public/llms/components/description-list.md +149 -0
  38. package/public/llms/components/detail-text.md +89 -0
  39. package/public/llms/components/divider.md +88 -0
  40. package/public/llms/components/em.md +43 -0
  41. package/public/llms/components/expandable-card.md +231 -0
  42. package/public/llms/components/flex.md +197 -0
  43. package/public/llms/components/grid.md +244 -0
  44. package/public/llms/components/heading.md +65 -0
  45. package/public/llms/components/helper-text.md +27 -0
  46. package/public/llms/components/highlight-banner.md +94 -0
  47. package/public/llms/components/icon-button.md +516 -0
  48. package/public/llms/components/icon-container.md +247 -0
  49. package/public/llms/components/inline-link.md +190 -0
  50. package/public/llms/components/label.md +28 -0
  51. package/public/llms/components/link.md +236 -0
  52. package/public/llms/components/list.md +715 -0
  53. package/public/llms/components/menu.md +270 -0
  54. package/public/llms/components/modal.md +328 -0
  55. package/public/llms/components/pagination.md +138 -0
  56. package/public/llms/components/password-input.md +93 -0
  57. package/public/llms/components/progress-bar.md +139 -0
  58. package/public/llms/components/progress-stepper.md +147 -0
  59. package/public/llms/components/radio-group.md +487 -0
  60. package/public/llms/components/search-input.md +132 -0
  61. package/public/llms/components/section-header.md +82 -0
  62. package/public/llms/components/select.md +148 -0
  63. package/public/llms/components/skeleton.md +282 -0
  64. package/public/llms/components/spinner.md +59 -0
  65. package/public/llms/components/strong.md +49 -0
  66. package/public/llms/components/switch.md +106 -0
  67. package/public/llms/components/table.md +230 -0
  68. package/public/llms/components/tabs.md +320 -0
  69. package/public/llms/components/text-area.md +141 -0
  70. package/public/llms/components/text-input.md +228 -0
  71. package/public/llms/components/toast.md +323 -0
  72. package/public/llms/components/toggle-button-card.md +513 -0
  73. package/public/llms/components/tooltip.md +188 -0
  74. package/public/llms/components/unstyled-icon-button.md +175 -0
  75. package/public/llms/components/validation-text.md +29 -0
  76. package/public/llms/components/verification-input.md +96 -0
  77. package/public/llms/docs/changelog.md +1430 -0
  78. package/public/llms/docs/common-props/align-self.md +90 -0
  79. package/public/llms/docs/common-props/border.md +308 -0
  80. package/public/llms/docs/common-props/colour.md +221 -0
  81. package/public/llms/docs/common-props/flex-items.md +91 -0
  82. package/public/llms/docs/common-props/gap.md +111 -0
  83. package/public/llms/docs/common-props/grid-items.md +96 -0
  84. package/public/llms/docs/common-props/margin.md +105 -0
  85. package/public/llms/docs/common-props/opacity.md +100 -0
  86. package/public/llms/docs/common-props/order.md +90 -0
  87. package/public/llms/docs/common-props/overflow.md +89 -0
  88. package/public/llms/docs/common-props/padding.md +102 -0
  89. package/public/llms/docs/common-props/position.md +92 -0
  90. package/public/llms/docs/common-props/size.md +93 -0
  91. package/public/llms/docs/common-props/spacing.md +97 -0
  92. package/public/llms/docs/common-props/text.md +35 -0
  93. package/public/llms/docs/common-props/z-index.md +88 -0
  94. package/public/llms/docs/design-tokens.md +72 -0
  95. package/public/llms/docs/getting-started.md +117 -0
  96. package/public/llms/docs/layout.md +135 -0
  97. package/public/llms/docs/migrating.md +302 -0
  98. package/public/llms/docs/responsive-design/breakpoints.md +119 -0
  99. package/public/llms/docs/responsive-design/media-queries.md +89 -0
  100. package/public/llms/docs/responsive-design/responsive-props.md +37 -0
  101. package/public/llms.txt +97 -0
  102. package/scripts/init-ai.js +142 -0
  103. package/styles.css +2 -2
  104. /package/dist/{chunk-JRVYOIXR.js.map → chunk-MIVYZGEV.js.map} +0 -0
@@ -0,0 +1,487 @@
1
+ # RadioGroup
2
+
3
+ `RadioGroup` provides an accessible way to group and control a set of `Radio`, `RadioTile` or `RadioCard` components, allowing the user to select one option from a set. The `RadioGroup` is responsible for handling the value, helper text, validation status and text, as well as determining the presentation and selection of the items in the list. Follows the [WAI-ARIA Radio Group Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/radio/) for radio groups not contained in a toolbar.
4
+
5
+ ```tsx
6
+ <Flex direction="column" gap="400">
7
+ <Flex direction="row" gap="200">
8
+ <RadioGroup {...args}>
9
+ <RadioTile value="england" label="England" />
10
+ <RadioTile value="wales" label="Wales" />
11
+ <RadioTile value="scotland" label="Scotland" />
12
+ <RadioTile value="northern-ireland" label="Northern Ireland" />
13
+ </RadioGroup>
14
+ <RadioGroup {...args}>
15
+ <Radio value="england" label="England" />
16
+ <Radio value="wales" label="Wales" />
17
+ <Radio value="scotland" label="Scotland" />
18
+ <Radio value="northern-ireland" label="Northern Ireland" />
19
+ </RadioGroup>
20
+ </Flex>
21
+ <RadioGroup
22
+ {...args}
23
+ label="Do you like living here?"
24
+ name="do-you-like-living-here"
25
+ direction="row"
26
+ >
27
+ <RadioTile value="y" label="Yes" image={<ThumbsUpSmallIcon />} />
28
+ <RadioTile value="n" label="No" image={<ThumbsDownSmallIcon />} />
29
+ </RadioGroup>
30
+ </Flex>
31
+ ```
32
+
33
+ - [Alternatives](#alternatives)
34
+ - [Usage](#usage)
35
+ - [Accessibility](#accessibility)
36
+ - [Keyboard interactions](#keyboard-interactions)
37
+ - [Custom label](#custom-label)
38
+ - [Helper text](#helper-text)
39
+ - [Validation](#validation)
40
+ - [Content width](#content-width)
41
+ - [Grid layout](#grid-layout)
42
+ - [RadioTile layout](#radiotile-layout)
43
+ - [Controlled](#controlled)
44
+ - [Radio & RadioTile Image](#radio--radiotile-image)
45
+ - [RadioCard](#radiocard)
46
+ - [API](#api)
47
+
48
+ ## Alternatives
49
+
50
+ - `CheckboxGroup`: For multi-select.
51
+
52
+ ## Usage
53
+
54
+ `RadioGroup` is intended for use with the `RadioTile`, `RadioCard` and `Radio` components.
55
+
56
+ - `RadioTile` is the most common radio button used within the `RadioGroup`, and offers a simple way to present grouped options.
57
+ - `RadioCard` is for instances when you have options that are either the main focus of your UI or would benefit from additional explanation.
58
+ - `Radio` will not often be used, as `RadioTile` is preferred.
59
+
60
+ ## Accessibility
61
+
62
+ The necessary aria props, such as `aria-labelledby`, `aria-describedby` and
63
+ `aria-errormessage` are handled internally, however when it is necessary for
64
+ the `RadioGroup` to be labelled by another element or even not to have a visual
65
+ label, either `aria-label` or `aria-labelledby` can be provided.
66
+
67
+ The `Radio` and `RadioTile` are, by default, appropriately labelled when using
68
+ the `label` props, if you do not provide a label, you must specify an
69
+ `aria-label` or `aria-labelledby` for accessibility.
70
+
71
+ ## Keyboard interactions
72
+
73
+ <Flex direction="column" gap="200" className="sb-unstyled">
74
+ <Flex>
75
+ <Box width="300px">
76
+ <BodyText as="span" weight="bold">
77
+ Key
78
+ </BodyText>
79
+ </Box>
80
+ <BodyText as="span" weight="bold">
81
+ Description
82
+ </BodyText>
83
+ </Flex>
84
+ <Divider />
85
+ {[
86
+ {
87
+ key: 'Tab',
88
+ description:
89
+ 'Moves focus to either the checked radio item or the first radio item in the group.',
90
+ },
91
+ {
92
+ key: 'Shift+Tab',
93
+ description:
94
+ 'Moves focus to either the checked radio item or the last radio item in the group.',
95
+ },
96
+ {
97
+ key: 'Space',
98
+ description: 'When focus is on an unchecked radio item, checks it.',
99
+ },
100
+ {
101
+ key: 'Arrow Down / Arrow Right',
102
+ description: 'Moves focus and checks the next radio item in the group.',
103
+ },
104
+ {
105
+ key: 'Arrow Up / Arrow Left',
106
+ description: 'Moves focus and checks the previous radio item in the group.',
107
+ },
108
+ ].map((kbi, i) => (
109
+ <>
110
+ <Flex>
111
+ <Box width="300px">
112
+ <kbd>{kbi.key}</kbd>
113
+ </Box>
114
+ <BodyText as="span">{kbi.description}</BodyText>
115
+ </Flex>
116
+ {i < 4 ? <Divider /> : null}
117
+ </>
118
+ ))}
119
+ </Flex>
120
+
121
+ ## Custom label
122
+
123
+ You can set a custom label either by passing in a component to the label prop,
124
+ or by properly labelling the `RadioGroup` with the relevant text element.
125
+
126
+ ```tsx
127
+ <Flex gap="600" direction="column">
128
+ <RadioGroup
129
+ {...args}
130
+ label={<Heading as="h2">Where do you live?</Heading>}
131
+ name="where-do-you-live"
132
+ >
133
+ <RadioTile value="england" label="England" />
134
+ <RadioTile value="wales" label="Wales" />
135
+ <RadioTile value="scotland" label="Scotland" />
136
+ <RadioTile value="northern-ireland" label="Northern Ireland" />
137
+ </RadioGroup>
138
+
139
+ <Flex direction="column" gap="100">
140
+ <Heading as="h2" id="where-do-you-live">
141
+ Where do you live?
142
+ </Heading>
143
+ <RadioGroup {...args} aria-labelledby="where-do-you-live">
144
+ <RadioTile value="england" label="England" />
145
+ <RadioTile value="wales" label="Wales" />
146
+ <RadioTile value="scotland" label="Scotland" />
147
+ <RadioTile value="northern-ireland" label="Northern Ireland" />
148
+ </RadioGroup>
149
+ </Flex>
150
+ </Flex>
151
+ ```
152
+
153
+ ## Helper text
154
+
155
+ `RadioGroup` can display a secondary message as a helper text. If displayed then
156
+ child radio items will not be display their own helper text.
157
+
158
+ ## Validation
159
+
160
+ In general, radio buttons should have a value selected by default. If this is
161
+ not the case, you can display an error if no value is selected when the form is
162
+ submitted.
163
+
164
+ ```tsx
165
+ <RadioGroup
166
+ {...args}
167
+ value={selected}
168
+ onValueChange={setSelected}
169
+ validationStatus={selected ? undefined : 'invalid'}
170
+ >
171
+ <RadioTile value="1" label="Bear" />
172
+ <RadioTile value="2" label="Koala" />
173
+ <RadioTile value="3" label="Wolf" />
174
+ <RadioTile value="4" label="Horse" />
175
+ </RadioGroup>
176
+ ```
177
+
178
+ By default, the validation text is placed above the radio items. Use `validationPlacement="bottom"` to display it below instead.
179
+
180
+ ```tsx
181
+ <Flex direction="column" gap="400">
182
+ <RadioGroup
183
+ label="Validation top (default)"
184
+ validationStatus="invalid"
185
+ validationText="Please select an option"
186
+ validationPlacement="top"
187
+ name="validation-placement-top"
188
+ contentWidth="fit-content"
189
+ >
190
+ <RadioTile value="1" label="Bear" />
191
+ <RadioTile value="2" label="Koala" />
192
+ <RadioTile value="3" label="Wolf" />
193
+ </RadioGroup>
194
+ <RadioGroup
195
+ label="Validation bottom"
196
+ validationStatus="invalid"
197
+ validationText="Please select an option"
198
+ validationPlacement="bottom"
199
+ name="validation-placement-bottom"
200
+ contentWidth="fit-content"
201
+ >
202
+ <RadioTile value="1" label="Bear" />
203
+ <RadioTile value="2" label="Koala" />
204
+ <RadioTile value="3" label="Wolf" />
205
+ </RadioGroup>
206
+ </Flex>
207
+ ```
208
+
209
+ ## Content width
210
+
211
+ The width of the `RadioGroup` should be set by the parent layout, however it is
212
+ possible to independently set the width of the children using `contentWidth`
213
+ prop.
214
+
215
+ By default it will set the width of the children to fit their content, however
216
+ you can set it to a specific width, or to `100%` to take up the full width of
217
+ the `RadioGroup`.
218
+
219
+ This is a responsive property, so you are able to set different widths for
220
+ different breakpoints.
221
+
222
+ ## Grid layout
223
+
224
+ You can compose the `RadioGroup` with the `Grid` component if you need to
225
+ present a specific grid layout.
226
+
227
+ ```tsx
228
+ <RadioGroup {...args}>
229
+ <Grid columns="3" gap="150">
230
+ <RadioTile value="1" label="One" />
231
+ <RadioTile value="2" label="Two" />
232
+ <RadioTile value="3" label="Three" />
233
+ <RadioTile value="4" label="Four" />
234
+ <RadioTile value="5" label="Five" />
235
+ <RadioTile value="6" label="Six" />
236
+ </Grid>
237
+ </RadioGroup>
238
+ ```
239
+
240
+ ## RadioTile layout
241
+
242
+ `RadioTile` components will, by default, fit their content. However they have
243
+ access to all flex item props, so you can set them to grow and fill the
244
+ available space, or to have a specific width.
245
+
246
+ ```tsx
247
+ <RadioGroup direction="row" label="Numbers">
248
+ <RadioTile value="1" label="One" flex="1" />
249
+ <RadioTile value="2" label="Two" flex="1" />
250
+ </RadioGroup>
251
+ ```
252
+
253
+ ## Controlled
254
+
255
+ A controlled value can be provided using the value prop, which accepts a value
256
+ corresponding with the value prop of each `Radio`. The onChange event is fired
257
+ when the user selects a `Radio`.
258
+
259
+ ```
260
+ const options = ['Bear', 'Koala', 'Wolf', 'Horse'];
261
+ const [selected, setSelected] = useState(options[0]);
262
+
263
+ [...]
264
+
265
+ <RadioGroup
266
+ {...args}
267
+ value={selected}
268
+ onValueChange={setSelected}
269
+ helperText={`Your favourite animal is a ${selected}`}
270
+ >
271
+ {options.map(animal => (
272
+ <RadioTile key={animal} value={animal} label={animal} />
273
+ ))}
274
+ </RadioGroup>
275
+ ```
276
+
277
+ ```tsx
278
+ <RadioGroup
279
+ {...args}
280
+ value={selected}
281
+ onValueChange={setSelected}
282
+ helperText={`Your favourite animal is a ${selected}`}
283
+ >
284
+ {options.map(animal => (
285
+ <RadioTile key={animal} value={animal} label={animal} />
286
+ ))}
287
+ </RadioGroup>
288
+ ```
289
+
290
+ ## Radio & RadioTile Image
291
+
292
+ The `Radio` & `RadioTile` components can display an icon or image between the indicator and label.
293
+
294
+ ```tsx
295
+ <Radio value="2" label="Two" helperText="The number two" image={<CashbackCardMediumIcon />} />
296
+ ```
297
+
298
+ ```tsx
299
+ <RadioGroup label="How would you like to pay?">
300
+ <RadioTile
301
+ value="mastercard"
302
+ label="Mastercard"
303
+ helperText=""
304
+ image={<img src={mastercard} width={40} height={24} alt="" />}
305
+ />
306
+ <RadioTile
307
+ value="visa"
308
+ label="Visa"
309
+ helperText=""
310
+ image={<img src={visa} width={40} height={24} alt="" />}
311
+ />
312
+ <RadioTile value="cash" label="Cash" image={<MoneyMediumIcon />} />
313
+ </RadioGroup>
314
+ ```
315
+
316
+ **If you are using an `img` element, remember to include a null alt tag
317
+ (`alt=""` ) so the image is ignored by assistive technologies.**
318
+
319
+ ```tsx
320
+ <RadioTile
321
+ value="2"
322
+ label="Two"
323
+ helperText="The number two"
324
+ image={<img src="https://help.uw.co.uk/images/iPhone.svg" width={25} alt="" />}
325
+ />
326
+ ```
327
+
328
+ ## RadioCard
329
+
330
+ You can use the `RadioCard` component to present additional content in a more
331
+ card-like visual style. Unlike `RadioTile`, this component will accept
332
+ children.
333
+
334
+ ```tsx
335
+ <RadioCard value="1" label="Debit card payment">
336
+ <Flex asChild gap="100" direction="column">
337
+ <ul role="list">
338
+ <li>• Unlimited free top-ups</li>
339
+ <li>• Instant withdrawals</li>
340
+ <li>• Extra layer of security</li>
341
+ </ul>
342
+ </Flex>
343
+ </RadioCard>
344
+ ```
345
+
346
+ ```tsx
347
+ <Flex>
348
+ <RadioGroup
349
+ defaultValue="1"
350
+ direction="column"
351
+ contentWidth="350px"
352
+ label={<Heading>Payment options</Heading>}
353
+ >
354
+ <Flex direction="column">
355
+ <Flex right="24px" position="relative" justifyContent="end">
356
+ <Badge flatBase colorScheme="positive" variant="emphasis" size="sm">
357
+ Recommended
358
+ </Badge>
359
+ </Flex>
360
+
361
+ <RadioCard value="1" label="Debit card payment" image={<CashbackCardMediumIcon />}>
362
+ <Flex asChild gap="100" direction="column">
363
+ <ul role="list">
364
+ <Box asChild marginLeft="100">
365
+ <li>• Unlimited free top-ups</li>
366
+ </Box>
367
+ <Box asChild marginLeft="100">
368
+ <li>• Instant withdrawals</li>
369
+ </Box>
370
+ <Box asChild marginLeft="100">
371
+ <li>• Extra layer of security</li>
372
+ </Box>
373
+ </ul>
374
+ </Flex>
375
+ </RadioCard>
376
+ </Flex>
377
+
378
+ <RadioCard value="2" label="Instant bank transfer" image={<BankMediumIcon />}>
379
+ <Flex asChild gap="100" direction="column">
380
+ <ul role="list">
381
+ <Box asChild marginLeft="100">
382
+ <li>• 5 free top-ups per month</li>
383
+ </Box>
384
+ <Box asChild marginLeft="100">
385
+ <li>• £0.35 per additional top-up</li>
386
+ </Box>
387
+ </ul>
388
+ </Flex>
389
+ </RadioCard>
390
+ </RadioGroup>
391
+ </Flex>
392
+ ```
393
+
394
+ ## API
395
+
396
+ This component is based on the `fieldset` element and supports the following common props:
397
+
398
+ - Margin
399
+
400
+ | Prop | Type | Default | Description |
401
+ | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
402
+ | `label` | `ReactNode` | — | The label for the formfield group. This should contain the question being answered by the formfield group. If you don't include a label you need to ensure you use the `aria-label` or `aria-labelledby` prop to properly associate a label with the formfield group. |
403
+ | `defaultValue` | `string` | — | |
404
+ | `asChild` | `boolean` | — | |
405
+ | `name` | `string` | — | |
406
+ | `required` | `boolean` | — | |
407
+ | `disabled` | `boolean` | — | |
408
+ | `loop` | `boolean` | — | |
409
+ | `value` | `string \| null` | — | |
410
+ | `onValueChange` | `((value: string) => void)` | — | |
411
+ | `labelVariant` | `"body" \| "heading"` | — | Set the label variant |
412
+ | `helperText` | `ReactNode` | — | Helper text for the formfield group. Provides a hint such as specific requirements for what to choose. When displayed, child components should not display their own `helperText`. |
413
+ | `validationText` | `ReactNode` | — | |
414
+ | `validationStatus` | `"valid" \| "invalid"` | — | |
415
+ | `validationPlacement` | `"top" \| "bottom"` | — | |
416
+ | `margin` | `Responsive<"0" \| "auto" \| `var(--h-${string})` \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">` | — | |
417
+ | `marginTop` | `Responsive<"0" \| "auto" \| `var(--h-${string})` \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">` | — | |
418
+ | `marginRight` | `Responsive<"0" \| "auto" \| `var(--h-${string})` \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">` | — | |
419
+ | `marginBottom` | `Responsive<"0" \| "auto" \| `var(--h-${string})` \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">` | — | |
420
+ | `marginLeft` | `Responsive<"0" \| "auto" \| `var(--h-${string})` \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">` | — | |
421
+ | `marginX` | `Responsive<"0" \| "auto" \| `var(--h-${string})` \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">` | — | |
422
+ | `marginY` | `Responsive<"0" \| "auto" \| `var(--h-${string})` \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">` | — | |
423
+ | `direction` | `Responsive<"row" \| "column" \| "row-reverse" \| "column-reverse">` | `column` | |
424
+ | `contentWidth` | `Responsive<string>` | — | Set the container width of the RadioGroup children, independent to the width of the parent RadioGroup. |
425
+
426
+ ### Radio API
427
+
428
+ This component is based on the `button` element and supports the following common props:
429
+
430
+ - Margin
431
+
432
+ | Prop | Type | Default | Description |
433
+ | ----------------- | ------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
434
+ | `label` | `ReactNode` | — | The label for the Radio. If not using please properly associate the Radio with a label using the `aria-label` or `aria-labelledby` props. |
435
+ | `image` | `ReactNode` | — | Optional image to show between the radio indicator and label. |
436
+ | `value` | `string` | — | |
437
+ | `asChild` | `boolean` | — | |
438
+ | `checked` | `boolean` | — | |
439
+ | `required` | `boolean` | — | |
440
+ | `labelFontWeight` | `"regular" \| "semibold"` | — | |
441
+ | `helperText` | `ReactNode` | — | Helper text for the Radio. Will not display if the radio group has `helperText` set. |
442
+
443
+ ### RadioTile API
444
+
445
+ This component is based on the `button` element and supports the following common props:
446
+
447
+ - Margin
448
+ - Flex item
449
+
450
+ | Prop | Type | Default | Description |
451
+ | ----------------- | ------------------------- | ------- | ------------------------------------------------------------------------------------ |
452
+ | `label` | `ReactNode` | — | |
453
+ | `image` | `ReactNode` | — | Optional image to show between the radio indicator and label. |
454
+ | `value` | `string` | — | |
455
+ | `asChild` | `boolean` | — | |
456
+ | `checked` | `boolean` | — | |
457
+ | `required` | `boolean` | — | |
458
+ | `labelFontWeight` | `"regular" \| "semibold"` | — | |
459
+ | `helperText` | `ReactNode` | — | Helper text for the Radio. Will not display if the radio group has `helperText` set. |
460
+ | `badge` | `ReactNode` | — | |
461
+ | `flex` | `Responsive<string>` | — | |
462
+ | `flexBasis` | `Responsive<string>` | — | |
463
+ | `flexShrink` | `Responsive<string>` | — | |
464
+ | `flexGrow` | `Responsive<string>` | — | |
465
+
466
+ ### RadioCard API
467
+
468
+ This component is based on the `button` element and supports the following common props:
469
+
470
+ - Margin
471
+
472
+ | Prop | Type | Default | Description |
473
+ | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
474
+ | `label` | `ReactNode` | — | The label for the Radio. If not using please properly associate the Radio with a label using the `aria-label` or `aria-labelledby` props. |
475
+ | `image` | `ReactNode` | — | Optional image to show between the radio indicator and label. |
476
+ | `value` | `string` | — | |
477
+ | `asChild` | `boolean` | — | |
478
+ | `checked` | `boolean` | — | |
479
+ | `required` | `boolean` | — | |
480
+ | `labelFontWeight` | `"regular" \| "semibold"` | — | |
481
+ | `margin` | `Responsive<"0" \| "auto" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
482
+ | `marginTop` | `Responsive<"0" \| "auto" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
483
+ | `marginRight` | `Responsive<"0" \| "auto" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
484
+ | `marginBottom` | `Responsive<"0" \| "auto" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
485
+ | `marginLeft` | `Responsive<"0" \| "auto" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
486
+ | `marginX` | `Responsive<"0" \| "auto" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
487
+ | `marginY` | `Responsive<"0" \| "auto" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
@@ -0,0 +1,132 @@
1
+ # SearchInput
2
+
3
+ `SearchInput` allows users to enter a specific keyword or phrase and obtain results related to the context in which it is placed.
4
+
5
+ - [Alternatives](#alternatives)
6
+ - [Accessibility](#accessibility)
7
+ - [Label](#label)
8
+ - [Clear](#clear)
9
+ - [Loading](#loading)
10
+ - [Usage with a button](#usage-with-a-button)
11
+ - [API](#api)
12
+
13
+ ```tsx
14
+ <SearchInput
15
+ value={value}
16
+ onChange={(event: ChangeEvent<HTMLInputElement>) => setValue(event.target.value)}
17
+ onClear={() => setValue('')}
18
+ id="search-input-playground"
19
+ {...args}
20
+ />
21
+ ```
22
+
23
+ ## Alternatives
24
+
25
+ - TextInput - For text
26
+ - PasswordInput - For passwords
27
+ - CurrencyInput - For money
28
+
29
+ ## Accessibility
30
+
31
+ Wrap `SearchInput` in a container element with `role="search"` to increase
32
+ their discoverability to assistive technologies. This parent element should
33
+ encompass all of the elements that together form the search feature.
34
+
35
+ Be aware though that too many landmark roles such as this can create
36
+ unnecessary 'noise' for screen reader users, and should be used sparingly on a
37
+ page.
38
+
39
+ You can learn more about this at the [the MDN docs](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Roles/search_role).
40
+
41
+ ```tsx
42
+ <form role="search">
43
+ <SearchInput />
44
+ </form>
45
+ ```
46
+
47
+ ## Label
48
+
49
+ A label is required. By default it will be visually hidden, but still available
50
+ to screen readers. You can change this by setting `hideLabel` to `false`.
51
+
52
+ ## Clear
53
+
54
+ You can pass a function to the `onClear` prop to clear the input. When there is
55
+ a value the `clear` button will be present, and clicking it will call the
56
+ `onClear` function. This should be used only to clear the value of the input.
57
+
58
+ ## Loading
59
+
60
+ You can set the `SearchInput` into a loading state, where it will disable the
61
+ input and display a loading spinner.
62
+
63
+ ```tsx
64
+ <SearchInput
65
+ {...args}
66
+ value={value}
67
+ onChange={(event: ChangeEvent<HTMLInputElement>) => setValue(event.target.value)}
68
+ onClear={() => setValue('')}
69
+ loading
70
+ />
71
+ ```
72
+
73
+ ## Usage with a button
74
+
75
+ On desktop, and tablet the `SearchInput` must be followed by a button which triggers the
76
+ containing form's search action. Results should be shown after the user
77
+ triggers the search action.
78
+
79
+ On mobile, no button is required, as the search can be triggered by
80
+ tapping on the search button on the keyboard or dynamically while typing. On
81
+ older mobile browsers, the enter key may not explicitly display the word
82
+ _Search_ but will still trigger the containing form's search action. Results
83
+ should be shown dynamically as the user types or after tapping on the search
84
+ button on the keyboard.
85
+
86
+ You can achieve this UI using responsive props.
87
+
88
+ ```tsx
89
+ <Flex asChild gap="50" width={{ mobile: '100%', tablet: '500px' }}>
90
+ <form role="search" action={search}>
91
+ <SearchInput
92
+ label="Search"
93
+ value={value}
94
+ placeholder="What do you need help with?"
95
+ onChange={(event: React.ChangeEvent<HTMLInputElement>) => setValue(event.target.value)}
96
+ onClear={() => setValue('')}
97
+ />
98
+ <Box display={{ mobile: 'none', tablet: 'block' }}>
99
+ <Button variant="solid" colorScheme="yellow">
100
+ Search
101
+ </Button>
102
+ </Box>
103
+ </form>
104
+ </Flex>
105
+ ```
106
+
107
+ ## API
108
+
109
+ This component is based on the `TextInput` component and supports the following common props:
110
+
111
+ - Margin
112
+
113
+ | Prop | Type | Default | Description |
114
+ | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | --------------------------------------------------------------------------- |
115
+ | `label` | `string` | — | The label for the form field, describing its purpose. |
116
+ | `defaultValue` | `string \| number` | — | The initial value of the input when rendered. |
117
+ | `value` | `string \| number` | — | The controlled value of the input. Must be used with an `onChange` handler. |
118
+ | `labelId` | `string` | — | |
119
+ | `helperTextId` | `string` | — | |
120
+ | `validationTextId` | `string` | — | |
121
+ | `hideLabel` | `boolean` | `true` | Visually hide the label. |
122
+ | `labelVariant` | `"body" \| "heading"` | — | Change the label variant |
123
+ | `helperText` | `string` | — | Optional helper text to provide additional context or instructions. |
124
+ | `margin` | `Responsive<"auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
125
+ | `marginTop` | `Responsive<"auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
126
+ | `marginRight` | `Responsive<"auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
127
+ | `marginBottom` | `Responsive<"auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
128
+ | `marginLeft` | `Responsive<"auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
129
+ | `marginX` | `Responsive<"auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
130
+ | `marginY` | `Responsive<"auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
131
+ | `onClear` | `(() => void)` | — | |
132
+ | `loading` | `boolean` | — | |