@ceed/ads 1.29.1 → 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.
Files changed (62) hide show
  1. package/dist/components/CurrencyInput/CurrencyInput.d.ts +1 -1
  2. package/dist/components/CurrencyInput/hooks/use-currency-setting.d.ts +2 -2
  3. package/dist/components/ProfileMenu/ProfileMenu.d.ts +1 -1
  4. package/dist/components/SearchBar/SearchBar.d.ts +21 -0
  5. package/dist/components/SearchBar/index.d.ts +3 -0
  6. package/dist/components/data-display/Badge.md +39 -71
  7. package/dist/components/data-display/DataTable.md +1 -1
  8. package/dist/components/data-display/InfoSign.md +98 -74
  9. package/dist/components/data-display/Typography.md +97 -363
  10. package/dist/components/feedback/Dialog.md +62 -76
  11. package/dist/components/feedback/Modal.md +44 -259
  12. package/dist/components/feedback/llms.txt +0 -2
  13. package/dist/components/index.d.ts +2 -0
  14. package/dist/components/inputs/Autocomplete.md +107 -356
  15. package/dist/components/inputs/ButtonGroup.md +106 -115
  16. package/dist/components/inputs/Calendar.md +459 -98
  17. package/dist/components/inputs/CurrencyInput.md +5 -183
  18. package/dist/components/inputs/DatePicker.md +431 -108
  19. package/dist/components/inputs/DateRangePicker.md +492 -131
  20. package/dist/components/inputs/FilterMenu.md +19 -169
  21. package/dist/components/inputs/FilterableCheckboxGroup.md +23 -123
  22. package/dist/components/inputs/IconButton.md +88 -137
  23. package/dist/components/inputs/Input.md +0 -5
  24. package/dist/components/inputs/MonthPicker.md +422 -95
  25. package/dist/components/inputs/MonthRangePicker.md +466 -89
  26. package/dist/components/inputs/PercentageInput.md +16 -185
  27. package/dist/components/inputs/RadioButton.md +35 -163
  28. package/dist/components/inputs/RadioTileGroup.md +61 -150
  29. package/dist/components/inputs/SearchBar.md +44 -0
  30. package/dist/components/inputs/Select.md +326 -222
  31. package/dist/components/inputs/Switch.md +376 -136
  32. package/dist/components/inputs/Textarea.md +10 -213
  33. package/dist/components/inputs/Uploader/Uploader.md +66 -145
  34. package/dist/components/inputs/llms.txt +1 -3
  35. package/dist/components/navigation/Breadcrumbs.md +322 -80
  36. package/dist/components/navigation/Dropdown.md +221 -92
  37. package/dist/components/navigation/IconMenuButton.md +502 -40
  38. package/dist/components/navigation/InsetDrawer.md +738 -68
  39. package/dist/components/navigation/Link.md +298 -39
  40. package/dist/components/navigation/Menu.md +285 -92
  41. package/dist/components/navigation/MenuButton.md +448 -55
  42. package/dist/components/navigation/Pagination.md +338 -47
  43. package/dist/components/navigation/ProfileMenu.md +268 -45
  44. package/dist/components/navigation/Stepper.md +28 -160
  45. package/dist/components/navigation/Tabs.md +316 -57
  46. package/dist/components/surfaces/Sheet.md +334 -151
  47. package/dist/index.browser.js +15 -13
  48. package/dist/index.browser.js.map +4 -4
  49. package/dist/index.cjs +289 -288
  50. package/dist/index.d.ts +1 -1
  51. package/dist/index.js +426 -369
  52. package/dist/llms.txt +1 -8
  53. package/framer/index.js +1 -1
  54. package/package.json +16 -15
  55. package/dist/chunks/rehype-accent-FZRUD7VI.js +0 -39
  56. package/dist/components/feedback/CircularProgress.md +0 -257
  57. package/dist/components/feedback/Skeleton.md +0 -280
  58. package/dist/components/inputs/FormControl.md +0 -361
  59. package/dist/components/inputs/RadioList.md +0 -241
  60. package/dist/components/inputs/Slider.md +0 -334
  61. package/dist/guides/ThemeProvider.md +0 -116
  62. package/dist/guides/llms.txt +0 -9
@@ -2,9 +2,7 @@
2
2
 
