@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,360 @@
1
+ # Combobox
2
+
3
+ `Combobox` allows users to both type to filter results and select from a predefined list.
4
+
5
+ - [Usage](#usage)
6
+ - [Trigger only on type](#trigger-only-on-type)
7
+ - [No options found](#no-options-found)
8
+ - [Status text](#status-text)
9
+ - [useComboboxFilter](#usecomboboxfilter)
10
+ - [Virtualised](#virtualised)
11
+ - [API](#api)
12
+
13
+ ```tsx
14
+ <Combobox {...args} items={fruits} />
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ Pass your array of options to the `items` prop, these will be rendered using
20
+ the `ComboboxItem` component.
21
+
22
+ You can use `ComboboxItem` yourself if you need more control over the rendered
23
+ option content.
24
+
25
+ ```tsx
26
+ const fruits = ['Apple', 'Banana', 'Orange'];
27
+
28
+ [...]
29
+
30
+
31
+ <Combobox>
32
+ {fruits.map(fruit => (
33
+ <ComboboxItem key={fruit} value={fruit}>
34
+ {fruit}
35
+ </ComboboxItem>
36
+ ))}
37
+ </Combobox>
38
+ ```
39
+
40
+ ## Trigger only on type
41
+
42
+ By default the dropdown will open when the input is clicked. You can change
43
+ this behaviour, so that the dropdown is only opened when a user starts typing,
44
+ with the `triggerOnlyOnType` prop. This will also remove the trigger icon button.
45
+
46
+ - Set `triggerOnlyOnType` to `false` where there is a predefined list of options for a user to choose.
47
+ - Set `triggerOnlyOnType` to `true` where the user is required to type before surfacing options. For example, postcode or address lookups.
48
+
49
+ ## No options found
50
+
51
+ If a user searches and no options are found, a disabled option will appear in
52
+ the dropdown to communicate this. You can customise this using the
53
+ `noOptionsFoundText` prop.
54
+
55
+ This requires that you pass options via the `items` prop. If you are rendering
56
+ the options yourself, using `ComboboxItem`, you can use the `ComboboxEmpty`
57
+ component to display when there are no options available.
58
+
59
+ ## Status text
60
+
61
+ Use the `statusText` prop to display a status message whose content changes are
62
+ announced politely to screen readers. Useful for conveying the status of an
63
+ asynchronously loaded list.
64
+
65
+ ## useComboboxFilter
66
+
67
+ The `useComboboxFilter` hook provides robust string matching using `Intl.Collator`.
68
+ It returns three filter functions — `contains`, `startsWith`, and `endsWith` —
69
+ that can be passed to the `filter` prop on `Combobox`.
70
+
71
+ When using `useComboboxFilter`, pass the `items` prop to provide the full list
72
+ of options to the `Combobox`, and pass the chosen filter function to the `filter`
73
+ prop. The `Combobox` will handle filtering the items internally.
74
+
75
+ ```tsx
76
+ import { Combobox, useComboboxFilter } from '@utilitywarehouse/hearth-react';
77
+
78
+ const fruits = ['Apple', 'Banana', 'Cherry', 'Grape', 'Mango', 'Orange'];
79
+
80
+ const [value, setValue] = React.useState<string | null>(null);
81
+ const { contains } = useComboboxFilter({ value });
82
+
83
+ <Combobox label="Fruit" items={fruits} filter={contains} value={value} onValueChange={setValue} />;
84
+ ```
85
+
86
+ ```tsx
87
+ <Combobox
88
+ {...args}
89
+ label="Fruit (contains)"
90
+ items={fruits}
91
+ filter={contains}
92
+ value={value}
93
+ onValueChange={v => setValue(v as string | null)}
94
+ />
95
+ ```
96
+
97
+ The `startsWith` and `endsWith` functions work the same way but match only from
98
+ the beginning or end of each item's label respectively.
99
+
100
+ ```tsx
101
+ <Combobox
102
+ {...args}
103
+ label="Fruit (startsWith)"
104
+ items={fruits}
105
+ filter={startsWith}
106
+ value={value}
107
+ onValueChange={v => setValue(v as string | null)}
108
+ />
109
+ ```
110
+
111
+ For more advanced scenarios, such as virtualised lists where you need to manage
112
+ the filtered items yourself, you can call the filter functions directly:
113
+
114
+ ```tsx
115
+ const { contains } = useComboboxFilter({ value });
116
+
117
+ const filteredItems = React.useMemo(() => {
118
+ return allItems.filter(item => contains(item, searchValue, getItemLabel));
119
+ }, [contains, searchValue]);
120
+ ```
121
+
122
+ ## Virtualised
123
+
124
+ Efficiently handle large datasets using a virtualization library like `@tanstack/react-virtual`.
125
+
126
+ ```tsx
127
+ <Combobox
128
+ virtualized
129
+ label="Search 10,000 items"
130
+ items={virtualizedItems}
131
+ filteredItems={filteredItems}
132
+ open={open}
133
+ onOpenChange={setOpen}
134
+ inputValue={searchValue}
135
+ onInputValueChange={setSearchValue}
136
+ value={value}
137
+ onValueChange={setValue}
138
+ itemToStringLabel={getItemLabel}
139
+ onItemHighlighted={(item: unknown, { reason, index }: { reason: string; index: number }) => {
140
+ if (!item) {
141
+ return;
142
+ }
143
+
144
+ const isStart = index === 0;
145
+ const isEnd = index === filteredItems.length - 1;
146
+ const shouldScroll = reason === 'none' || (reason === 'keyboard' && (isStart || isEnd));
147
+
148
+ if (shouldScroll) {
149
+ queueMicrotask(() => {
150
+ virtualizer.scrollToIndex(index, { align: isEnd ? 'start' : 'end' });
151
+ });
152
+ }
153
+ }}
154
+ >
155
+ {filteredItems.length > 0 && (
156
+ <div
157
+ role="presentation"
158
+ ref={handleScrollElementRef}
159
+ style={{
160
+ height: `min(22rem, ${totalSize}px)`,
161
+ width: '100%',
162
+ }}
163
+ >
164
+ <div role="presentation" style={{ height: totalSize }}>
165
+ {virtualizer.getVirtualItems().map(virtualItem => {
166
+ const item = filteredItems[virtualItem.index];
167
+ if (!item) {
168
+ return null;
169
+ }
170
+
171
+ return (
172
+ <ComboboxItem
173
+ key={virtualItem.key}
174
+ index={virtualItem.index}
175
+ data-index={virtualItem.index}
176
+ ref={virtualizer.measureElement}
177
+ value={item}
178
+ aria-setsize={filteredItems.length}
179
+ aria-posinset={virtualItem.index + 1}
180
+ >
181
+ {item.name}
182
+ </ComboboxItem>
183
+ );
184
+ })}
185
+ </div>
186
+ </div>
187
+ )}
188
+ </Combobox>
189
+ ```
190
+
191
+ ```tsx
192
+ import { Combobox, ComboboxItem, useComboboxFilter } from '@utilitywarehouse/hearth-react';
193
+ import { useVirtualizer } from '@tanstack/react-virtual';
194
+
195
+ [...]
196
+
197
+
198
+ const [open, setOpen] = React.useState(false);
199
+ const [searchValue, setSearchValue] = React.useState('');
200
+ const [value, setValue] = React.useState<VirtualizedItem | null>(null);
201
+
202
+ const deferredSearchValue = React.useDeferredValue(searchValue);
203
+
204
+ const scrollElementRef = React.useRef<HTMLDivElement | null>(null);
205
+
206
+ const { contains } = useComboboxFilter({ value });
207
+
208
+ const resolvedSearchValue =
209
+ searchValue === '' || deferredSearchValue === '' ? searchValue : deferredSearchValue;
210
+
211
+ const filteredItems = React.useMemo(() => {
212
+ return virtualizedItems.filter(item => contains(item, resolvedSearchValue, getItemLabel));
213
+ }, [contains, resolvedSearchValue]);
214
+
215
+ const virtualizer = useVirtualizer({
216
+ enabled: open,
217
+ count: filteredItems.length,
218
+ getScrollElement: () => scrollElementRef.current,
219
+ estimateSize: () => 32,
220
+ overscan: 20,
221
+ });
222
+
223
+ const handleScrollElementRef = React.useCallback(
224
+ (element: HTMLDivElement | null) => {
225
+ scrollElementRef.current = element;
226
+ if (element) {
227
+ virtualizer.measure();
228
+ }
229
+ },
230
+ [virtualizer]
231
+ );
232
+
233
+ const totalSize = virtualizer.getTotalSize();
234
+
235
+ return (
236
+ <Combobox
237
+ virtualized
238
+ label="Search 10,000 items"
239
+ items={virtualizedItems}
240
+ filteredItems={filteredItems}
241
+ open={open}
242
+ onOpenChange={setOpen}
243
+ inputValue={searchValue}
244
+ onInputValueChange={setSearchValue}
245
+ value={value}
246
+ onValueChange={setValue}
247
+ itemToStringLabel={getItemLabel}
248
+ onItemHighlighted={(item: any, { reason, index }: any) => {
249
+ if (!item) {
250
+ return;
251
+ }
252
+
253
+ const isStart = index === 0;
254
+ const isEnd = index === filteredItems.length - 1;
255
+ const shouldScroll = reason === 'none' || (reason === 'keyboard' && (isStart || isEnd));
256
+
257
+ if (shouldScroll) {
258
+ queueMicrotask(() => {
259
+ virtualizer.scrollToIndex(index, { align: isEnd ? 'start' : 'end' });
260
+ });
261
+ }
262
+ }}
263
+ >
264
+ {filteredItems.length > 0 && (
265
+ <div
266
+ role="presentation"
267
+ ref={handleScrollElementRef}
268
+ style={{
269
+ height: `min(22rem, ${totalSize}px)`,
270
+ width: '100%',
271
+ }}
272
+ >
273
+ <div role="presentation" style={{ height: totalSize }}>
274
+ {virtualizer.getVirtualItems().map(virtualItem => {
275
+ const item = filteredItems[virtualItem.index];
276
+ if (!item) {
277
+ return null;
278
+ }
279
+
280
+ return (
281
+ <ComboboxItem
282
+ key={virtualItem.key}
283
+ index={virtualItem.index}
284
+ data-index={virtualItem.index}
285
+ ref={virtualizer.measureElement}
286
+ value={item}
287
+ aria-setsize={filteredItems.length}
288
+ aria-posinset={virtualItem.index + 1}
289
+ >
290
+ {item.name}
291
+ </ComboboxItem>
292
+ );
293
+ })}
294
+ </div>
295
+ </div>
296
+ )}
297
+ </Combobox>
298
+ )
299
+ ```
300
+
301
+ ## API
302
+
303
+ This component is based on the [Base UI Combobox](https://base-ui.com/react/components/combobox#) and supports the following common props:
304
+
305
+ - Margin
306
+
307
+ | Prop | Type | Default | Description |
308
+ | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
309
+ | `triggerOnlyOnType` | `boolean` | — | |
310
+ | `noOptionsFoundText` | `string` | — | |
311
+ | `statusText` | `string` | — | Displays a status message whose content changes are announced politely to screen readers. Useful for conveying the status of an asynchronously loaded list. |
312
+ | `loading` | `boolean` | — | Displays a loading indicator in the input field to show that options are being fetched or updated asynchronously. |
313
+ | `autoComplete` | `string` | — | Provides a hint to the browser for autofill. @see https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/autocomplete |
314
+ | `itemToStringLabel` | `((itemValue: Value) => string)` | — | When the item values are objects (`<Combobox.Item value={object}>`), this function converts the object value to a string representation for display in the input. If the shape of the object is `{ value, label }`, the label will be used automatically without needing to specify this prop. |
315
+ | `itemToStringValue` | `((itemValue: Value) => string)` | — | When the item values are objects (`<Combobox.Item value={object}>`), this function converts the object value to a string representation for form submission. If the shape of the object is `{ value, label }`, the value will be used automatically without needing to specify this prop. |
316
+ | `isItemEqualToValue` | `((itemValue: Value, value: Value) => boolean)` | — | Custom comparison logic used to determine if a combobox item value matches the current selected value. Useful when item values are objects without matching referentially. Defaults to `Object.is` comparison. |
317
+ | `onOpenChange` | `((open: boolean, eventDetails: ChangeEventDetails) => void)` | — | Event handler called when the popup is opened or closed. |
318
+ | `onInputValueChange` | `((inputValue: string, eventDetails: ChangeEventDetails) => void)` | — | Event handler called when the input value changes. |
319
+ | `name` | `string` | — | Identifies the field when a form is submitted. |
320
+ | `form` | `string` | — | Identifies the form that owns the internal input. Useful when the combobox is rendered outside the form. |
321
+ | `id` | `string` | — | The id of the component. |
322
+ | `required` | `boolean` | `false` | Whether the user must choose a value before submitting a form. |
323
+ | `readOnly` | `boolean` | `false` | Whether the user should be unable to choose a different option from the popup. |
324
+ | `disabled` | `boolean` | `false` | Whether the component should ignore user interaction. |
325
+ | `defaultOpen` | `boolean` | `false` | Whether the popup is initially open. To render a controlled popup, use the `open` prop instead. |
326
+ | `open` | `boolean` | — | Whether the popup is currently open. Use when controlled. |
327
+ | `onOpenChangeComplete` | `((open: boolean) => void)` | — | Event handler called after any animations complete when the popup is opened or closed. |
328
+ | `loopFocus` | `boolean` | `true` | Whether to loop keyboard focus back to the input when the end of the list is reached while using the arrow keys. The first item can then be reached by pressing <kbd>ArrowDown</kbd> again from the input, or the last item can be reached by pressing <kbd>ArrowUp</kbd> from the input. The input is always included in the focus loop per [ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/). When disabled, focus does not move when on the last element and the user presses <kbd>ArrowDown</kbd>, or when on the first element and the user presses <kbd>ArrowUp</kbd>. |
329
+ | `inputValue` | `string \| number \| readonly string[]` | — | The input value of the combobox. Use when controlled. |
330
+ | `defaultInputValue` | `string \| number \| readonly string[]` | — | The uncontrolled input value when initially rendered. To render a controlled input, use the `inputValue` prop instead. |
331
+ | `inputRef` | `Ref<HTMLInputElement>` | — | A ref to the hidden input element. |
332
+ | `grid` | `boolean` | `false` | Whether list items are presented in a grid layout. When enabled, arrow keys navigate across rows and columns inferred from DOM rows. |
333
+ | `items` | `readonly any[] \| readonly Group<any>[]` | — | The items to be displayed in the list. Can be either a flat array of items or an array of groups with items. |
334
+ | `filteredItems` | `readonly any[] \| readonly Group<any>[]` | — | Filtered items to display in the list. When provided, the list will use these items instead of filtering the `items` prop internally. Use when you want to control filtering logic externally with the `useFilter()` hook. |
335
+ | `filter` | `((itemValue: Value, query: string, itemToString?: ((itemValue: Value) => string) \| undefined) => boolean) \| null` | — | Filter function used to match items vs input query. |
336
+ | `virtualized` | `boolean` | `false` | Whether the items are being externally virtualized. |
337
+ | `inline` | `boolean` | `false` | Whether the list is rendered inline without using the popup. |
338
+ | `modal` | `boolean` | `false` | Determines if the popup enters a modal state when open. - `true`: user interaction is limited to the popup: document page scroll is locked and pointer interactions on outside elements are disabled. - `false`: user interaction with the rest of the document is allowed. |
339
+ | `limit` | `number` | `-1` | The maximum number of items to display in the list. |
340
+ | `locale` | `LocalesArgument` | — | The locale to use for string comparison. Defaults to the user's runtime locale. |
341
+ | `multiple` | `boolean` | `false` | Whether multiple items can be selected. |
342
+ | `defaultValue` | `ComboboxValueType<Value, Multiple> \| null` | — | The uncontrolled selected value of the combobox when it's initially rendered. To render a controlled combobox, use the `value` prop instead. |
343
+ | `value` | `ComboboxValueType<Value, Multiple> \| null` | — | The selected value of the combobox. Use when controlled. |
344
+ | `onValueChange` | `((value: ComboboxValueType<Value, Multiple> \| (Multiple extends true ? never : null), eventDetails: ChangeEventDetails) => void)` | — | Event handler called when the selected value of the combobox changes. |
345
+ | `labelId` | `string` | — | |
346
+ | `helperTextId` | `string` | — | |
347
+ | `validationTextId` | `string` | — | |
348
+ | `label` | `string` | — | The label for the form field, describing its purpose. |
349
+ | `hideLabel` | `boolean` | — | Visually hide the label. |
350
+ | `labelVariant` | `"body" \| "heading"` | — | Change the label variant |
351
+ | `helperText` | `string` | — | Optional helper text to provide additional context or instructions. |
352
+ | `validationText` | `string` | — | Text to display when the `validationStatus` is set. |
353
+ | `validationStatus` | `"valid" \| "invalid"` | — | Indicates the validation status. |
354
+ | `margin` | `Responsive<"auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
355
+ | `marginTop` | `Responsive<"auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
356
+ | `marginRight` | `Responsive<"auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
357
+ | `marginBottom` | `Responsive<"auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
358
+ | `marginLeft` | `Responsive<"auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
359
+ | `marginX` | `Responsive<"auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
360
+ | `marginY` | `Responsive<"auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
@@ -0,0 +1,162 @@
1
+ # Container
2
+
3
+ ```tsx
4
+ <Container {...args}>
5
+ <Placeholder
6
+ width="100%"
7
+ height="84px"
8
+ backgroundColor="secondary"
9
+ borderColor="subtle"
10
+ borderWidth="1"
11
+ />
12
+ <Placeholder
13
+ width="100%"
14
+ height="100px"
15
+ backgroundColor="secondary"
16
+ borderColor="subtle"
17
+ borderWidth="1"
18
+ />
19
+ <Placeholder
20
+ width="100%"
21
+ height={{ mobile: '544px', desktop: '383px' }}
22
+ backgroundColor="secondary"
23
+ borderColor="subtle"
24
+ borderWidth="1"
25
+ />
26
+ </Container>
27
+ ```
28
+
29
+ ## Alternatives
30
+
31
+ - Box - For primitive styling and layouts
32
+ - Grid - For grid layouts
33
+ - Flex - For stacked, inline or flexbox based
34
+ layouts
35
+
36
+ ## Semantic HTML
37
+
38
+ By default `Container` renders a `div` element, this can be customised using
39
+ the `asChild` prop.
40
+
41
+ ```tsx
42
+ <Container asChild>
43
+ <main>...</main>
44
+ </Container>
45
+ ```
46
+
47
+ ## Max width
48
+
49
+ By default `Container` has a max-width of `100%` for screen widths below the
50
+ desktop breakpoint, and for desktop screens, and above, the max-width is
51
+ defined by the container width design token.
52
+
53
+ If you need to, you can apply your app-specific max-width, usually only at the
54
+ `desktop` breakpoint.
55
+
56
+ ```tsx
57
+ <Container maxWidth={{ desktop: '1096px' }}>{...}</Container>
58
+ ```
59
+
60
+ ## Align
61
+
62
+ By default `Container` aligns its content in the center, you can change this
63
+ with the `align` prop.
64
+
65
+ ```tsx
66
+ <Container align='start'>{...}</Container>
67
+ ```
68
+
69
+ ## Spacing
70
+
71
+ As well as the `gap` prop for flexbox spacing, there is a `spacing` prop which
72
+ uses fewer steps and is already optimised for responsive design. This prop will
73
+ be overridden by the `gap` prop.
74
+
75
+ ```tsx
76
+ <Container spacing="lg">
77
+ ```
78
+
79
+ ## Show/hide content
80
+
81
+ The `display` prop is responsive, you can use this to show or hide content responsively.
82
+
83
+ ```tsx
84
+ <Container display={{ mobile: 'none', tablet: 'flex' }}>hide on mobile screens</Container>
85
+ ```
86
+
87
+ ## API
88
+
89
+ This component is based on the `div` element and supports the following common props:
90
+
91
+ - AlignSelf
92
+ - Gap
93
+ - Padding
94
+ - Margin
95
+ - Position
96
+ - Size
97
+ - Background colour
98
+ - Flex item
99
+ - Z-Index
100
+ - Overflow
101
+ - Order
102
+
103
+ | Prop | Type | Default | Description |
104
+ | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
105
+ | `spacing` | `"none" \| "2xs" \| "xs" \| "sm" \| "md" \| "lg" \| "xl" \| "2xl"` | — | Set responsive spacing between child elements. |
106
+ | `asChild` | `boolean` | — | |
107
+ | `display` | `Responsive<"flex" \| "none" \| "inline-flex">` | — | |
108
+ | `direction` | `Responsive<"row" \| "column" \| "row-reverse" \| "column-reverse">` | — | |
109
+ | `wrap` | `Responsive<"wrap" \| "nowrap" \| "wrap-reverse">` | — | |
110
+ | `alignContent` | `Responsive<"center" \| "start" \| "end" \| "stretch" \| "between" \| "around" \| "evenly">` | — | |
111
+ | `alignItems` | `Responsive<"center" \| "start" \| "end" \| "baseline" \| "stretch">` | — | |
112
+ | `alignSelf` | `Responsive<"center" \| "start" \| "end" \| "stretch">` | — | |
113
+ | `backgroundColor` | `"primary" \| "secondary" \| "brand" \| `var(--h-${string})`` | — | |
114
+ | `borderRadius` | `Responsive<"none" \| "inherit" \| "xs" \| "sm" \| "md" \| "lg" \| "xl" \| "full">` | — | |
115
+ | `borderRadiusTopLeftNone` | `boolean` | — | |
116
+ | `borderRadiusTopRightNone` | `boolean` | — | |
117
+ | `borderRadiusBottomLeftNone` | `boolean` | — | |
118
+ | `borderRadiusBottomRightNone` | `boolean` | — | |
119
+ | `borderRadiusTopNone` | `boolean` | — | |
120
+ | `borderRadiusRightNone` | `boolean` | — | |
121
+ | `borderRadiusBottomNone` | `boolean` | — | |
122
+ | `borderRadiusLeftNone` | `boolean` | — | |
123
+ | `flex` | `Responsive<string>` | — | |
124
+ | `flexBasis` | `Responsive<string>` | — | |
125
+ | `flexShrink` | `Responsive<string>` | — | |
126
+ | `flexGrow` | `Responsive<string>` | — | |
127
+ | `gap` | `Responsive<`var(--h-${string})` \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">` | — | |
128
+ | `rowGap` | `Responsive<`var(--h-${string})` \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">` | — | |
129
+ | `columnGap` | `Responsive<`var(--h-${string})` \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">` | — | |
130
+ | `justifyContent` | `Responsive<"center" \| "start" \| "end" \| "stretch" \| "between" \| "around" \| "evenly">` | — | For flexboxes, the stretch value behaves as flex-start or start. This is because, in flexboxes, stretching is controlled using the flex-grow property. |
131
+ | `margin` | `Responsive<`var(--h-${string})` \| "auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">` | — | |
132
+ | `marginTop` | `Responsive<`var(--h-${string})` \| "auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">` | — | |
133
+ | `marginRight` | `Responsive<`var(--h-${string})` \| "auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">` | — | |
134
+ | `marginBottom` | `Responsive<`var(--h-${string})` \| "auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">` | — | |
135
+ | `marginLeft` | `Responsive<`var(--h-${string})` \| "auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">` | — | |
136
+ | `marginX` | `Responsive<`var(--h-${string})` \| "auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">` | — | |
137
+ | `marginY` | `Responsive<`var(--h-${string})` \| "auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">` | — | |
138
+ | `order` | `Responsive<string>` | — | |
139
+ | `overflow` | `Responsive<"hidden" \| "auto" \| "visible" \| "clip" \| "scroll">` | — | |
140
+ | `overflowX` | `Responsive<"hidden" \| "auto" \| "visible" \| "clip" \| "scroll">` | — | |
141
+ | `overflowY` | `Responsive<"hidden" \| "auto" \| "visible" \| "clip" \| "scroll">` | — | |
142
+ | `padding` | `Responsive<`var(--h-${string})` \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">` | — | |
143
+ | `paddingTop` | `Responsive<`var(--h-${string})` \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">` | — | |
144
+ | `paddingRight` | `Responsive<`var(--h-${string})` \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">` | — | |
145
+ | `paddingBottom` | `Responsive<`var(--h-${string})` \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">` | — | |
146
+ | `paddingLeft` | `Responsive<`var(--h-${string})` \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">` | — | |
147
+ | `paddingX` | `Responsive<`var(--h-${string})` \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">` | — | |
148
+ | `paddingY` | `Responsive<`var(--h-${string})` \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">` | — | |
149
+ | `position` | `Responsive<"static" \| "relative" \| "absolute" \| "fixed" \| "sticky">` | — | |
150
+ | `inset` | `Responsive<Union<string, "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">>` | — | |
151
+ | `top` | `Responsive<Union<string, "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">>` | — | |
152
+ | `right` | `Responsive<Union<string, "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">>` | — | |
153
+ | `bottom` | `Responsive<Union<string, "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">>` | — | |
154
+ | `left` | `Responsive<Union<string, "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000">>` | — | |
155
+ | `width` | `Responsive<string>` | — | |
156
+ | `maxWidth` | `Responsive<string>` | — | |
157
+ | `minWidth` | `Responsive<string>` | — | |
158
+ | `height` | `Responsive<string>` | — | |
159
+ | `maxHeight` | `Responsive<string>` | — | |
160
+ | `minHeight` | `Responsive<string>` | — | |
161
+ | `zIndex` | `Responsive<string>` | — | |
162
+ | `align` | `Responsive<"center" \| "start" \| "end">` | `center` | |