@ceed/cds 1.22.3 → 1.22.5

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 (44) hide show
  1. package/dist/components/data-display/InfoSign.md +74 -91
  2. package/dist/components/data-display/Typography.md +363 -63
  3. package/dist/components/feedback/CircularProgress.md +257 -0
  4. package/dist/components/feedback/Skeleton.md +280 -0
  5. package/dist/components/feedback/llms.txt +2 -0
  6. package/dist/components/inputs/ButtonGroup.md +115 -104
  7. package/dist/components/inputs/CurrencyInput.md +181 -8
  8. package/dist/components/inputs/DatePicker.md +108 -436
  9. package/dist/components/inputs/DateRangePicker.md +130 -496
  10. package/dist/components/inputs/FilterableCheckboxGroup.md +141 -20
  11. package/dist/components/inputs/FormControl.md +361 -0
  12. package/dist/components/inputs/IconButton.md +137 -88
  13. package/dist/components/inputs/Input.md +203 -77
  14. package/dist/components/inputs/MonthPicker.md +95 -427
  15. package/dist/components/inputs/MonthRangePicker.md +89 -471
  16. package/dist/components/inputs/PercentageInput.md +183 -19
  17. package/dist/components/inputs/RadioButton.md +163 -35
  18. package/dist/components/inputs/RadioList.md +241 -0
  19. package/dist/components/inputs/RadioTileGroup.md +146 -62
  20. package/dist/components/inputs/Select.md +219 -328
  21. package/dist/components/inputs/Slider.md +334 -0
  22. package/dist/components/inputs/Switch.md +143 -376
  23. package/dist/components/inputs/Textarea.md +209 -11
  24. package/dist/components/inputs/Uploader/Uploader.md +145 -66
  25. package/dist/components/inputs/llms.txt +3 -0
  26. package/dist/components/navigation/Breadcrumbs.md +57 -308
  27. package/dist/components/navigation/Drawer.md +180 -0
  28. package/dist/components/navigation/Dropdown.md +98 -215
  29. package/dist/components/navigation/IconMenuButton.md +40 -502
  30. package/dist/components/navigation/InsetDrawer.md +281 -650
  31. package/dist/components/navigation/Link.md +31 -348
  32. package/dist/components/navigation/Menu.md +92 -285
  33. package/dist/components/navigation/MenuButton.md +55 -448
  34. package/dist/components/navigation/Pagination.md +47 -338
  35. package/dist/components/navigation/Stepper.md +160 -28
  36. package/dist/components/navigation/Tabs.md +57 -316
  37. package/dist/components/surfaces/Accordions.md +49 -804
  38. package/dist/components/surfaces/Card.md +97 -157
  39. package/dist/components/surfaces/Divider.md +83 -234
  40. package/dist/components/surfaces/Sheet.md +152 -327
  41. package/dist/guides/ThemeProvider.md +89 -0
  42. package/dist/guides/llms.txt +9 -0
  43. package/dist/llms.txt +8 -0
  44. package/package.json +1 -1
@@ -2,7 +2,9 @@
2
2
 
3
3
  ## Introduction
4
4
 
5
- Accordions is a component that displays a vertically stacked list of collapsible sections, each with a header that users can click to expand or collapse the content below. It efficiently organizes content by allowing users to focus on one section at a time while keeping other sections collapsed, reducing visual clutter and improving content navigation. Accordions are commonly used for FAQs, settings panels, navigation menus, and any content that benefits from progressive disclosure.
5
+ Accordions is a component that displays a vertically stacked list of collapsible sections. Each section has a header that users can click to expand or collapse the associated content. This pattern efficiently organizes information through progressive disclosure, reducing visual clutter by allowing users to focus on one section at a time.
6
+
7
+ Accordions are ideal for FAQ pages, settings panels, product detail sections, and any content that benefits from being grouped into expandable categories. The component supports multiple variants, colors, and sizes for flexible visual customization.
6
8
 
7
9
  ```tsx
8
10
  <Accordions {...args} />
@@ -12,15 +14,6 @@ Accordions is a component that displays a vertically stacked list of collapsible
12
14
  | ----- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
13
15
  | items | Array of accordion summaries and details | \[\{ summary: 'First header', details: \<h3>Content of the first accordion.\</h3> }, \{ summary: 'Second header', details: \<h3>Content of the second accordion.\</h3> }, \{ summary: 'Third header', details: \<h3>Content of the third accordion.\</h3> }] |
14
16
 
15
- > ⚠️ **Usage Warning** ⚠️
16
- >
17
- > Consider these guidelines when using Accordions:
18
- >
19
- > - **Don't hide critical content**: Important information should be visible by default
20
- > - **Limit nesting**: Avoid nesting accordions within accordions
21
- > - **Keep headers concise**: Users should understand content without expanding
22
- > - **Consider Tabs**: Use Tabs for content that users need to compare side-by-side
23
-
24
17
  ## Usage
25
18
 
26
19
  ```tsx