3
3
  ## Introduction
4
4
 
5
- The Select component is a form input that allows users to choose one or multiple options from a predefined list. Built on Joy UI's Select, it provides a dropdown interface for picking values within forms, filters, and configuration settings.
6
-
7
- Select accepts options as an array of objects (with `value`, `label`, and optional `secondaryText` / `disabled` fields) or as simple string/number arrays. It wraps the underlying select element with built-in `FormControl`, `FormLabel`, and `FormHelperText` so you can compose complete form fields with a single component.
5
+ The Select component is a form input that allows users to choose one or multiple options from a predefined list. Built on Joy UI's Select, it provides a dropdown interface for selecting values within forms. Select is designed for data input scenarios where users need to pick from a set of options, making it ideal for forms, filters, and configuration settings.
8
6
 
9
7
  ```tsx
10
8
  <Select options={options} />
@@ -26,21 +24,16 @@ Select accepts options as an array of objects (with `value`, `label`, and option
26
24
  | onChange | — | — |
27
25
  | options | — | options |
28
26
 
29
- > **Don't confuse Select with Dropdown**
30
- >
31
- > - **Select**: For form value selection -- the selected value becomes form data.
32
- > - **Dropdown**: For menus and action lists -- triggers actions or navigation.
27
+ > ⚠️ **Don't Confuse Select with Dropdown** ⚠️
33
28
  >
34
- > Choosing the right component:
29
+ > - **Select**: For form value selection - the selected value becomes form data
30
+ > - **Dropdown**: For menus and action lists - triggers actions or navigation
35
31
  >
36
- > - Fewer than 5 options -- consider RadioButton or RadioGroup
37
- > - More than 20 options -- consider Autocomplete with search
38
- > - Actions / navigation -- use Dropdown with Menu
39
-
40
- > **Use built-in form props**
32
+ > Choose the right component:
41
33
  >
42
- > This component natively supports `label` and `helperText` props.
43
- > When building forms, use these built-in props instead of manually composing labels and helper text with Typography.
34
+ > - Less than 5 options Consider RadioButton or RadioGroup
35
+ > - More than 20 options Consider Autocomplete with search
36
+ > - Actions/navigation → Use Dropdown with Menu
44
37
 
45
38
  ## Usage
46
39
 
@@ -64,9 +57,19 @@ function MyComponent() {
64
57
  }
65
58
  ```
66
59
 
67
- ## Variants
60
+ ## Examples
61
+
62
+ ### Basic Select
63
+
64
+ The default Select with a list of options.
65
+
66
+ ```tsx
67
+ <Select options={options} />
68
+ ```
69
+
70
+ ### Variants
68
71
 
69
- Select supports four visual styles: `outlined` (default), `plain`, `soft`, and `solid`.
72
+ Select supports different visual styles.
70
73
 
71
74
  ```tsx
72
75
  <Stack spacing={4}>
@@ -77,16 +80,9 @@ Select supports four visual styles: `outlined` (default), `plain`, `soft`, and `
77
80
  </Stack>
78
81
  ```
79
82
 
80
- ```tsx
81
- <Select options={options} defaultValue="dog" />
82
- <Select options={options} defaultValue="dog" variant="plain" />
83
- <Select options={options} defaultValue="dog" variant="soft" />
84
- <Select options={options} defaultValue="dog" variant="solid" />
85
- ```
86
-
87
- ## Sizes
83
+ ### Sizes
88
84
 
89
- Three sizes are available: `sm`, `md` (default), and `lg`.
85
+ Select comes in different sizes.
90
86
 
91
87
  ```tsx
92
88
  <Stack spacing={4}>
@@ -96,15 +92,9 @@ Three sizes are available: `sm`, `md` (default), and `lg`.
96
92
  </Stack>
97
93
  ```
98
94
 
99
- ```tsx
100
- <Select options={options} defaultValue="dog" size="sm" />
101
- <Select options={options} defaultValue="dog" size="md" />
102
- <Select options={options} defaultValue="dog" size="lg" />
103
- ```
104
-
105
- ## Colors
95
+ ### Colors
106
96
 
107
- Apply semantic colors to communicate intent or state.
97
+ Apply semantic colors to Select.
108
98
 
109
99
  ```tsx
110
100
  <Stack spacing={4}>
