@ceed/ads 1.29.0 → 1.30.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/CurrencyInput/CurrencyInput.d.ts +1 -1
- package/dist/components/CurrencyInput/hooks/use-currency-setting.d.ts +2 -2
- package/dist/components/DataTable/hooks.d.ts +2 -1
- package/dist/components/DataTable/utils.d.ts +1 -0
- package/dist/components/ProfileMenu/ProfileMenu.d.ts +1 -1
- package/dist/components/SearchBar/SearchBar.d.ts +21 -0
- package/dist/components/SearchBar/index.d.ts +3 -0
- package/dist/components/data-display/Badge.md +39 -71
- package/dist/components/data-display/DataTable.md +1 -1
- package/dist/components/data-display/InfoSign.md +98 -74
- package/dist/components/data-display/Typography.md +97 -363
- package/dist/components/feedback/Dialog.md +62 -76
- package/dist/components/feedback/Modal.md +44 -259
- package/dist/components/feedback/llms.txt +0 -2
- package/dist/components/index.d.ts +2 -0
- package/dist/components/inputs/Autocomplete.md +107 -356
- package/dist/components/inputs/ButtonGroup.md +106 -115
- package/dist/components/inputs/Calendar.md +459 -98
- package/dist/components/inputs/CurrencyInput.md +5 -183
- package/dist/components/inputs/DatePicker.md +431 -108
- package/dist/components/inputs/DateRangePicker.md +492 -131
- package/dist/components/inputs/FilterMenu.md +19 -169
- package/dist/components/inputs/FilterableCheckboxGroup.md +23 -123
- package/dist/components/inputs/IconButton.md +88 -137
- package/dist/components/inputs/Input.md +0 -5
- package/dist/components/inputs/MonthPicker.md +422 -95
- package/dist/components/inputs/MonthRangePicker.md +466 -89
- package/dist/components/inputs/PercentageInput.md +16 -185
- package/dist/components/inputs/RadioButton.md +35 -163
- package/dist/components/inputs/RadioTileGroup.md +61 -150
- package/dist/components/inputs/SearchBar.md +44 -0
- package/dist/components/inputs/Select.md +326 -222
- package/dist/components/inputs/Switch.md +376 -136
- package/dist/components/inputs/Textarea.md +10 -213
- package/dist/components/inputs/Uploader/Uploader.md +66 -145
- package/dist/components/inputs/llms.txt +1 -3
- package/dist/components/navigation/Breadcrumbs.md +322 -80
- package/dist/components/navigation/Dropdown.md +221 -92
- package/dist/components/navigation/IconMenuButton.md +502 -40
- package/dist/components/navigation/InsetDrawer.md +738 -68
- package/dist/components/navigation/Link.md +298 -39
- package/dist/components/navigation/Menu.md +285 -92
- package/dist/components/navigation/MenuButton.md +448 -55
- package/dist/components/navigation/Pagination.md +338 -47
- package/dist/components/navigation/ProfileMenu.md +268 -45
- package/dist/components/navigation/Stepper.md +28 -160
- package/dist/components/navigation/Tabs.md +316 -57
- package/dist/components/surfaces/Sheet.md +334 -151
- package/dist/index.browser.js +15 -13
- package/dist/index.browser.js.map +4 -4
- package/dist/index.cjs +313 -291
- package/dist/index.d.ts +1 -1
- package/dist/index.js +450 -372
- package/dist/llms.txt +1 -8
- package/framer/index.js +1 -1
- package/package.json +16 -15
- package/dist/chunks/rehype-accent-FZRUD7VI.js +0 -39
- package/dist/components/feedback/CircularProgress.md +0 -257
- package/dist/components/feedback/Skeleton.md +0 -280
- package/dist/components/inputs/FormControl.md +0 -361
- package/dist/components/inputs/RadioList.md +0 -241
- package/dist/components/inputs/Slider.md +0 -334
- package/dist/guides/ThemeProvider.md +0 -116
- package/dist/guides/llms.txt +0 -9
|
@@ -8,36 +8,10 @@ Autocomplete is an enhanced input component that provides real-time suggestions
|
|
|
8
8
|
<Autocomplete options={['Option1', 'Option2']} />
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
| Field
|
|
12
|
-
|
|
|
13
|
-
|
|
|
14
|
-
|
|
|
15
|
-
| size | — | — |
|
|
16
|
-
| placeholder | — | — |
|
|
17
|
-
| label | — | — |
|
|
18
|
-
| helperText | — | — |
|
|
19
|
-
| error | — | — |
|
|
20
|
-
| required | — | — |
|
|
21
|
-
| disabled | — | — |
|
|
22
|
-
| readOnly | — | — |
|
|
23
|
-
| multiple | — | — |
|
|
24
|
-
| freeSolo | — | — |
|
|
25
|
-
| disableClearable | — | — |
|
|
26
|
-
| autoHighlight | — | — |
|
|
27
|
-
| clearOnEscape | — | — |
|
|
28
|
-
| disableCloseOnSelect | — | — |
|
|
29
|
-
| openOnFocus | — | — |
|
|
30
|
-
| blurOnSelect | — | — |
|
|
31
|
-
| filterSelectedOptions | — | — |
|
|
32
|
-
| selectOnFocus | — | — |
|
|
33
|
-
| clearOnBlur | — | — |
|
|
34
|
-
| forcePopupIcon | — | — |
|
|
35
|
-
| loading | — | — |
|
|
36
|
-
| noOptionsText | — | — |
|
|
37
|
-
| loadingText | — | — |
|
|
38
|
-
| limitTags | — | — |
|
|
39
|
-
| value | — | — |
|
|
40
|
-
| defaultValue | — | — |
|
|
11
|
+
| Field | Description | Default |
|
|
12
|
+
| ------- | ----------- | ------- |
|
|
13
|
+
| label | — | — |
|
|
14
|
+
| loading | — | — |
|
|
41
15
|
|
|
42
16
|
> ⚠️ **Usage Warning** ⚠️
|
|
43
17
|
>
|
|
@@ -48,11 +22,6 @@ Autocomplete is an enhanced input component that provides real-time suggestions
|
|
|
48
22
|
> - **Dropdown**: For action menus, not form value selection
|
|
49
23
|
> - **Input**: For free-text entry without predefined options
|
|
50
24
|
|
|
51
|
-
> 💡 **Use built-in form props**
|
|
52
|
-
>
|
|
53
|
-
> This component natively supports form elements such as `label` and `helperText` props.
|
|
54
|
-
> When building forms, use these built-in props instead of manually composing labels and helper text with Typography.
|
|
55
|
-
|
|
56
25
|
## Usage
|
|
57
26
|
|
|
58
27
|
```tsx
|
|
@@ -73,136 +42,23 @@ function CountrySelector() {
|
|
|
73
42
|
}
|
|
74
43
|
```
|
|
75
44
|
|
|
76
|
-
##
|
|
77
|
-
|
|
78
|
-
The `variant` prop controls the visual style of the autocomplete input. Available variants: `outlined` (default), `soft`, `solid`, `plain`.
|
|
79
|
-
|
|
80
|
-
```tsx
|
|
81
|
-
<Stack gap={2} p={2}>
|
|
82
|
-
{variants.map(variant => <Autocomplete key={variant} variant={variant} options={sampleOptions} placeholder={variant} label={variant} sx={{
|
|
83
|
-
maxWidth: 300
|
|
84
|
-
}} />)}
|
|
85
|
-
</Stack>
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
## Sizes
|
|
89
|
-
|
|
90
|
-
Available size options: `sm`, `md`, `lg`.
|
|
91
|
-
|
|
92
|
-
```tsx
|
|
93
|
-
<div style={{
|
|
94
|
-
display: 'flex',
|
|
95
|
-
gap: '10px'
|
|
96
|
-
}}>
|
|
97
|
-
<Autocomplete {...args} size="sm" />
|
|
98
|
-
<Autocomplete {...args} size="md" />
|
|
99
|
-
<Autocomplete {...args} size="lg" />
|
|
100
|
-
</div>
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
## Colors
|
|
104
|
-
|
|
105
|
-
The `color` prop changes the color scheme. Available colors: `primary`, `neutral`, `danger`, `success`, `warning`.
|
|
106
|
-
|
|
107
|
-
```tsx
|
|
108
|
-
<Stack gap={2} p={2}>
|
|
109
|
-
{colors.map(color => <Autocomplete key={color} color={color} options={sampleOptions} defaultValue="Apple" label={color} sx={{
|
|
110
|
-
maxWidth: 300
|
|
111
|
-
}} />)}
|
|
112
|
-
</Stack>
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
## States
|
|
116
|
-
|
|
117
|
-
Autocomplete supports several form states for different interaction contexts.
|
|
118
|
-
|
|
119
|
-
### Disabled
|
|
120
|
-
|
|
121
|
-
A disabled autocomplete cannot be focused or interacted with. Use for fields that are temporarily unavailable.
|
|
122
|
-
|
|
123
|
-
### Read Only
|
|
124
|
-
|
|
125
|
-
A read-only autocomplete can be focused and its value copied, but cannot be changed. Use when a value should be visible but not editable.
|
|
126
|
-
|
|
127
|
-
### Error
|
|
128
|
-
|
|
129
|
-
Set `error` along with `helperText` to indicate validation failures.
|
|
130
|
-
|
|
131
|
-
### Required
|
|
132
|
-
|
|
133
|
-
Set `required` to mark the field as required in a form.
|
|
134
|
-
|
|
135
|
-
```tsx
|
|
136
|
-
<Stack gap={3} p={2} sx={{
|
|
137
|
-
maxWidth: 300
|
|
138
|
-
}}>
|
|
139
|
-
<Autocomplete label="Disabled" options={sampleOptions} defaultValue="Apple" disabled />
|
|
140
|
-
<Autocomplete label="Read Only" options={sampleOptions} defaultValue="Banana" readOnly />
|
|
141
|
-
<Autocomplete label="Error" options={sampleOptions} error helperText="This field is required" />
|
|
142
|
-
<Autocomplete label="Required" options={sampleOptions} required placeholder="Select a fruit..." />
|
|
143
|
-
</Stack>
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
## Free Solo
|
|
147
|
-
|
|
148
|
-
The `freeSolo` prop allows users to type arbitrary values that are not in the options list. This is useful for inputs where the user can either pick a suggestion or enter a custom value.
|
|
149
|
-
|
|
150
|
-
> ⚠️ **Known limitation**: The component's internal `handleChange` accesses `newValue.value`, which is `undefined` for raw strings in freeSolo mode. Typed arbitrary values may not propagate correctly through `onChange`. Consider using `onInputChange` as an alternative for capturing free-text input.
|
|
151
|
-
|
|
152
|
-
```tsx
|
|
153
|
-
<Stack gap={2} p={2} sx={{
|
|
154
|
-
maxWidth: 300
|
|
155
|
-
}}>
|
|
156
|
-
<Autocomplete label="Free Solo" options={sampleOptions} freeSolo placeholder="Type anything..." value={value} onChange={e => setValue(e.target.value)} />
|
|
157
|
-
<Typography level="body-sm" textColor="text.tertiary">
|
|
158
|
-
Current value: {value ?? '(empty)'}
|
|
159
|
-
</Typography>
|
|
160
|
-
<Typography level="body-xs" textColor="text.tertiary">
|
|
161
|
-
Note: freeSolo allows arbitrary text input. However, the component's onChange handler accesses
|
|
162
|
-
newValue.value which is undefined for raw strings, so typed values may not propagate correctly.
|
|
163
|
-
</Typography>
|
|
164
|
-
</Stack>
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
## Disable Clearable
|
|
168
|
-
|
|
169
|
-
Set `disableClearable` to hide the clear (X) button. This forces the user to always have a selection.
|
|
170
|
-
|
|
171
|
-
```tsx
|
|
172
|
-
<Autocomplete
|
|
173
|
-
options={sampleOptions}
|
|
174
|
-
defaultValue="Cherry"
|
|
175
|
-
disableClearable
|
|
176
|
-
label="Disable Clearable"
|
|
177
|
-
sx={{
|
|
178
|
-
maxWidth: 300
|
|
179
|
-
}}
|
|
180
|
-
/>
|
|
181
|
-
```
|
|
45
|
+
## Examples
|
|
182
46
|
|
|
183
|
-
|
|
47
|
+
### Playground
|
|
184
48
|
|
|
185
|
-
|
|
49
|
+
Interactive example with basic string options.
|
|
186
50
|
|
|
187
51
|
```tsx
|
|
188
|
-
<
|
|
189
|
-
<Autocomplete label="Custom No Options Text" options={[]} noOptionsText="No fruits found — try a different search" placeholder="Search fruits..." sx={{
|
|
190
|
-
minWidth: 280
|
|
191
|
-
}} />
|
|
192
|
-
<Autocomplete label="Custom Loading Text" options={[]} loading loadingText="Fetching fruits from the orchard..." placeholder="Loading fruits..." sx={{
|
|
193
|
-
minWidth: 280
|
|
194
|
-
}} />
|
|
195
|
-
</Stack>
|
|
52
|
+
<Autocomplete options={['Option1', 'Option2']} />
|
|
196
53
|
```
|
|
197
54
|
|
|
198
|
-
|
|
55
|
+
### Sizes
|
|
199
56
|
|
|
200
|
-
|
|
57
|
+
Available size options: `sm`, `md`, `lg`.
|
|
201
58
|
|
|
202
59
|
```tsx
|
|
203
60
|
<div style={{
|
|
204
61
|
display: 'flex',
|
|
205
|
-
flexDirection: 'column',
|
|
206
62
|
gap: '10px'
|
|
207
63
|
}}>
|
|
208
64
|
<Autocomplete {...args} size="sm" />
|
|
@@ -211,28 +67,7 @@ Enable `multiple` to allow selecting more than one option. Selected values are s
|
|
|
211
67
|
</div>
|
|
212
68
|
```
|
|
213
69
|
|
|
214
|
-
###
|
|
215
|
-
|
|
216
|
-
In multiple mode, use `limitTags` to control how many tags are visible before truncating. Use `filterSelectedOptions` to hide already-selected options from the dropdown.
|
|
217
|
-
|
|
218
|
-
> 💡 The component uses a custom `renderTags` implementation. JoyUI's `limitTags` truncates the array passed to `renderTags`, so tags will be limited, but the default "+N more" indicator text may not appear.
|
|
219
|
-
|
|
220
|
-
```tsx
|
|
221
|
-
<Stack gap={3} p={2} sx={{
|
|
222
|
-
maxWidth: 400
|
|
223
|
-
}}>
|
|
224
|
-
<Stack gap={1}>
|
|
225
|
-
<Typography level="title-sm">limitTags=2</Typography>
|
|
226
|
-
<Autocomplete multiple options={sampleOptions} defaultValue={['Apple', 'Banana', 'Cherry', 'Date']} limitTags={2} label="Limit Tags" />
|
|
227
|
-
</Stack>
|
|
228
|
-
<Stack gap={1}>
|
|
229
|
-
<Typography level="title-sm">filterSelectedOptions</Typography>
|
|
230
|
-
<Autocomplete multiple options={sampleOptions} defaultValue={['Apple', 'Banana']} filterSelectedOptions label="Filter Selected Options" />
|
|
231
|
-
</Stack>
|
|
232
|
-
</Stack>
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
## Option Groups
|
|
70
|
+
### Option Groups
|
|
236
71
|
|
|
237
72
|
Group options into categories using the `groupBy` function.
|
|
238
73
|
|
|
@@ -260,7 +95,7 @@ Group options into categories using the `groupBy` function.
|
|
|
260
95
|
/>
|
|
261
96
|
```
|
|
262
97
|
|
|
263
|
-
|
|
98
|
+
### Custom Options
|
|
264
99
|
|
|
265
100
|
Options can include decorators for rich content display.
|
|
266
101
|
|
|
@@ -281,28 +116,7 @@ Options can include decorators for rich content display.
|
|
|
281
116
|
/>
|
|
282
117
|
```
|
|
283
118
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
Options can display a secondary line of text using the `secondaryText` property. This is useful for showing additional context like emails, phone numbers, or descriptions alongside the main label.
|
|
287
|
-
|
|
288
|
-
```tsx
|
|
289
|
-
<Stack gap={4} direction="row" alignItems="flex-start" p={2}>
|
|
290
|
-
{sizes.map(size => <Stack key={size} gap={1}>
|
|
291
|
-
<span style={{
|
|
292
|
-
color: '#6366f1',
|
|
293
|
-
fontSize: 12
|
|
294
|
-
}}>{size}</span>
|
|
295
|
-
<Autocomplete placeholder="Placeholder" options={optionsWithSecondaryText} value={values[size]} onChange={e => setValues(prev => ({
|
|
296
|
-
...prev,
|
|
297
|
-
[size]: e.target.value
|
|
298
|
-
}))} sx={{
|
|
299
|
-
minWidth: 200
|
|
300
|
-
}} size={size} />
|
|
301
|
-
</Stack>)}
|
|
302
|
-
</Stack>
|
|
303
|
-
```
|
|
304
|
-
|
|
305
|
-
## Loading State
|
|
119
|
+
### Loading State
|
|
306
120
|
|
|
307
121
|
Show a loading indicator while fetching options.
|
|
308
122
|
|
|
@@ -313,8 +127,6 @@ Show a loading indicator while fetching options.
|
|
|
313
127
|
/>
|
|
314
128
|
```
|
|
315
129
|
|
|
316
|
-
## Controlled / Uncontrolled
|
|
317
|
-
|
|
318
130
|
### Controlled
|
|
319
131
|
|
|
320
132
|
Manage value externally with controlled state.
|
|
@@ -341,67 +153,6 @@ Manage value externally with controlled state.
|
|
|
341
153
|
</Stack>
|
|
342
154
|
```
|
|
343
155
|
|
|
344
|
-
### Uncontrolled
|
|
345
|
-
|
|
346
|
-
Let the component manage its own state with `defaultValue`.
|
|
347
|
-
|
|
348
|
-
```tsx
|
|
349
|
-
<Autocomplete
|
|
350
|
-
options={['Uncontrolled', 'Controlled']}
|
|
351
|
-
label="Component Type"
|
|
352
|
-
defaultValue="Controlled"
|
|
353
|
-
/>
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
## Virtualization
|
|
357
|
-
|
|
358
|
-
Autocomplete automatically virtualizes long option lists for performance. This example renders 1,000 options efficiently.
|
|
359
|
-
|
|
360
|
-
```tsx
|
|
361
|
-
<Autocomplete
|
|
362
|
-
options={(() => {
|
|
363
|
-
const res: any[] = [];
|
|
364
|
-
for (let i = 0; i < 1000; i++) {
|
|
365
|
-
res.push(i);
|
|
366
|
-
}
|
|
367
|
-
return res;
|
|
368
|
-
})()}
|
|
369
|
-
/>
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
## Behavior Props
|
|
373
|
-
|
|
374
|
-
These boolean props fine-tune interaction behavior. Toggle them in the Controls panel below to see their effects.
|
|
375
|
-
|
|
376
|
-
| Prop | Default | Effect |
|
|
377
|
-
| ---------------------- | -------- | -------------------------------------------------------------- |
|
|
378
|
-
| `autoHighlight` | `false` | Automatically highlights the first option when the popup opens |
|
|
379
|
-
| `clearOnEscape` | `false` | Clears the input value when the Escape key is pressed |
|
|
380
|
-
| `disableCloseOnSelect` | `false` | Keeps the popup open after selecting an option |
|
|
381
|
-
| `openOnFocus` | `false` | Opens the popup when the input receives focus |
|
|
382
|
-
| `blurOnSelect` | `false` | Blurs the input after an option is selected |
|
|
383
|
-
| `selectOnFocus` | `false` | Selects all input text when the input is focused |
|
|
384
|
-
| `clearOnBlur` | `true` | Clears the input text on blur if it doesn't match any option |
|
|
385
|
-
| `forcePopupIcon` | `'auto'` | Controls whether the popup icon is always shown |
|
|
386
|
-
|
|
387
|
-
```tsx
|
|
388
|
-
<Autocomplete
|
|
389
|
-
options={sampleOptions}
|
|
390
|
-
label="Behavior Props"
|
|
391
|
-
placeholder="Toggle props in the Controls panel..."
|
|
392
|
-
autoHighlight={false}
|
|
393
|
-
clearOnEscape={false}
|
|
394
|
-
disableCloseOnSelect={false}
|
|
395
|
-
openOnFocus={false}
|
|
396
|
-
blurOnSelect={false}
|
|
397
|
-
selectOnFocus={false}
|
|
398
|
-
clearOnBlur
|
|
399
|
-
sx={{
|
|
400
|
-
maxWidth: 400
|
|
401
|
-
}}
|
|
402
|
-
/>
|
|
403
|
-
```
|
|
404
|
-
|
|
405
156
|
## When to Use
|
|
406
157
|
|
|
407
158
|
### ✅ Good Use Cases
|
|
@@ -476,7 +227,7 @@ function UserSearch({ onSelect }) {
|
|
|
476
227
|
label: user.name,
|
|
477
228
|
secondaryText: user.email,
|
|
478
229
|
startDecorator: <Avatar src={user.avatar} size="sm" />,
|
|
479
|
-
}))
|
|
230
|
+
}))
|
|
480
231
|
);
|
|
481
232
|
} finally {
|
|
482
233
|
setLoading(false);
|
|
@@ -553,7 +304,7 @@ function AddressAutocomplete({ onAddressSelect }) {
|
|
|
553
304
|
value: result.placeId,
|
|
554
305
|
label: result.formattedAddress,
|
|
555
306
|
secondaryText: result.city + ', ' + result.country,
|
|
556
|
-
}))
|
|
307
|
+
}))
|
|
557
308
|
);
|
|
558
309
|
} finally {
|
|
559
310
|
setLoading(false);
|
|
@@ -645,7 +396,13 @@ function ContactSelector() {
|
|
|
645
396
|
{ value: 'michael', label: 'Michael Chen', secondaryText: '(646) 555-0876' },
|
|
646
397
|
];
|
|
647
398
|
|
|
648
|
-
return
|
|
399
|
+
return (
|
|
400
|
+
<Autocomplete
|
|
401
|
+
label="Contact"
|
|
402
|
+
placeholder="Search contacts..."
|
|
403
|
+
options={contacts}
|
|
404
|
+
/>
|
|
405
|
+
);
|
|
649
406
|
}
|
|
650
407
|
```
|
|
651
408
|
|
|
@@ -686,46 +443,30 @@ function LazyAutocomplete({ fetchOptions }) {
|
|
|
686
443
|
|
|
687
444
|
### Key Props
|
|
688
445
|
|
|
689
|
-
| Prop
|
|
690
|
-
|
|
|
691
|
-
| `options`
|
|
692
|
-
| `value`
|
|
693
|
-
| `defaultValue`
|
|
694
|
-
| `onChange`
|
|
695
|
-
| `onInputChange`
|
|
696
|
-
| `label`
|
|
697
|
-
| `placeholder`
|
|
698
|
-
| `loading`
|
|
699
|
-
| `multiple`
|
|
700
|
-
| `groupBy`
|
|
701
|
-
| `size`
|
|
702
|
-
| `
|
|
703
|
-
| `color` | `'primary' \| 'neutral' \| 'danger' \| 'success' \| 'warning'` | `'neutral'` | Color scheme |
|
|
704
|
-
| `disabled` | `boolean` | `false` | Disable the input |
|
|
705
|
-
| `readOnly` | `boolean` | `false` | Make the input read-only (focusable but not editable) |
|
|
706
|
-
| `required` | `boolean` | `false` | Mark the field as required |
|
|
707
|
-
| `error` | `boolean` | `false` | Indicate an error state |
|
|
708
|
-
| `helperText` | `ReactNode` | - | Helper text below the input |
|
|
709
|
-
| `freeSolo` | `boolean` | `false` | Allow arbitrary values not in the options list |
|
|
710
|
-
| `disableClearable` | `boolean` | `false` | Hide the clear (X) button |
|
|
711
|
-
| `noOptionsText` | `ReactNode` | `'No options'` | Text when no options match |
|
|
712
|
-
| `loadingText` | `ReactNode` | `'Loading…'` | Text while loading |
|
|
713
|
-
| `limitTags` | `number` | `-1` | Max visible tags in multiple mode (-1 for unlimited) |
|
|
714
|
-
| `autoHighlight` | `boolean` | `false` | Auto-highlight first option |
|
|
715
|
-
| `clearOnEscape` | `boolean` | `false` | Clear value on Escape key |
|
|
716
|
-
| `disableCloseOnSelect` | `boolean` | `false` | Keep popup open after selection |
|
|
717
|
-
| `openOnFocus` | `boolean` | `false` | Open popup on focus |
|
|
718
|
-
| `filterSelectedOptions` | `boolean` | `false` | Hide selected options from dropdown (multiple mode) |
|
|
446
|
+
| Prop | Type | Default | Description |
|
|
447
|
+
| --------------- | ---------------------------------------- | ------- | ------------------------------------- |
|
|
448
|
+
| `options` | `string[] \| OptionObject[]` | `[]` | Array of options (strings or objects) |
|
|
449
|
+
| `value` | `string \| string[]` | - | Selected value(s) for controlled mode |
|
|
450
|
+
| `defaultValue` | `string \| string[]` | - | Initial value for uncontrolled mode |
|
|
451
|
+
| `onChange` | `(event: { target: { value } }) => void` | - | Callback when selection changes |
|
|
452
|
+
| `onInputChange` | `(event: { target: { value } }) => void` | - | Callback when input text changes |
|
|
453
|
+
| `label` | `string` | - | Label text above the input |
|
|
454
|
+
| `placeholder` | `string` | - | Placeholder text when empty |
|
|
455
|
+
| `loading` | `boolean` | `false` | Show loading indicator |
|
|
456
|
+
| `multiple` | `boolean` | `false` | Allow multiple selections |
|
|
457
|
+
| `groupBy` | `(option) => string` | - | Function to group options |
|
|
458
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Input size |
|
|
459
|
+
| `disabled` | `boolean` | `false` | Disable the input |
|
|
719
460
|
|
|
720
461
|
### Option Object Structure
|
|
721
462
|
|
|
722
463
|
```tsx
|
|
723
464
|
interface OptionObject {
|
|
724
|
-
value: string;
|
|
725
|
-
label: string;
|
|
726
|
-
secondaryText?: string;
|
|
465
|
+
value: string; // Unique value identifier
|
|
466
|
+
label: string; // Display text
|
|
467
|
+
secondaryText?: string; // Secondary line of text
|
|
727
468
|
startDecorator?: ReactNode; // Content before label
|
|
728
|
-
endDecorator?: ReactNode;
|
|
469
|
+
endDecorator?: ReactNode; // Content after label
|
|
729
470
|
}
|
|
730
471
|
|
|
731
472
|
// Example option objects
|
|
@@ -750,7 +491,10 @@ const options = [
|
|
|
750
491
|
|
|
751
492
|
```tsx
|
|
752
493
|
// Simplest usage with string array
|
|
753
|
-
<Autocomplete
|
|
494
|
+
<Autocomplete
|
|
495
|
+
label="Fruit"
|
|
496
|
+
options={['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry']}
|
|
497
|
+
/>
|
|
754
498
|
```
|
|
755
499
|
|
|
756
500
|
### Controlled vs Uncontrolled
|
|
@@ -760,12 +504,23 @@ const options = [
|
|
|
760
504
|
function ControlledExample() {
|
|
761
505
|
const [value, setValue] = useState<string | undefined>();
|
|
762
506
|
|
|
763
|
-
return
|
|
507
|
+
return (
|
|
508
|
+
<Autocomplete
|
|
509
|
+
value={value}
|
|
510
|
+
onChange={(e) => setValue(e.target.value)}
|
|
511
|
+
options={options}
|
|
512
|
+
/>
|
|
513
|
+
);
|
|
764
514
|
}
|
|
765
515
|
|
|
766
516
|
// Uncontrolled - internal state management
|
|
767
517
|
function UncontrolledExample() {
|
|
768
|
-
return
|
|
518
|
+
return (
|
|
519
|
+
<Autocomplete
|
|
520
|
+
defaultValue="option-1"
|
|
521
|
+
options={options}
|
|
522
|
+
/>
|
|
523
|
+
);
|
|
769
524
|
}
|
|
770
525
|
```
|
|
771
526
|
|
|
@@ -799,7 +554,12 @@ function UncontrolledExample() {
|
|
|
799
554
|
### Multiple Selection
|
|
800
555
|
|
|
801
556
|
```tsx
|
|
802
|
-
<Autocomplete
|
|
557
|
+
<Autocomplete
|
|
558
|
+
multiple
|
|
559
|
+
value={['option-1', 'option-2']}
|
|
560
|
+
options={options}
|
|
561
|
+
onChange={(e) => setValues(e.target.value)}
|
|
562
|
+
/>
|
|
803
563
|
```
|
|
804
564
|
|
|
805
565
|
## Accessibility
|
|
@@ -818,7 +578,7 @@ Autocomplete includes comprehensive accessibility features:
|
|
|
818
578
|
- **Arrow Down**: Open dropdown / move to next option
|
|
819
579
|
- **Arrow Up**: Move to previous option
|
|
820
580
|
- **Enter**: Select focused option
|
|
821
|
-
- **Escape**: Close dropdown
|
|
581
|
+
- **Escape**: Close dropdown
|
|
822
582
|
- **Tab**: Move focus out of component
|
|
823
583
|
- **Home**: Jump to first option
|
|
824
584
|
- **End**: Jump to last option
|
|
@@ -829,7 +589,7 @@ Autocomplete includes comprehensive accessibility features:
|
|
|
829
589
|
```tsx
|
|
830
590
|
// Proper labeling for screen readers
|
|
831
591
|
<Autocomplete
|
|
832
|
-
label="Select a country"
|
|
592
|
+
label="Select a country" // Announces: "Select a country, combobox"
|
|
833
593
|
placeholder="Search..."
|
|
834
594
|
options={countries}
|
|
835
595
|
/>
|
|
@@ -843,11 +603,6 @@ Autocomplete includes comprehensive accessibility features:
|
|
|
843
603
|
- Focus returns to input when selecting an option
|
|
844
604
|
- Clear visual focus indicators on all interactive elements
|
|
845
605
|
|
|
846
|
-
### Read Only vs Disabled Semantics
|
|
847
|
-
|
|
848
|
-
- **`readOnly`**: The input is focusable, its value can be copied, and screen readers announce it as read-only. Use when a value should be visible but not editable.
|
|
849
|
-
- **`disabled`**: The input is not focusable and is skipped in tab order. Use when the field is temporarily unavailable.
|
|
850
|
-
|
|
851
606
|
## Best Practices
|
|
852
607
|
|
|
853
608
|
### ✅ Do
|
|
@@ -856,21 +611,32 @@ Autocomplete includes comprehensive accessibility features:
|
|
|
856
611
|
|
|
857
612
|
```tsx
|
|
858
613
|
// ✅ Good: Clear label and placeholder
|
|
859
|
-
<Autocomplete
|
|
614
|
+
<Autocomplete
|
|
615
|
+
label="Shipping Country"
|
|
616
|
+
placeholder="Type to search countries..."
|
|
617
|
+
options={countries}
|
|
618
|
+
/>
|
|
860
619
|
```
|
|
861
620
|
|
|
862
621
|
2. **Show loading state during async operations**: Keep users informed
|
|
863
622
|
|
|
864
623
|
```tsx
|
|
865
624
|
// ✅ Good: Loading indicator while fetching
|
|
866
|
-
<Autocomplete
|
|
625
|
+
<Autocomplete
|
|
626
|
+
options={options}
|
|
627
|
+
loading={isLoading}
|
|
628
|
+
placeholder={isLoading ? 'Loading...' : 'Search...'}
|
|
629
|
+
/>
|
|
867
630
|
```
|
|
868
631
|
|
|
869
632
|
3. **Use grouping for better organization**: Help users scan large lists
|
|
870
633
|
|
|
871
634
|
```tsx
|
|
872
635
|
// ✅ Good: Logical grouping
|
|
873
|
-
<Autocomplete
|
|
636
|
+
<Autocomplete
|
|
637
|
+
options={allProducts}
|
|
638
|
+
groupBy={(product) => product.category}
|
|
639
|
+
/>
|
|
874
640
|
```
|
|
875
641
|
|
|
876
642
|
4. **Debounce API searches**: Prevent excessive requests
|
|
@@ -883,20 +649,6 @@ useEffect(() => {
|
|
|
883
649
|
}, [query]);
|
|
884
650
|
```
|
|
885
651
|
|
|
886
|
-
5. **Use `disableCloseOnSelect` with `multiple`**: Keep the popup open for batch selection
|
|
887
|
-
|
|
888
|
-
```tsx
|
|
889
|
-
// ✅ Good: Popup stays open for multiple selections
|
|
890
|
-
<Autocomplete multiple disableCloseOnSelect options={tags} />
|
|
891
|
-
```
|
|
892
|
-
|
|
893
|
-
6. **Set `limitTags` for constrained layouts**: Prevent tag overflow
|
|
894
|
-
|
|
895
|
-
```tsx
|
|
896
|
-
// ✅ Good: Show at most 3 tags, truncate the rest
|
|
897
|
-
<Autocomplete multiple limitTags={3} options={allTags} />
|
|
898
|
-
```
|
|
899
|
-
|
|
900
652
|
### ❌ Don't
|
|
901
653
|
|
|
902
654
|
1. **Don't use for small option sets**: Use Select instead
|
|
@@ -934,36 +686,20 @@ useEffect(() => {
|
|
|
934
686
|
|
|
935
687
|
```tsx
|
|
936
688
|
// ✅ Good: Handle empty results
|
|
937
|
-
<Autocomplete
|
|
689
|
+
<Autocomplete
|
|
690
|
+
options={filteredOptions}
|
|
691
|
+
noOptionsText="No matches found. Try a different search."
|
|
692
|
+
/>
|
|
938
693
|
```
|
|
939
694
|
|
|
940
695
|
4. **Don't block interaction during initial load**: Show placeholders
|
|
941
696
|
|
|
942
697
|
```tsx
|
|
943
698
|
// ❌ Bad: Blocking the entire form
|
|
944
|
-
{
|
|
945
|
-
loading ? <Spinner /> : <Autocomplete options={options} />;
|
|
946
|
-
}
|
|
699
|
+
{loading ? <Spinner /> : <Autocomplete options={options} />}
|
|
947
700
|
|
|
948
701
|
// ✅ Good: Allow interaction with loading state
|
|
949
|
-
<Autocomplete options={options} loading={loading}
|
|
950
|
-
```
|
|
951
|
-
|
|
952
|
-
5. **Don't rely on `freeSolo` for validated input without extra handling**: Validate free-text values
|
|
953
|
-
|
|
954
|
-
```tsx
|
|
955
|
-
// ❌ Bad: No validation for free-text input
|
|
956
|
-
<Autocomplete freeSolo options={emails} />
|
|
957
|
-
|
|
958
|
-
// ✅ Good: Validate free-text input via onInputChange
|
|
959
|
-
<Autocomplete
|
|
960
|
-
freeSolo
|
|
961
|
-
options={emails}
|
|
962
|
-
onInputChange={(e) => {
|
|
963
|
-
const value = e.target.value;
|
|
964
|
-
setError(!isValidEmail(value));
|
|
965
|
-
}}
|
|
966
|
-
/>
|
|
702
|
+
<Autocomplete options={options} loading={loading} />
|
|
967
703
|
```
|
|
968
704
|
|
|
969
705
|
## Performance Considerations
|
|
@@ -974,7 +710,9 @@ Autocomplete automatically virtualizes long lists for performance:
|
|
|
974
710
|
|
|
975
711
|
```tsx
|
|
976
712
|
// Handles 1000+ options efficiently
|
|
977
|
-
<Autocomplete
|
|
713
|
+
<Autocomplete
|
|
714
|
+
options={Array.from({ length: 1000 }, (_, i) => `Option ${i + 1}`)}
|
|
715
|
+
/>
|
|
978
716
|
```
|
|
979
717
|
|
|
980
718
|
### Debounce Search Requests
|
|
@@ -1001,10 +739,16 @@ function SearchAutocomplete({ fetchOptions }) {
|
|
|
1001
739
|
setLoading(false);
|
|
1002
740
|
}
|
|
1003
741
|
}, 300),
|
|
1004
|
-
[fetchOptions]
|
|
742
|
+
[fetchOptions]
|
|
1005
743
|
);
|
|
1006
744
|
|
|
1007
|
-
return
|
|
745
|
+
return (
|
|
746
|
+
<Autocomplete
|
|
747
|
+
options={options}
|
|
748
|
+
loading={loading}
|
|
749
|
+
onInputChange={(e) => debouncedFetch(e.target.value)}
|
|
750
|
+
/>
|
|
751
|
+
);
|
|
1008
752
|
}
|
|
1009
753
|
```
|
|
1010
754
|
|
|
@@ -1020,10 +764,10 @@ const options = useMemo(
|
|
|
1020
764
|
label: item.name,
|
|
1021
765
|
startDecorator: <StatusChip status={item.status} />,
|
|
1022
766
|
})),
|
|
1023
|
-
[data]
|
|
767
|
+
[data]
|
|
1024
768
|
);
|
|
1025
769
|
|
|
1026
|
-
<Autocomplete options={options}
|
|
770
|
+
<Autocomplete options={options} />
|
|
1027
771
|
```
|
|
1028
772
|
|
|
1029
773
|
### Lazy Load Options
|
|
@@ -1049,7 +793,14 @@ function LazyLoadAutocomplete() {
|
|
|
1049
793
|
}
|
|
1050
794
|
};
|
|
1051
795
|
|
|
1052
|
-
return
|
|
796
|
+
return (
|
|
797
|
+
<Autocomplete
|
|
798
|
+
options={options}
|
|
799
|
+
loading={loading}
|
|
800
|
+
onFocus={loadOptions}
|
|
801
|
+
onOpen={loadOptions}
|
|
802
|
+
/>
|
|
803
|
+
);
|
|
1053
804
|
}
|
|
1054
805
|
```
|
|
1055
806
|
|
|
@@ -1077,7 +828,7 @@ const options = useMemo(
|
|
|
1077
828
|
label: user.name,
|
|
1078
829
|
startDecorator: <MemoizedOption option={user} />,
|
|
1079
830
|
})),
|
|
1080
|
-
[users]
|
|
831
|
+
[users]
|
|
1081
832
|
);
|
|
1082
833
|
```
|
|
1083
834
|
|