@@ -48,19 +41,9 @@ function FAQSection() {
48
41
  }
49
42
  ```
50
43
 
51
- ## Examples
52
-
53
- ### Playground
54
-
55
- Interactive example with all controls.
56
-
57
- ```tsx
58
- <Accordions {...args} />
59
- ```
60
-
61
- ### Basics
44
+ ## Basics
62
45
 
63
- Basic accordion with multiple collapsible sections.
46
+ A basic accordion with multiple collapsible sections.
64
47
 
65
48
  ```tsx
66
49
  <Accordions
@@ -77,9 +60,9 @@ Basic accordion with multiple collapsible sections.
77
60
  />
78
61
  ```
79
62
 
80
- ### Sizes
63
+ ## Sizes
81
64
 
82
- Available size options: `sm`, `md`, `lg`.
65
+ Available in three sizes: `sm`, `md`, and `lg`. Use smaller sizes for sidebars or navigation menus, and larger sizes for main content areas.
83
66
 
84
67
  ```tsx
85
68
  <>
@@ -89,9 +72,9 @@ Available size options: `sm`, `md`, `lg`.
89
72
  </>
90
73
  ```
91
74
 
92
- ### Variants
75
+ ## Variants
93
76
 
94
- Style variants: `plain`, `outlined`, `soft`, `solid`.
77
+ Four style variants are available: `plain`, `outlined`, `soft`, and `solid`. Choose the variant that best matches the surrounding context.
95
78
 
96
79
  ```tsx
97
80
  <>
@@ -114,9 +97,9 @@ Style variants: `plain`, `outlined`, `soft`, `solid`.
114
97
  </>
115
98
  ```
116
99
 
117
- ### Colors
100
+ ## Colors
118
101
 
119
- Color options: `primary`, `neutral`, `danger`, `success`, `warning`.
102
+ Apply semantic colors to match the accordion's purpose: `primary`, `neutral`, `danger`, `success`, or `warning`.
120
103
 
121
104
  ```tsx
122
105
  <>
@@ -143,40 +126,21 @@ Color options: `primary`, `neutral`, `danger`, `success`, `warning`.
143
126
  </>
144
127
  ```
145
128
 
146
- ### Removing Divider
129
+ ## Removing Divider
147
130
 
148
- Use `disableDivider` to remove the divider lines between accordion items.
131
+ Use the `disableDivider` prop to remove the divider lines between accordion items for a cleaner look.
149
132
 
150
133
  ```tsx
151
134
  <Accordions {...args} disableDivider />
152
135
  ```
153
136
 
154
- ## When to Use
155
-
156
- ### ✅ Good Use Cases
157
-
158
- - **FAQs**: Frequently asked questions with expandable answers
159
- - **Settings panels**: Grouped settings that can be expanded individually
160
- - **Product details**: Specifications, reviews, shipping info sections
161
- - **Documentation**: Collapsible sections for detailed explanations
162
- - **Navigation menus**: Expandable category menus
163
- - **Form sections**: Long forms grouped into logical sections
164
- - **Help content**: Step-by-step instructions or troubleshooting guides
165
-
166
- ### ❌ When Not to Use
167
-
168
- - **Critical information**: Don't hide must-read content in accordions
169
- - **Short content**: Use a list or cards if content is minimal
170
- - **Comparison content**: Use Tabs when users need to compare sections
171
- - **Primary navigation**: Use Navigator or Tabs for main navigation
172
- - **Single item**: Don't use accordion for a single collapsible section
173
- - **Deeply nested content**: Avoid nesting accordions within accordions
174
-
175
137
  ## Common Use Cases
176
138
 
177
139
  ### FAQ Section
178
140
 
179
141
  ```tsx