@@ -116,17 +106,9 @@ Apply semantic colors to communicate intent or state.
116
106
  </Stack>
117
107
  ```
118
108
 
119
- ```tsx
120
- <Select options={options} defaultValue="dog" color="primary" />
121
- <Select options={options} defaultValue="dog" color="neutral" />
122
- <Select options={options} defaultValue="dog" color="success" />
123
- <Select options={options} defaultValue="dog" color="danger" />
124
- <Select options={options} defaultValue="dog" color="warning" />
125
- ```
109
+ ### With Decorators
126
110
 
127
- ## Decorators
128
-
129
- Use `startDecorator` and `endDecorator` to add icons, badges, or other elements beside the select trigger.
111
+ Add icons or badges to the Select.
130
112
 
131
113
  ```tsx
132
114
  <Select placeholder="Select a pet…" startDecorator={<FavoriteBorder />} endDecorator={<Chip size="sm" color="danger" variant="soft">
@@ -136,24 +118,9 @@ width: 240
136
118
  }} options={options} />
137
119
  ```
138
120
 
139
- ```tsx
140
- import FavoriteBorder from '@mui/icons-material/FavoriteBorder';
141
- import { Chip } from '@ceed/ads';
121
+ ### With Label
142
122
 
143
- <Select
144
- placeholder="Select a pet..."
145
- startDecorator={<FavoriteBorder />}
146
- endDecorator={
147
- <Chip size="sm" color="danger" variant="soft">+5</Chip>
148
- }
149
- options={options}
150
- sx={{ width: 240 }}
151
- />
152
- ```
153
-
154
- ## Label and Helper Text
155
-
156
- The `label` prop renders a form label above the select. The `helperText` prop renders descriptive text below it. Both are built into the component so you do not need to compose them separately.
123
+ Select with an associated label.
157
124
 
158
125
  ```tsx
159
126
  <>
@@ -161,26 +128,19 @@ The `label` prop renders a form label above the select. The `helperText` prop re
161
128
  </>
162
129
  ```
163
130
 
131
+ ### With Helper Text
132
+
133
+ Add helper text for additional context.
134
+
164
135
  ```tsx
165
136
  <>
166
137
  <Select label="Select" helperText="I'm helper text" defaultValue="dog" options={options} />
167
138
  </>
168
139
  ```
169
140
 
170
- ```tsx
171
- <Select label="Pet" options={options} defaultValue="dog" />
141
+ ### Error State
172
142
 
173
- <Select
174
- label="Pet"
175
- helperText="Choose your favorite animal"
176
- options={options}
177
- defaultValue="dog"
178
- />
179
- ```
180
-
181
- ## Error State
182
-
183
- Set `error` to `true` to visually indicate a validation error. Combine with `helperText` to display an error message.
143
+ Show validation errors.
184
144
 
185
145
  ```tsx
186
146
  <>
@@ -188,18 +148,9 @@ Set `error` to `true` to visually indicate a validation error. Combine with `hel
188
148
  </>
189
149
  ```
190
150
 
191
- ```tsx
192
- <Select
193
- label="Pet"
194
- error
195
- helperText="This field is required"
196
- options={options}
197
- />
198
- ```
199
-
200
- ## Form Control
151
+ ### Form Control
201
152
 
202
- Combining `label`, `helperText`, and `error` produces a complete form field. Here is a normal field next to one with an error.
153
+ Complete form integration with label and helper text.
203
154
 
204
155
  ```tsx
205
156
  <>
@@ -208,9 +159,9 @@ Combining `label`, `helperText`, and `error` produces a complete form field. Her
208
159
  </>
209
160
  ```
210
161
 
211
- ## Required Field
162
+ ### Required Field
212
163
 
213
- Set `required` to mark the field as required. An asterisk is added to the label automatically.
164
+ Mark the Select as required.
214
165
 
215
166
  ```tsx
216
167
  <Select
@@ -221,18 +172,9 @@ Set `required` to mark the field as required. An asterisk is added to the label
221
172
  />
222
173
  ```
223
174
 
224
- ```tsx
225
- <Select
226
- label="Pet"
227
- helperText="This field is required"
228
- required
229
- options={options}
230
- />
231
- ```
232
-
233
- ## Multiple Selection
175
+ ### Multiple Selection
234
176
 