142
+ import { Accordions, Typography, Stack, Box } from '@ceed/cds';
143
+
180
144
  function FAQAccordion() {
181
145
  const faqs = [
182
146
  {
@@ -184,7 +148,7 @@ function FAQAccordion() {
184
148
  details: (
185
149
  <Typography>
186
150
  We accept Visa, MasterCard, American Express, and PayPal.
187
- All payments are processed securely through our payment gateway.
151
+ All payments are processed securely.
188
152
  </Typography>
189
153
  ),
190
154
  },
@@ -192,9 +156,8 @@ function FAQAccordion() {
192
156
  summary: 'How can I track my order?',
193
157
  details: (
194
158
  <Typography>
195
- Once your order ships, you'll receive an email with a tracking
196
- number. You can use this number on our website or the carrier's
197
- site to track your package.
159
+ Once your order ships, you will receive an email with a tracking
160
+ number that you can use on our website.
198
161
  </Typography>
199
162
  ),
200
163
  },
@@ -227,7 +190,9 @@ function FAQAccordion() {
227
190
  ### Settings Panel
228
191
 
229
192
  ```tsx
230
- function SettingsAccordion({ settings, onSettingChange }) {
193
+ import { Accordions, Stack, FormControl, FormLabel, Input, Checkbox } from '@ceed/cds';
194
+
195
+ function SettingsPanel() {
231
196
  const settingsItems = [
232
197
  {
233
198
  summary: 'Account Settings',
@@ -235,18 +200,11 @@ function SettingsAccordion({ settings, onSettingChange }) {
235
200
  <Stack gap={2}>
236
201
  <FormControl>
237
202
  <FormLabel>Display Name</FormLabel>
238
- <Input
239
- value={settings.displayName}
240
- onChange={(e) => onSettingChange('displayName', e.target.value)}
241
- />
203
+ <Input placeholder="Enter your name" />
242
204
  </FormControl>
243
205
  <FormControl>
244
206
  <FormLabel>Email</FormLabel>
245
- <Input
246
- type="email"
247
- value={settings.email}
248
- onChange={(e) => onSettingChange('email', e.target.value)}
249
- />
207
+ <Input type="email" placeholder="your@email.com" />
250
208
  </FormControl>
251
209
  </Stack>
252
210
  ),
@@ -255,179 +213,32 @@ function SettingsAccordion({ settings, onSettingChange }) {
255
213
  summary: 'Notification Preferences',
256
214
  details: (
257
215
  <Stack gap={1}>
258
- <Checkbox
259
- label="Email notifications"
260
- checked={settings.emailNotifications}
261
- onChange={(e) =>
262
- onSettingChange('emailNotifications', e.target.checked)
263
- }
264
- />
265
- <Checkbox
266
- label="Push notifications"
267
- checked={settings.pushNotifications}
268
- onChange={(e) =>
269
- onSettingChange('pushNotifications', e.target.checked)
270
- }
271
- />
272
- <Checkbox
273
- label="Weekly digest"
274
- checked={settings.weeklyDigest}
275
- onChange={(e) => onSettingChange('weeklyDigest', e.target.checked)}
276
- />
277
- </Stack>
278
- ),
279
- },
280
- {
281
- summary: 'Privacy Settings',
282
- details: (
283
- <Stack gap={1}>
284
- <Checkbox
285
- label="Make profile public"
286
- checked={settings.publicProfile}
287
- onChange={(e) => onSettingChange('publicProfile', e.target.checked)}
288
- />
289
- <Checkbox
290
- label="Show activity status"
291
- checked={settings.showActivity}
292
- onChange={(e) => onSettingChange('showActivity', e.target.checked)}
293
- />
294
- </Stack>
295
- ),
296
- },
297
- ];
298
-
299
- return (
300
- <Box sx={{ maxWidth: 500 }}>
301
- <Typography level="h3" sx={{ mb: 2 }}>
302
- Settings
303
- </Typography>
304
- <Accordions items={settingsItems} variant="soft" color="neutral" />
305
- </Box>
306
- );
307
- }
308
- ```
309
-
310
- ### Product Details
311
-
312
- ```tsx
313
- function ProductAccordion({ product }) {
314
- const productDetails = [
315
- {
316
- summary: 'Description',
317
- details: (
318
- <Typography>{product.description}</Typography>
319
- ),
320
- },
321
- {
322
- summary: 'Specifications',
323
- details: (
324
- <Table>
325
- <tbody>
326
- {Object.entries(product.specs).map(([key, value]) => (
327
- <tr key={key}>
328
- <td>
329
- <Typography level="body-sm" fontWeight="md">
330
- {key}
331
- </Typography>
332
- </td>
333
- <td>
334
- <Typography level="body-sm">{value}</Typography>
335
- </td>
336
- </tr>
337
- ))}
338
- </tbody>
339
- </Table>
340
- ),
341
- },
342
- {
343
- summary: 'Shipping & Returns',
344
- details: (
345
- <Stack gap={2}>
346
- <Box>
347
- <Typography level="title-sm">Shipping</Typography>
348
- <Typography level="body-sm">
349
- Free shipping on orders over $50. Standard delivery 3-5 days.
350
- </Typography>
351
- </Box>
352
- <Box>
353
- <Typography level="title-sm">Returns</Typography>
354
- <Typography level="body-sm">
355
- 30-day return policy. Items must be unused with original tags.
356
- </Typography>
357
- </Box>
358
- </Stack>
359
- ),
360
- },
361
- {
362
- summary: `Reviews (${product.reviewCount})`,
363
- details: (
364
- <Stack gap={2}>
365
- {product.reviews.slice(0, 3).map((review) => (
366
- <Card key={review.id} variant="outlined">
367
- <CardContent>
368
- <Stack direction="row" justifyContent="space-between">
369
- <Typography level="title-sm">{review.author}</Typography>
370
- <Typography level="body-xs" color="neutral">
371
- {review.date}
372
- </Typography>
373
- </Stack>
374
- <Typography level="body-sm">{review.content}</Typography>
375
- </CardContent>
376
- </Card>
377
- ))}
378
- <Button variant="plain" size="sm">
379
- View all reviews
380
- </Button>
216
+ <Checkbox label="Email notifications" />
217
+ <Checkbox label="Push notifications" />
218
+ <Checkbox label="Weekly digest" />
381
219
  </Stack>
382
220
  ),
383
221
  },
384
222
  ];
385
223
 
386
- return <Accordions items={productDetails} variant="plain" />;
224
+ return <Accordions items={settingsItems} variant="soft" color="neutral" />;
387
225
  }
388
226
  ```
389
227
 
390
228
  ### Navigation Menu
391
229
 
392
230
  ```tsx
393
- function NavigationAccordion() {
231
+ import { Accordions, List, ListItem, ListItemButton, Box } from '@ceed/cds';
232
+
233
+ function SidebarMenu() {
394
234
  const menuItems = [
395
235
  {
396
236
  summary: 'Products',
397
237
  details: (
398
238
  <List size="sm">
399
- <ListItem>
400
- <ListItemButton onClick={() => navigate('/products/electronics')}>
401
- Electronics
402
- </ListItemButton>
403
- </ListItem>
404
- <ListItem>
405
- <ListItemButton onClick={() => navigate('/products/clothing')}>
406
- Clothing
407
- </ListItemButton>
408
- </ListItem>
409
- <ListItem>
410
- <ListItemButton onClick={() => navigate('/products/home')}>
411
- Home & Garden
412
- </ListItemButton>
413
- </ListItem>
414
- </List>
415
- ),
416
- },
417
- {
418
- summary: 'Services',
419
- details: (
420
- <List size="sm">
421
- <ListItem>
422
- <ListItemButton onClick={() => navigate('/services/consulting')}>
423
- Consulting
424
- </ListItemButton>
425
- </ListItem>
426
- <ListItem>
427
- <ListItemButton onClick={() => navigate('/services/support')}>
428
- Support
429
- </ListItemButton>
430
- </ListItem>
239
+ <ListItem><ListItemButton>Electronics</ListItemButton></ListItem>
240
+ <ListItem><ListItemButton>Clothing</ListItemButton></ListItem>
241
+ <ListItem><ListItemButton>Home & Garden</ListItemButton></ListItem>
431
242
  </List>
432
243
  ),
433
244
  },
@@ -435,21 +246,8 @@ function NavigationAccordion() {
435
246
  summary: 'Resources',
436
247
  details: (
437
248
  <List size="sm">
438
- <ListItem>
439
- <ListItemButton onClick={() => navigate('/docs')}>
440
- Documentation
441
- </ListItemButton>
442
- </ListItem>
443
- <ListItem>
444
- <ListItemButton onClick={() => navigate('/blog')}>
445
- Blog
446
- </ListItemButton>
447
- </ListItem>
448
- <ListItem>
449
- <ListItemButton onClick={() => navigate('/tutorials')}>
450
- Tutorials
451
- </ListItemButton>
452
- </ListItem>
249
+ <ListItem><ListItemButton>Documentation</ListItemButton></ListItem>
250
+ <ListItem><ListItemButton>Blog</ListItemButton></ListItem>
453
251
  </List>
454
252
  ),
455
253
  },
@@ -463,578 +261,25 @@ function NavigationAccordion() {
463
261
  }
464
262
  ```
465
263
 
466
- ### Help Documentation
467
-
468
- ```tsx
469
- function HelpAccordion() {
470
- const helpTopics = [
471
- {
472
- summary: 'Getting Started',
473
- details: (
474
- <Stack gap={2}>
475
- <Typography level="title-sm">Step 1: Create an Account</Typography>
476
- <Typography level="body-sm">
477
- Click the "Sign Up" button and fill in your details.
478
- </Typography>
479
- <Typography level="title-sm">Step 2: Verify Email</Typography>
480
- <Typography level="body-sm">
481
- Check your inbox for a verification email and click the link.
482
- </Typography>
483
- <Typography level="title-sm">Step 3: Complete Profile</Typography>
484
- <Typography level="body-sm">
485
- Add your profile picture and bio to personalize your account.
486
- </Typography>
487
- </Stack>
488
- ),
489
- },
490
- {
491
- summary: 'Troubleshooting',
492
- details: (
493
- <Stack gap={2}>
494
- <Box>
495
- <Typography level="title-sm" color="danger">
496
- Can't log in?
497
- </Typography>
498
- <Typography level="body-sm">
499
- Try resetting your password or clearing your browser cache.
500
- </Typography>
501
- </Box>
502
- <Box>
503
- <Typography level="title-sm" color="danger">
504
- Page not loading?
505
- </Typography>
506
- <Typography level="body-sm">
507
- Check your internet connection and try refreshing the page.
508
- </Typography>
509
- </Box>
510
- </Stack>
511
- ),
512
- },
513
- {
514
- summary: 'Contact Support',
515
- details: (
516
- <Stack gap={2}>
517
- <Typography level="body-sm">
518
- Need more help? Reach out to our support team:
519
- </Typography>
520
- <Stack gap={1}>
521
- <Typography level="body-sm">
522
- Email: support@example.com
523
- </Typography>
524
- <Typography level="body-sm">
525
- Live Chat: Available 9am-5pm EST
526
- </Typography>
527
- <Typography level="body-sm">
528
- Phone: 1-800-EXAMPLE
529
- </Typography>
530
- </Stack>
531
- </Stack>
532
- ),
533
- },
534
- ];
535
-
536
- return (
537
- <Box sx={{ maxWidth: 600 }}>
538
- <Typography level="h2" sx={{ mb: 2 }}>
539
- Help Center
540
- </Typography>
541
- <Accordions items={helpTopics} variant="outlined" color="primary" />
542
- </Box>
543
- );
544
- }
545
- ```
546
-
547
- ### Collapsible Form Sections
548
-
549
- ```tsx
550
- function MultiSectionForm({ onSubmit }) {
551
- const [formData, setFormData] = useState({
552
- personal: { firstName: '', lastName: '', email: '' },
553
- address: { street: '', city: '', zipCode: '' },
554
- payment: { cardNumber: '', expiry: '', cvv: '' },
555
- });
556
-
557
- const updateField = (section, field, value) => {
558
- setFormData((prev) => ({
559
- ...prev,
560
- [section]: { ...prev[section], [field]: value },
561
- }));
562
- };
563
-
564
- const formSections = [
565
- {
566
- summary: 'Personal Information',
567
- details: (
568
- <Stack gap={2}>
569
- <Stack direction="row" gap={2}>
570
- <FormControl sx={{ flex: 1 }}>
571
- <FormLabel>First Name</FormLabel>
572
- <Input
573
- value={formData.personal.firstName}
574
- onChange={(e) =>
575
- updateField('personal', 'firstName', e.target.value)
576
- }
577
- />
578
- </FormControl>
579
- <FormControl sx={{ flex: 1 }}>
580
- <FormLabel>Last Name</FormLabel>
581
- <Input
582
- value={formData.personal.lastName}
583
- onChange={(e) =>
584
- updateField('personal', 'lastName', e.target.value)
585
- }
586
- />
587
- </FormControl>
588
- </Stack>
589
- <FormControl>
590
- <FormLabel>Email</FormLabel>
591
- <Input
592
- type="email"
593
- value={formData.personal.email}
594
- onChange={(e) =>
595
- updateField('personal', 'email', e.target.value)
596
- }
597
- />
598
- </FormControl>
599
- </Stack>
600
- ),
601
- },
602
- {
603
- summary: 'Shipping Address',
604
- details: (
605
- <Stack gap={2}>
606
- <FormControl>
607
- <FormLabel>Street Address</FormLabel>
608
- <Input
609
- value={formData.address.street}
610
- onChange={(e) =>
611
- updateField('address', 'street', e.target.value)
612
- }
613
- />
614
- </FormControl>
615
- <Stack direction="row" gap={2}>
616
- <FormControl sx={{ flex: 2 }}>
617
- <FormLabel>City</FormLabel>
618
- <Input
619
- value={formData.address.city}
620
- onChange={(e) =>
621
- updateField('address', 'city', e.target.value)
622
- }
623
- />
624
- </FormControl>
625
- <FormControl sx={{ flex: 1 }}>
626
- <FormLabel>ZIP Code</FormLabel>
627
- <Input
628
- value={formData.address.zipCode}
629
- onChange={(e) =>
630
- updateField('address', 'zipCode', e.target.value)
631
- }
632
- />
633
- </FormControl>
634
- </Stack>
635
- </Stack>
636
- ),
637
- },
638
- {
639
- summary: 'Payment Details',
640
- details: (
641
- <Stack gap={2}>
642
- <FormControl>
643
- <FormLabel>Card Number</FormLabel>
644
- <Input
645
- placeholder="1234 5678 9012 3456"
646
- value={formData.payment.cardNumber}
647
- onChange={(e) =>
648
- updateField('payment', 'cardNumber', e.target.value)
649
- }
650
- />
651
- </FormControl>
652
- <Stack direction="row" gap={2}>
653
- <FormControl sx={{ flex: 1 }}>
654
- <FormLabel>Expiry Date</FormLabel>
655
- <Input
656
- placeholder="MM/YY"
657
- value={formData.payment.expiry}
658
- onChange={(e) =>
659
- updateField('payment', 'expiry', e.target.value)
660
- }
661
- />
662
- </FormControl>
663
- <FormControl sx={{ flex: 1 }}>
664
- <FormLabel>CVV</FormLabel>
665
- <Input
666
- type="password"
667
- placeholder="123"
668
- value={formData.payment.cvv}
669
- onChange={(e) =>
670
- updateField('payment', 'cvv', e.target.value)
671
- }
672
- />
673
- </FormControl>
674
- </Stack>
675
- </Stack>
676
- ),
677
- },
678
- ];
679
-
680
- return (
681
- <Box sx={{ maxWidth: 500 }}>
682
- <Accordions items={formSections} variant="outlined" />
683
- <Button sx={{ mt: 2 }} fullWidth onClick={() => onSubmit(formData)}>
684
- Submit Order
685
- </Button>
686
- </Box>
687
- );
688
- }
689
- ```
690
-
691
- ## Props and Customization
692
-
693
- ### Key Props
694
-
695
- | Prop | Type | Default | Description |
696
- | ---------------- | -------------------------------------------------------------- | ----------- | ------------------------------------------------- |
697
- | `items` | `Array<{ summary: string; details: ReactNode }>` | - | Array of accordion items with headers and content |
698
- | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Size of the accordion |
699
- | `variant` | `'plain' \| 'outlined' \| 'soft' \| 'solid'` | `'plain'` | Visual style variant |
700
- | `color` | `'primary' \| 'neutral' \| 'danger' \| 'success' \| 'warning'` | `'neutral'` | Color theme |
701
- | `disableDivider` | `boolean` | `false` | Remove divider lines between items |
702
-
703
- ### Items Structure
704
-
705
- ```tsx
706
- interface AccordionItem {
707
- summary: string; // Header text displayed when collapsed
708
- details: ReactNode; // Content shown when expanded
709
- }
710
-
711
- // Example items array
712
- const items = [
713
- {
714
- summary: 'Section Title',
715
- details: <Typography>Section content...</Typography>,
716
- },
717
- {
718
- summary: 'Another Section',
719
- details: (
720
- <Stack gap={2}>
721
- <Typography>Multiple elements...</Typography>
722
- <Button>Action</Button>
723
- </Stack>
724
- ),
725
- },
726
- ];
727
- ```
728
-
729
- ### Variant Options
730
-
731
- ```tsx
732
- // Plain - minimal styling, no background
733
- <Accordions items={items} variant="plain" />
734
-
735
- // Outlined - bordered container
736
- <Accordions items={items} variant="outlined" />
737
-
738
- // Soft - subtle background color
739
- <Accordions items={items} variant="soft" />
740
-
741
- // Solid - full background color
742
- <Accordions items={items} variant="solid" />
743
- ```
744
-
745
- ### Size Options
746
-
747
- ```tsx
748
- // Small - compact for sidebars/menus
749
- <Accordions items={items} size="sm" />
750
-
751
- // Medium - default size
752
- <Accordions items={items} size="md" />
753
-
754
- // Large - spacious for main content
755
- <Accordions items={items} size="lg" />
756
- ```
757
-
758
- ### Color Options
759
-
760
- ```tsx
761
- // Primary - brand color emphasis
762
- <Accordions items={items} color="primary" />
763
-
764
- // Neutral - subtle, default
765
- <Accordions items={items} color="neutral" />
766
-
767
- // Status colors
768
- <Accordions items={items} color="success" />
769
- <Accordions items={items} color="warning" />
770
- <Accordions items={items} color="danger" />
771
- ```
772
-
773
- ### Without Dividers
774
-
775
- ```tsx
776
- // Clean look without divider lines
777
- <Accordions items={items} disableDivider />
778
- ```
779
-
780
- ## Accessibility
781
-
782
- Accordions includes built-in accessibility features:
783
-
784
- ### ARIA Attributes
785
-
786
- - Accordion headers have `role="button"` with `aria-expanded`
787
- - Content regions have `role="region"` with `aria-labelledby`
788
- - Proper focus management between sections
789
-
790
- ### Keyboard Navigation
791
-
792
- - **Tab**: Move focus between accordion headers
793
- - **Enter/Space**: Expand or collapse focused accordion
794
- - **Arrow Down**: Move focus to next accordion header
795
- - **Arrow Up**: Move focus to previous accordion header
796
- - **Home**: Move focus to first accordion header
797
- - **End**: Move focus to last accordion header
798
-
799
- ### Screen Reader Support
800
-
801
- ```tsx
802
- // Headers announce: "Section Title, collapsed/expanded, button"
803
- <Accordions
804
- items={[
805
- {
806
- summary: 'Shipping Information', // Announced as header
807
- details: <Typography>Content...</Typography>,
808
- },
809
- ]}
810
- />
811
- ```
812
-
813
- ### Focus Visibility
814
-
815
- - Clear focus indicators on headers
816
- - Focus remains on header after expand/collapse
817
- - Tab navigation works within expanded content
818
-
819
264
  ## Best Practices
820
265
 
821
- ### Do
822
-
823
- 1. **Use descriptive headers**: Make content clear without expanding
824
-
825
- ```tsx
826
- // ✅ Good: Descriptive headers
827
- <Accordions
828
- items={[
829
- { summary: 'Return Policy (30 days)', details: '...' },
830
- { summary: 'Shipping Options & Costs', details: '...' },
831
- ]}
832
- />
833
- ```
834
-
835
- 2. **Group related content**: Keep sections logically organized
836
-
837
- ```tsx
838
- // ✅ Good: Logical grouping
839
- <Accordions
840
- items={[
841
- { summary: 'Account Settings', details: accountSettings },
842
- { summary: 'Notification Settings', details: notificationSettings },
843
- { summary: 'Privacy Settings', details: privacySettings },
844
- ]}
845
- />
846
- ```
847
-
848
- 3. **Keep content scannable**: Use lists and headings inside accordions
849
-
850
- ```tsx
851
- // ✅ Good: Scannable content
852
- <Accordions
853
- items={[
854
- {
855
- summary: 'Features',
856
- details: (
857
- <ul>
858
- <li>Feature one</li>
859
- <li>Feature two</li>
860
- <li>Feature three</li>
861
- </ul>
862
- ),
863
- },
864
- ]}
865
- />
866
- ```
867
-
868
- 4. **Match variant to context**: Use appropriate styling
869
-
870
- ```tsx
871
- // ✅ Good: Outlined for forms, plain for navigation
872
- <Accordions items={formSections} variant="outlined" />
873
- <Accordions items={menuItems} variant="plain" size="sm" />
874
- ```
875
-
876
- ### ❌ Don't
877
-
878
- 1. **Don't hide critical information**: Important content should be visible
879
-
880
- ```tsx
881
- // ❌ Bad: Hiding important warnings
882
- <Accordions
883
- items={[
884
- { summary: 'Important Safety Information', details: criticalWarning },
885
- ]}
886
- />
887
-
888
- // ✅ Good: Show warnings prominently
889
- <Alert color="warning">{criticalWarning}</Alert>
890
- ```
891
-
892
- 2. **Don't nest accordions**: Avoid complex hierarchies
893
-
894
- ```tsx
895
- // ❌ Bad: Nested accordions
896
- <Accordions
897
- items={[
898
- {
899
- summary: 'Parent',
900
- details: (
901
- <Accordions items={[{ summary: 'Child', details: '...' }]} />
902
- ),
903
- },
904
- ]}
905
- />
906
-
907
- // ✅ Good: Flat structure or use alternative
908
- <Accordions items={flattenedItems} />
909
- ```
266
+ - **Use descriptive headers.** Users should understand what content a section contains without needing to expand it.
267
+ - ✔ `"Shipping Options & Estimated Costs"`
268
+ - `"Section 3"`
910
269
 
911
- 3. **Don't use for single items**: Unnecessary complexity
270
+ - **Keep the number of items manageable.** Aim for 3 to 7 items per accordion group. If you have more, consider grouping them into categories or adding a search filter.
912
271
 
913
- ```tsx
914
- // Bad: Single accordion item
915
- <Accordions items={[{ summary: 'Details', details: content }]} />
272
+ - **Do not hide critical information.** Important warnings, legal notices, or mandatory instructions should be displayed prominently rather than tucked inside an accordion.
273
+ - Show safety warnings with an Alert component
274
+ - Hide safety warnings inside an accordion
916
275
 
917
- // Good: Use simple disclosure or always show content
918
- <Card>
919
- <CardContent>{content}</CardContent>
920
- </Card>
921
- ```
276
+ - **Avoid nesting accordions within accordions.** Deeply nested structures are confusing and difficult to navigate. Flatten the hierarchy or use a different pattern such as tabs.
922
277
 
923
- 4. **Don't overload with too many sections**: Keep it manageable
924
-
925
- ```tsx
926
- // ❌ Bad: Too many accordion items (15+)
927
- <Accordions items={arrayOf15Items} />
928
-
929
- // ✅ Good: Group or paginate if needed
930
- <Accordions items={arrayOf5To7Items} />
931
- ```
278
+ - **Match the variant to the context.** Use `outlined` for form sections, `plain` for navigation menus, and `soft` for informational panels.
932
279
 
933
- ## Performance Considerations
934
-
935
- ### Lazy Load Heavy Content
936
-
937
- For accordions with heavy content, render only when expanded:
938
-
939
- ```tsx
940
- function LazyAccordionContent({ isExpanded, children }) {
941
- const [hasBeenExpanded, setHasBeenExpanded] = useState(false);
942
-
943
- useEffect(() => {
944
- if (isExpanded) setHasBeenExpanded(true);
945
- }, [isExpanded]);
946
-
947
- // Render placeholder until first expansion
948
- if (!hasBeenExpanded) {
949
- return <Typography color="neutral">Loading...</Typography>;
950
- }
951
-
952
- return children;
953
- }
954
- ```
955
-
956
- ### Memoize Items Array
957
-
958
- Prevent unnecessary re-renders by memoizing items:
959
-
960
- ```tsx
961
- const accordionItems = useMemo(
962
- () => [
963
- {
964
- summary: 'Section 1',
965
- details: <ExpensiveComponent data={data1} />,
966
- },
967
- {
968
- summary: 'Section 2',
969
- details: <ExpensiveComponent data={data2} />,
970
- },
971
- ],
972
- [data1, data2]
973
- );
974
-
975
- <Accordions items={accordionItems} />
976
- ```
977
-
978
- ### Avoid Inline Functions in Items
979
-
980
- ```tsx
981
- // ❌ Bad: Creates new objects on every render
982
- <Accordions
983
- items={data.map((item) => ({
984
- summary: item.title,
985
- details: <Content data={item} />,
986
- }))}
987
- />
988
-
989
- // ✅ Good: Memoized transformation
990
- const items = useMemo(
991
- () =>
992
- data.map((item) => ({
993
- summary: item.title,
994
- details: <Content data={item} />,
995
- })),
996
- [data]
997
- );
998
- <Accordions items={items} />
999
- ```
1000
-
1001
- ### Virtualize Long Lists
1002
-
1003
- For many accordion items, consider virtualization:
1004
-
1005
- ```tsx
1006
- // For very long lists (20+ items), consider:
1007
- // 1. Pagination with limited items per page
1008
- // 2. Search/filter to reduce visible items
1009
- // 3. Grouping into categories
1010
-
1011
- function FilteredAccordions({ allItems }) {
1012
- const [search, setSearch] = useState('');
1013
-
1014
- const filteredItems = useMemo(
1015
- () =>
1016
- allItems.filter((item) =>
1017
- item.summary.toLowerCase().includes(search.toLowerCase())
1018
- ),
1019
- [allItems, search]
1020
- );
1021
-
1022
- return (
1023
- <Stack gap={2}>
1024
- <Input
1025
- placeholder="Search..."
1026
- value={search}
1027
- onChange={(e) => setSearch(e.target.value)}
1028
- />
1029
- <Accordions items={filteredItems.slice(0, 10)} />
1030
- {filteredItems.length > 10 && (
1031
- <Typography level="body-sm" color="neutral">
1032
- Showing 10 of {filteredItems.length} results
1033
- </Typography>
1034
- )}
1035
- </Stack>
1036
- );
1037
- }
1038
- ```
280
+ ## Accessibility
1039
281
 
1040
- Accordions provides an efficient way to organize and present collapsible content sections. Use descriptive headers, keep content scannable, and choose appropriate variants based on your context. For critical information, consider displaying it prominently rather than hiding it within an accordion.
282
+ - Accordion headers use `role="button"` with `aria-expanded` to indicate their current state to screen readers.
283
+ - Content regions use `role="region"` with `aria-labelledby` to associate them with their headers.
284
+ - Keyboard navigation is fully supported: **Tab** moves focus between headers, **Enter/Space** toggles expand/collapse, **Arrow Up/Down** moves between headers, and **Home/End** jumps to the first or last header.
285
+ - Focus indicators are clearly visible on headers, and focus remains on the header after toggling to avoid disorienting the user.