235
- Set `multiple` to allow selecting more than one option. The value becomes an array.
177
+ Allow selecting multiple options.
236
178
 
237
179
  ```tsx
238
180
  <Select
@@ -244,18 +186,9 @@ Set `multiple` to allow selecting more than one option. The value becomes an arr
244
186
  />
245
187
  ```
246
188
 
247
- ```tsx
248
- <Select
249
- label="Pets"
250
- multiple
251
- defaultValue={['dog']}
252
- options={options}
253
- />
254
- ```
255
-
256
- ## Controlled Select
189
+ ### Controlled Select
257
190
 
258
- Use the `value` and `onChange` props for controlled behavior when you need to synchronize the selected value with other state.
191
+ Programmatically control the selected value.
259
192
 
260
193
  ```tsx
261
194
  <div>
@@ -274,20 +207,9 @@ Use the `value` and `onChange` props for controlled behavior when you need to sy
274
207
  </div>
275
208
  ```
276
209
 
277
- ```tsx
278
- const [value, setValue] = useState('dog');
279
-
280
- <Select
281
- label="Pet"
282
- value={value}
283
- onChange={(event, newValue) => setValue(newValue)}
284
- options={options}
285
- />
286
- ```
287
-
288
- ## Disabled Options
210
+ ### Disabled Options
289
211
 
290
- Individual options can be disabled by setting `disabled: true` on the option object.
212
+ Individual options can be disabled.
291
213
 
292
214
  ```tsx
293
215
  <Select
@@ -300,20 +222,9 @@ Individual options can be disabled by setting `disabled: true` on the option obj
300
222
  />
301
223
  ```
302
224
 
303
- ```tsx
304
- const options = [
305
- { value: 'dog', label: 'Dog', disabled: true },
306
- { value: 'cat', label: 'Cat' },
307
- { value: 'fish', label: 'Fish', disabled: true },
308
- { value: 'bird', label: 'Bird' },
309
- ];
310
-
311
- <Select label="Pet" options={options} defaultValue="dog" />
312
- ```
313
-
314
- ## Options with Secondary Text
225
+ ### Options with Secondary Text
315
226
 
316
- Add a `secondaryText` field to display supplementary information below each option label. The secondary text size scales proportionally with the component `size`.
227
+ Display additional information for each option.
317
228
 
318
229
  ```tsx
319
230
  <Stack spacing={4} direction="row" alignItems="flex-start">
@@ -329,76 +240,58 @@ Add a `secondaryText` field to display supplementary information below each opti
329
240
  </Stack>
330
241
  ```
331
242
 
332
- ```tsx
333
- const userOptions = [
334
- { value: 'emily', label: 'Emily Carter', secondaryText: '(415) 555-0198' },
335
- { value: 'daniel', label: 'Daniel Kim', secondaryText: '(212) 555-0421' },
336
- { value: 'sophia', label: 'Sophia Martinez', secondaryText: '(646) 555-0734' },
337
- ];
243
+ ## When to Use
338
244
 
339
- <Select placeholder="Select a contact" options={userOptions} />
340
- ```
245
+ ### Good Use Cases
341
246
 
342
- ## Numeric Values
247
+ - **Forms**: When users need to select a value that will be submitted as form data
248
+ - **Filters**: Selecting filter criteria for lists or search results
249
+ - **Settings**: Configuration options where user needs to pick one value
250
+ - **Data entry**: Standardized input where free text isn't appropriate
251
+ - **5-20 options**: Ideal number of choices for a Select
252
+ - **Single source of truth**: When the selected value should be clearly visible
343
253
 
344
- Select supports both string and numeric option values. When using numeric values, TypeScript infers the correct type automatically.
254
+ ### When Not to Use
345
255
 
346
- ```tsx
347
- <Stack spacing={4}>
348
- <Select defaultValue={1} options={numericOptions} />
349
- <Select defaultValue={1} variant="plain" options={numericOptions} />
350
- <Select defaultValue={1} variant="soft" options={numericOptions} />
351
- <Select defaultValue={1} variant="solid" options={numericOptions} />
352
- </Stack>
353
- ```
354
-
355
- ```tsx
356
- const numericOptions = [
357
- { value: 1, label: 'Option 1' },
358
- { value: 2, label: 'Option 2' },
359
- { value: 3, label: 'Option 3' },
360
- ];
361
-
362
- <Select options={numericOptions} defaultValue={1} />
363
- ```
256
+ - **Actions/navigation**: Use Dropdown with Menu instead
257
+ - **2-4 options visible at once**: Consider RadioGroup for better visibility
258
+ - **20+ options**: Use Autocomplete with search functionality
259
+ - **Complex selections**: Consider a different pattern if selections involve complex logic
260
+ - **Toggle between states**: Use Switch or Checkbox instead
364
261
 
365
262
  ## Common Use Cases
366
263
 
367
- ### Form with Validation
264
+ ### Form with Select
368
265
 
369
266
  ```tsx
370
- import { useState } from 'react';
371
- import { Select, Button, Stack } from '@ceed/ads';
372
-
373
267
  function UserForm() {
374
- const [role, setRole] = useState<string | null>(null);
375
- const [submitted, setSubmitted] = useState(false);
376
-
377
- const handleSubmit = (e: React.FormEvent) => {
378
- e.preventDefault();
379
- setSubmitted(true);
380
- if (role) {
381
- // submit form
382
- }
383
- };
268
+ const [country, setCountry] = useState('');
269
+ const [role, setRole] = useState('');
384
270
 
385
271
  return (
386
272
  <form onSubmit={handleSubmit}>
387
273
  <Stack spacing={2}>
274
+ <Select
275
+ label="Country"
276
+ required
277
+ value={country}
278
+ onChange={(e, val) => setCountry(val)}
279
+ options={countries}
280
+ placeholder="Select your country"
281
+ />
282
+
388
283
  <Select
389
284
  label="Role"
390
285
  required
391
286
  value={role}
392
287
  onChange={(e, val) => setRole(val)}
393
- error={submitted && !role}
394
- helperText={submitted && !role ? 'Please select a role' : undefined}
395
288
  options={[
396
289
  { value: 'admin', label: 'Administrator' },
397
290
  { value: 'editor', label: 'Editor' },
398
291
  { value: 'viewer', label: 'Viewer' },
399
292
  ]}
400
- placeholder="Select a role..."
401
293
  />
294
+
402
295
  <Button type="submit">Submit</Button>
403
296
  </Stack>
404
297
  </form>
@@ -406,11 +299,9 @@ function UserForm() {
406
299
  }
407
300
  ```
408
301
 
409
- ### Filter Bar
302
+ ### Filter Select
410
303
 
411
304
  ```tsx
412
- import { Select, Stack } from '@ceed/ads';
413
-
414
305
  function ProductFilter({ onFilterChange }) {
415
306
  const [category, setCategory] = useState('all');
416
307
  const [sortBy, setSortBy] = useState('newest');
@@ -430,8 +321,10 @@ function ProductFilter({ onFilterChange }) {
430
321
  { value: 'all', label: 'All Categories' },
431
322
  { value: 'electronics', label: 'Electronics' },
432
323
  { value: 'clothing', label: 'Clothing' },
324
+ { value: 'home', label: 'Home & Garden' },
433
325
  ]}
434
326
  />
327
+
435
328
  <Select
436
329
  label="Sort By"
437
330
  size="sm"
@@ -441,6 +334,7 @@ function ProductFilter({ onFilterChange }) {
441
334
  { value: 'newest', label: 'Newest First' },
442
335
  { value: 'price-low', label: 'Price: Low to High' },
443
336
  { value: 'price-high', label: 'Price: High to Low' },
337
+ { value: 'popular', label: 'Most Popular' },
444
338
  ]}
445
339
  />
446
340
  </Stack>
@@ -448,15 +342,39 @@ function ProductFilter({ onFilterChange }) {
448
342
  }
449
343
  ```
450
344
 
451
- ### Dependent Selects
345
+ ### Multiple Select with Tags
452
346
 
453
347
  ```tsx
454
- import { useState, useMemo } from 'react';
455
- import { Select, Stack } from '@ceed/ads';
348
+ function TagSelect() {
349
+ const [selectedTags, setSelectedTags] = useState([]);
350
+
351
+ const tagOptions = [
352
+ { value: 'urgent', label: 'Urgent' },
353
+ { value: 'feature', label: 'Feature' },
354
+ { value: 'bug', label: 'Bug' },
355
+ { value: 'enhancement', label: 'Enhancement' },
356
+ { value: 'documentation', label: 'Documentation' },
357
+ ];
358
+
359
+ return (
360
+ <Select
361
+ label="Tags"
362
+ multiple
363
+ value={selectedTags}
364
+ onChange={(e, val) => setSelectedTags(val)}
365
+ options={tagOptions}
366
+ placeholder="Select tags..."
367
+ />
368
+ );
369
+ }
370
+ ```
456
371
 
372
+ ### Dependent Selects
373
+
374
+ ```tsx
457
375
  function LocationSelect() {
458
- const [country, setCountry] = useState<string | null>(null);
459
- const [city, setCity] = useState<string | null>(null);
376
+ const [country, setCountry] = useState('');
377
+ const [city, setCity] = useState('');
460
378
 
461
379
  const cities = useMemo(() => {
462
380
  if (!country) return [];
@@ -470,83 +388,269 @@ function LocationSelect() {
470
388
  value={country}
471
389
  onChange={(e, val) => {
472
390
  setCountry(val);
473
- setCity(null);
391
+ setCity(''); // Reset city when country changes
474
392
  }}
475
393
  options={countries}
476
- placeholder="Select a country"
477
394
  />
395
+
478
396
  <Select
479
397
  label="City"
480
398
  value={city}
481
399
  onChange={(e, val) => setCity(val)}
482
400
  options={cities}
483
401
  disabled={!country}
484
- placeholder={country ? 'Select a city' : 'Select a country first'}
402
+ placeholder={country ? 'Select city' : 'Select country first'}
485
403
  />
486
404
  </Stack>
487
405
  );
488
406
  }
489
407
  ```
490
408
 
409
+ ### With Custom Option Rendering
410
+
411
+ ```tsx
412
+ function UserSelect() {
413
+ const userOptions = [
414
+ { value: 'user1', label: 'John Doe', secondaryText: 'john@example.com' },
415
+ { value: 'user2', label: 'Jane Smith', secondaryText: 'jane@example.com' },
416
+ { value: 'user3', label: 'Bob Johnson', secondaryText: 'bob@example.com' },
417
+ ];
418
+
419
+ return (
420
+ <Select
421
+ label="Assign to"
422
+ options={userOptions}
423
+ placeholder="Select a user..."
424
+ />
425
+ );
426
+ }
427
+ ```
428
+
429
+ ## Props and Customization
430
+
431
+ ### Key Props
432
+
433
+ | Prop | Type | Default | Description |
434
+ | -------------- | -------------------------------------------------------------- | ------------ | ------------------------------- |
435
+ | `options` | `Option[]` | `[]` | Array of options to display |
436
+ | `value` | `T \| T[]` | - | Selected value(s) (controlled) |
437
+ | `defaultValue` | `T \| T[]` | - | Default value (uncontrolled) |
438
+ | `onChange` | `function` | - | Callback when selection changes |
439
+ | `multiple` | `boolean` | `false` | Allow multiple selections |
440
+ | `label` | `string` | - | Label text above the Select |
441
+ | `helperText` | `string` | - | Helper text below the Select |
442
+ | `error` | `boolean` | `false` | Show error state |
443
+ | `required` | `boolean` | `false` | Mark as required |
444
+ | `disabled` | `boolean` | `false` | Disable the Select |
445
+ | `placeholder` | `string` | - | Placeholder text |
446
+ | `variant` | `'plain' \| 'outlined' \| 'soft' \| 'solid'` | `'outlined'` | Visual style |
447
+ | `color` | `'primary' \| 'neutral' \| 'danger' \| 'success' \| 'warning'` | - | Color scheme |
448
+ | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Component size |
449
+
450
+ ### Option Type
451
+
452
+ ```tsx
453
+ interface Option {
454
+ value: string | number;
455
+ label: string;
456
+ secondaryText?: string;
457
+ disabled?: boolean;
458
+ }
459
+ ```
460
+
461
+ ### Numeric Values
462
+
463
+ Select supports both string and numeric values:
464
+
465
+ ```tsx
466
+ <Stack spacing={4}>
467
+ <Select defaultValue={1} options={numericOptions} />
468
+ <Select defaultValue={1} variant="plain" options={numericOptions} />
469
+ <Select defaultValue={1} variant="soft" options={numericOptions} />
470
+ <Select defaultValue={1} variant="solid" options={numericOptions} />
471
+ </Stack>
472
+ ```
473
+
474
+ ```tsx
475
+ const numericOptions = [
476
+ { value: 1, label: 'Option 1' },
477
+ { value: 2, label: 'Option 2' },
478
+ { value: 3, label: 'Option 3' },
479
+ ];
480
+
481
+ <Select options={numericOptions} defaultValue={1} />
482
+ ```
483
+
484
+ ### Custom Styling
485
+
486
+ ```tsx
487
+ <Select
488
+ options={options}
489
+ sx={{
490
+ minWidth: 200,
491
+ '& .MuiSelect-button': {
492
+ borderRadius: 'xl',
493
+ },
494
+ }}
495
+ />
496
+ ```
497
+
498
+ ## Accessibility
499
+
500
+ Select components follow accessibility best practices:
501
+
502
+ ### ARIA Attributes
503
+
504
+ - Uses native listbox role with proper ARIA attributes
505
+ - `aria-labelledby` connects to the label
506
+ - `aria-describedby` connects to helper text
507
+ - `aria-required` when required prop is true
508
+ - `aria-invalid` when error prop is true
509
+
510
+ ### Keyboard Navigation
511
+
512
+ - **Tab**: Focus the Select
513
+ - **Enter/Space**: Open the dropdown
514
+ - **Arrow Up/Down**: Navigate through options
515
+ - **Home/End**: Jump to first/last option
516
+ - **Enter**: Select the focused option
517
+ - **Escape**: Close the dropdown
518
+
519
+ ### Screen Reader Support
520
+
521
+ ```tsx
522
+ <Select
523
+ label="Country"
524
+ helperText="Select your country of residence"
525
+ options={countries}
526
+ aria-label="Country selection"
527
+ />
528
+ ```
529
+
530
+ ### Form Association
531
+
532
+ ```tsx
533
+ <FormControl required error={hasError}>
534
+ <FormLabel>Country</FormLabel>
535
+ <Select options={countries} />
536
+ <FormHelperText>{hasError ? 'Please select a country' : 'Required field'}</FormHelperText>
537
+ </FormControl>
538
+ ```
539
+
491
540
  ## Best Practices
492
541
 
493
- 1. **Use clear, specific labels.** The label should describe exactly what the user is choosing.
542
+ ### Do
543
+
544
+ 1. **Use clear labels**: Labels should clearly describe what the user is selecting
494
545
 
495
546
  ```tsx
496
- // ✅ Good
547
+ // ✅ Good: Clear, specific label
497
548
  <Select label="Preferred contact method" options={contactMethods} />
498
549
 
499
- // ❌ Bad
550
+ // ❌ Bad: Vague label
500
551
  <Select label="Select" options={contactMethods} />
501
552
  ```
502
553
 
503
- 2. **Provide meaningful option text.** Each option label should be immediately understandable.
554
+ 2. **Provide meaningful option labels**: Options should be easy to understand
504
555
 
505
556
  ```tsx
506
- // ✅ Good
557
+ // ✅ Good: Descriptive options
507
558
  { value: 'express', label: 'Express Shipping (1-2 days)' }
508
559
 
509
- // ❌ Bad
560
+ // ❌ Bad: Cryptic options
510
561
  { value: 'exp', label: 'EXP' }
511
562
  ```
512
563
 
513
- 3. **Do not use Select for actions.** Select is for data input. For action menus (Edit, Delete, etc.), use Dropdown with Menu.
564
+ 3. **Order options logically**: Alphabetically, by frequency, or by importance
565
+
566
+ 4. **Include a placeholder**: Help users understand what to select
567
+
568
+ ```tsx
569
+ <Select placeholder="Select a country..." options={countries} />
570
+ ```
571
+
572
+ 5. **Use helper text**: Provide additional context when needed
514
573
 
515
574
  ```tsx
516
- // ✅ Good: Select for data
517
575
  <Select
518
- label="Country"
519
- options={countries}
576
+ label="Timezone"
577
+ helperText="Select the timezone for your reports"
578
+ options={timezones}
520
579
  />
580
+ ```
521
581
 
522
- //Bad: Select for actions
523
- <Select
524
- options={[
525
- { value: 'edit', label: 'Edit' },
526
- { value: 'delete', label: 'Delete' },
527
- ]}
582
+ ###Don't
583
+
584
+ 1. **Don't use for actions**: Select is for data, not navigation or actions
585
+
586
+ ```tsx
587
+ // ❌ Bad: Using Select for actions
588
+ <Select options={[
589
+ { value: 'edit', label: 'Edit' },
590
+ { value: 'delete', label: 'Delete' },
591
+ ]} />
592
+
593
+ // ✅ Good: Use Dropdown for actions
594
+ <Dropdown>
595
+ <MenuButton>Actions</MenuButton>
596
+ <Menu>
597
+ <MenuItem onClick={handleEdit}>Edit</MenuItem>
598
+ <MenuItem onClick={handleDelete}>Delete</MenuItem>
599
+ </Menu>
600
+ </Dropdown>
601
+ ```
602
+
603
+ 2. **Don't disable without explanation**: If options are unavailable, explain why
604
+
605
+ 3. **Don't use with very few options**: Consider RadioGroup for 2-4 options
606
+
607
+ 4. **Don't use with many options without search**: Use Autocomplete for 20+ options
608
+
609
+ ## Performance Considerations
610
+
611
+ ### Large Option Lists
612
+
613
+ For lists with many options, consider:
614
+
615
+ 1. **Pagination or virtual scrolling**: For very large lists
616
+ 2. **Autocomplete**: When users need to search through options
617
+ 3. **Lazy loading**: Load options on demand
618
+
619
+ ```tsx
620
+ // For many options, use Autocomplete instead
621
+ <Autocomplete
622
+ options={largeOptionList}
623
+ getOptionLabel={(option) => option.label}
624
+ renderInput={(params) => <Input {...params} label="Search..." />}
528
625
  />
529
626
  ```
530
627
 
531
- 4. **Choose the right component for the option count.** For 2--4 visible choices, use RadioGroup. For 20+ options that need searching, use Autocomplete. Select works best with roughly 5--20 options.
628
+ ### Controlled vs Uncontrolled
532
629
 
533
- 5. **Use the built-in `label` and `helperText` props** instead of manually wrapping Select with FormControl, FormLabel, and FormHelperText. The component handles the composition and accessibility wiring internally.
630
+ Use controlled mode only when necessary:
534
631
 
535
632
  ```tsx
536
- // Good
537
- <Select label="Timezone" helperText="Used for report scheduling" options={timezones} />
633
+ // Uncontrolled - simpler, better performance
634
+ <Select defaultValue="option1" options={options} />
538
635
 
539
- // Bad
540
- <FormControl>
541
- <FormLabel>Timezone</FormLabel>
542
- <Select options={timezones} />
543
- <FormHelperText>Used for report scheduling</FormHelperText>
544
- </FormControl>
636
+ // Controlled - when you need to sync with other state
637
+ const [value, setValue] = useState('option1');
638
+ <Select value={value} onChange={(e, val) => setValue(val)} options={options} />
545
639
  ```
546
640
 
547
- ## Accessibility
641
+ ### Memoize Options
642
+
643
+ When options are computed, memoize them:
644
+
645
+ ```tsx
646
+ const options = useMemo(() =>
647
+ data.map(item => ({
648
+ value: item.id,
649
+ label: item.name,
650
+ })),
651
+ [data]);
652
+
653
+ <Select options={options} />
654
+ ```
548
655
 
549
- - **Label association**: When you use the `label` prop, the component automatically connects the label to the select element via `aria-labelledby`. Always provide a label for screen reader users.
550
- - **Keyboard navigation**: The select can be opened with Enter or Space, navigated with Arrow Up/Down and Home/End, confirmed with Enter, and dismissed with Escape.
551
- - **Error announcement**: When `error` is set, `aria-invalid` is applied. Pair it with a descriptive `helperText` so assistive technology can announce the error reason.
552
- - **Required state**: The `required` prop adds `aria-required` and a visible asterisk to the label, communicating the requirement both visually and programmatically.
656
+ Select is a fundamental form component that provides a clean interface for choosing from predefined options. Use it appropriately to create intuitive forms and ensure users can easily make selections.