@roadlittledawn/docs-design-system-react 0.11.0 → 0.11.2

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/USAGE.md CHANGED
@@ -1,22 +1,75 @@
1
- # @roadlittledawn/docs-design-system-react — Component API Reference
1
+ # @roadlittledawn/docs-design-system-react — Component Usage Guide
2
2
 
3
- Hand-maintained reference for all components. Point your AI tool at this file to get full prop coverage without running Storybook.
3
+ Hand-maintained reference for AI tools and human contributors. Covers when to use each component, when not to, how to choose between similar components, and full prop coverage.
4
4
 
5
5
  ```
6
6
  // CLAUDE.md or equivalent:
7
- // Component API docs: packages/react/USAGE.md (or https://raw.githubusercontent.com/roadlittledawn/docs-design-system/main/packages/react/USAGE.md)
7
+ // Component usage guide: packages/react/USAGE.md (or https://raw.githubusercontent.com/roadlittledawn/docs-design-system/main/packages/react/USAGE.md)
8
8
  ```
9
9
 
10
10
  ---
11
11
 
12
+ ## Choosing Between Similar Components
13
+
14
+ Before diving into individual components, here's guidance on common decision points:
15
+
16
+ ### Navigation and links
17
+
18
+ - **`Link`** — for text-based navigation within prose; auto-handles external links
19
+ - **`Button`** — for actions (submit, save, trigger); not for navigation
20
+ - **`Card` with `href`** — for clickable card-style navigation elements
21
+ - **`Breadcrumb`** — for showing location in the doc hierarchy
22
+
23
+ ### Lists and steps
24
+
25
+ - **`<ol>/<ul>`** — for short, simple text-only lists
26
+ - **`List`** — for visually prominent steps or benefits lists; use when items contain rich content (code blocks, callouts) or need custom bullets
27
+ - **`CollapserGroup` with `numbered`** — for numbered steps where each step needs expand/collapse behavior
28
+
29
+ ### Organizing and hiding content
30
+
31
+ - **`Tabs`** — for a small number of parallel content alternatives displayed side-by-side; user sees one at a time but knows others exist
32
+ - **`Collapser`/`CollapserGroup`** — for long vertical content, FAQs, or any content that benefits from progressive disclosure; user can see all titles at once
33
+ - **`CodeBlock` with `snippets`** — specifically for showing the same code in multiple languages; more compact than Tabs for code-only use cases
34
+
35
+ ### Layout
36
+
37
+ - **`Grid`/`Column`** — for asymmetric or varied multi-column layouts (tutorial + code panel, image + annotation, side-by-side comparison)
38
+ - **`CardGrid`** — specifically for grids of uniform `Card` items; simpler API than `Grid`
39
+
40
+ ### Headings and text
41
+
42
+ - **`Heading`** — for semantic HTML headings that contribute to the document outline (SEO, accessibility, screen reader navigation)
43
+ - **`Typography`** — for styled text, including headings when you still want semantic `<h1>`–`<h4>` elements; for heading-like visuals that should *not* be semantic headings, use `variant="p"` (or similar) plus styling instead of an `h1`–`h4` variant (e.g., a callout title, a sidebar widget header)
44
+
45
+ ---
46
+
12
47
  ## Button
13
48
 
14
- The Button component provides a consistent way to trigger actions across your documentation.
49
+ The Button component is used for user actions — not navigation. Use it when something happens as a result of the click (form submit, trigger an action, open a modal).
50
+
51
+ ### When to Use
52
+
53
+ - Primary actions: "Submit", "Save", "Continue", "Get started"
54
+ - Secondary or cancel actions: "Cancel", "Go back", "Reset"
55
+ - Prominent calls-to-action on documentation landing pages
56
+
57
+ ### When Not to Use
58
+
59
+ - **Navigation between pages** — use `Link` instead; buttons are for actions, not page navigation
60
+ - **Low-priority actions** — a plain text `Link` is less visually noisy
61
+ - **Clickable cards** — use `Card` with the `href` prop
62
+
63
+ ### Variants
64
+
65
+ - `primary` — the main action on a page; use once per section/form
66
+ - `secondary` — alternative or less important actions
67
+ - `outline` — tertiary actions or when you need a subtle button
15
68
 
16
69
  ### Import
17
70
 
18
71
  ```tsx
19
- import { Button } from '@roadlittledawn/docs-design-system-react';
72
+ import { Button } from "@roadlittledawn/docs-design-system-react";
20
73
  ```
21
74
 
22
75
  ### Props
@@ -24,7 +77,7 @@ import { Button } from '@roadlittledawn/docs-design-system-react';
24
77
  Extends `React.ButtonHTMLAttributes<HTMLButtonElement>`.
25
78
 
26
79
  | Prop | Type | Default | Description |
27
- |------|------|---------|-------------|
80
+ | --- | --- | --- | --- |
28
81
  | `variant` | `"primary" \| "secondary" \| "outline"` | `"primary"` | Visual style variant of the button |
29
82
  | `size` | `"sm" \| "md" \| "lg"` | `"md"` | Size of the button |
30
83
  | `children` | `React.ReactNode` | — | Button content |
@@ -33,19 +86,12 @@ Extends `React.ButtonHTMLAttributes<HTMLButtonElement>`.
33
86
 
34
87
  ### Examples
35
88
 
36
- #### Basic
37
-
38
89
  ```tsx
39
90
  <Button variant="primary">Primary Button</Button>
40
91
  <Button variant="secondary">Secondary Button</Button>
41
92
  <Button variant="outline">Outline Button</Button>
42
- ```
43
-
44
- #### Sizes
45
93
 
46
- ```tsx
47
94
  <Button variant="primary" size="sm">Small</Button>
48
- <Button variant="primary" size="md">Medium</Button>
49
95
  <Button variant="primary" size="lg">Large</Button>
50
96
  ```
51
97
 
@@ -53,18 +99,35 @@ Extends `React.ButtonHTMLAttributes<HTMLButtonElement>`.
53
99
 
54
100
  ## Card
55
101
 
56
- The Card component provides a flexible container for displaying content with visual hierarchy.
102
+ A contained, elevated box for grouping related content. Becomes a fully-clickable link element when `href` is provided.
103
+
104
+ ### When to Use
105
+
106
+ - Grouping related content with a visual boundary
107
+ - Creating clickable navigation tiles (use with `href`)
108
+ - Displaying feature highlights or key information
109
+ - Organizing content in grid layouts alongside `CardGrid`
110
+
111
+ ### When Not to Use
112
+
113
+ - **Plain paragraphs of text** — use standard HTML elements or `Typography`
114
+ - **Alerts, warnings, or notices** — use `Callout`
115
+ - **Very long content** — cards are best for summaries; long content belongs in page sections
116
+
117
+ ### When to Use `Card` vs `Callout`
118
+
119
+ Use `Card` for content that is part of the normal page structure (navigation, feature highlights). Use `Callout` when you need to interrupt the reading flow to highlight something important, warn users, or provide tips.
57
120
 
58
121
  ### Import
59
122
 
60
123
  ```tsx
61
- import { Card } from '@roadlittledawn/docs-design-system-react';
124
+ import { Card } from "@roadlittledawn/docs-design-system-react";
62
125
  ```
63
126
 
64
127
  ### Props
65
128
 
66
129
  | Prop | Type | Default | Description |
67
- |------|------|---------|-------------|
130
+ | --- | --- | --- | --- |
68
131
  | `title` | `string` | — | Optional title displayed at the top of the card |
69
132
  | `titleColor` | `"blue" \| "green" \| "purple" \| "red" \| "yellow" \| "gray"` | `"gray"` | Color of the title text |
70
133
  | `backgroundColor` | `"blue" \| "green" \| "purple" \| "red" \| "yellow" \| "gray" \| "white"` | `"white"` | Background color of the card |
@@ -74,89 +137,132 @@ import { Card } from '@roadlittledawn/docs-design-system-react';
74
137
 
75
138
  ### Examples
76
139
 
77
- #### Basic
78
-
79
140
  ```tsx
141
+ {
142
+ /* Basic card */
143
+ }
80
144
  <Card title="Getting Started">
81
145
  Learn the basics of using this documentation system.
82
- </Card>
83
- ```
146
+ </Card>;
84
147
 
85
- #### Clickable card
86
-
87
- ```tsx
148
+ {
149
+ /* Clickable card */
150
+ }
88
151
  <Card title="API Reference" href="/docs/api">
89
152
  Complete reference for all available components.
90
- </Card>
91
- ```
153
+ </Card>;
92
154
 
93
- #### Colored background
94
-
95
- ```tsx
155
+ {
156
+ /* Colored background */
157
+ }
96
158
  <Card title="New Feature" titleColor="blue" backgroundColor="blue">
97
159
  Check out our latest component additions.
98
- </Card>
160
+ </Card>;
99
161
  ```
100
162
 
101
163
  ---
102
164
 
103
165
  ## CardGrid
104
166
 
105
- The CardGrid component provides a responsive grid layout for displaying multiple cards.
167
+ A responsive grid layout specifically for displaying multiple `Card` components. Use this whenever you have 2 or more cards to display together.
168
+
169
+ ### When to Use
170
+
171
+ - Displaying multiple related cards in an organized layout
172
+ - Feature grids and product/section showcases
173
+ - Navigation option grids
174
+ - Any time you have 2+ `Card` components to show side by side
175
+
176
+ ### When Not to Use
177
+
178
+ - **Single cards** — just use `Card` directly
179
+ - **Non-card content** — use `Grid`/`Column` for arbitrary multi-column layouts
180
+ - **Asymmetric layouts** — use `Grid` when columns have different widths or content types
181
+
182
+ ### `CardGrid` vs `Grid`
183
+
184
+ Use `CardGrid` when all items are uniform `Card` components — it has simpler semantics and handles equal-height automatically. Use `Grid` when columns have different widths (e.g. 1/3 + 2/3 split), different content types, or you need layout features like sticky columns.
106
185
 
107
186
  ### Import
108
187
 
109
188
  ```tsx
110
- import { CardGrid } from '@roadlittledawn/docs-design-system-react';
189
+ import { CardGrid } from "@roadlittledawn/docs-design-system-react";
111
190
  ```
112
191
 
113
192
  ### Props
114
193
 
115
194
  | Prop | Type | Default | Description |
116
- |------|------|---------|-------------|
195
+ | --- | --- | --- | --- |
117
196
  | `columns` | `2 \| 3 \| 4` | `3` | Number of columns in the grid |
118
- | `equalHeight` | `boolean` | `true` | When true, all cards in each row expand to the height of the tallest card |
197
+ | `equalHeight` | `boolean` | `true` | When true, all cards in each row expand to the height of the tallest card. Set to `false` if cards should shrink-wrap their content |
119
198
  | `children` | `ReactNode` | — | Grid content (typically Card components) |
120
199
  | `className` | `string` | `""` | Additional CSS classes |
121
200
 
122
201
  ### Examples
123
202
 
124
- #### Basic
125
-
126
203
  ```tsx
127
204
  <CardGrid columns={3}>
128
205
  <Card title="Tutorials">Step-by-step learning guides.</Card>
129
206
  <Card title="How-To Guides">Task-oriented instructions.</Card>
130
207
  <Card title="Reference">Technical reference documentation.</Card>
131
- </CardGrid>
132
- ```
133
-
134
- #### With clickable cards
208
+ </CardGrid>;
135
209
 
136
- ```tsx
210
+ {
211
+ /* Clickable cards */
212
+ }
137
213
  <CardGrid columns={3}>
138
- <Card title="Documentation" href="/docs">Complete documentation guide</Card>
139
- <Card title="API Reference" href="/api">Detailed API reference</Card>
140
- <Card title="Examples" href="/examples">Code examples and patterns</Card>
141
- </CardGrid>
214
+ <Card title="Documentation" href="/docs">
215
+ Complete documentation guide
216
+ </Card>
217
+ <Card title="API Reference" href="/api">
218
+ Detailed API reference
219
+ </Card>
220
+ <Card title="Examples" href="/examples">
221
+ Code examples and patterns
222
+ </Card>
223
+ </CardGrid>;
142
224
  ```
143
225
 
144
226
  ---
145
227
 
146
228
  ## Callout
147
229
 
148
- The Callout component draws attention to important information within documentation pages.
230
+ Interrupts reading flow to highlight important information. Each variant has a specific semantic meaning — choose the right one.
231
+
232
+ ### When to Use
233
+
234
+ - **`caution`** — warnings about potential issues, destructive operations, or things to avoid (yellow/orange color)
235
+ - **`important`** — critical information users must know before proceeding (red/pink color)
236
+ - **`tip`** — helpful suggestions, best practices, shortcuts (green color)
237
+ - **`course`** — learning-oriented content in tutorial or educational contexts (blue color)
238
+
239
+ ### When Not to Use
240
+
241
+ - **General content** — if it doesn't need emphasis, use regular paragraphs
242
+ - **Code examples** — use `CodeBlock`
243
+ - **Navigation or actions** — use `Link` or `Button`
244
+ - **Grouping related content** — use `Card` or `Grid`
245
+
246
+ ### `Callout` vs `Card`
247
+
248
+ `Callout` is for interrupting reading flow with critical contextual information. `Card` is for organizing and presenting content. If you're thinking "users need to stop and read this", it's a `Callout`. If you're organizing content into sections, it's a `Card`.
249
+
250
+ ### Title behavior
251
+
252
+ - By default the title is the capitalized variant name: `"Caution"`, `"Important"`, `"Tip"`, `"Course"`
253
+ - Pass a custom string to override: `title="Security Notice"`
254
+ - Pass `title={null}` to hide the title entirely
149
255
 
150
256
  ### Import
151
257
 
152
258
  ```tsx
153
- import { Callout } from '@roadlittledawn/docs-design-system-react';
259
+ import { Callout } from "@roadlittledawn/docs-design-system-react";
154
260
  ```
155
261
 
156
262
  ### Props
157
263
 
158
264
  | Prop | Type | Default | Description |
159
- |------|------|---------|-------------|
265
+ | --- | --- | --- | --- |
160
266
  | `variant` | `"caution" \| "important" \| "tip" \| "course"` | — | Visual style variant that sets the color and icon |
161
267
  | `title` | `string \| null` | Variant name | Optional title. Pass `null` to hide entirely |
162
268
  | `children` | `ReactNode` | — | Callout content |
@@ -164,41 +270,23 @@ import { Callout } from '@roadlittledawn/docs-design-system-react';
164
270
 
165
271
  ### Examples
166
272
 
167
- #### Caution
168
-
169
273
  ```tsx
170
274
  <Callout variant="caution">
171
275
  This operation cannot be undone. Make sure you have a backup before proceeding.
172
276
  </Callout>
173
- ```
174
277
 
175
- #### Important
176
-
177
- ```tsx
178
278
  <Callout variant="important">
179
279
  All users must update their passwords by the end of the month.
180
280
  </Callout>
181
- ```
182
-
183
- #### Tip
184
281
 
185
- ```tsx
186
282
  <Callout variant="tip">
187
283
  You can use keyboard shortcuts (Cmd+K or Ctrl+K) to quickly search the documentation.
188
284
  </Callout>
189
- ```
190
-
191
- #### Custom title
192
285
 
193
- ```tsx
194
286
  <Callout variant="important" title="Security Notice">
195
287
  Two-factor authentication is now required for all administrator accounts.
196
288
  </Callout>
197
- ```
198
-
199
- #### No title
200
289
 
201
- ```tsx
202
290
  <Callout variant="tip" title={null}>
203
291
  This callout has no title and displays only the content.
204
292
  </Callout>
@@ -208,18 +296,41 @@ import { Callout } from '@roadlittledawn/docs-design-system-react';
208
296
 
209
297
  ## Heading
210
298
 
211
- The Heading component provides semantic HTML headings (h1–h4) with consistent styling and auto-generated IDs.
299
+ Semantic HTML headings (h1–h4) with consistent styling and auto-generated anchor IDs. Use this for actual document structure.
300
+
301
+ ### When to Use
302
+
303
+ - Page and section titles that should appear in the document outline
304
+ - Creating proper heading hierarchy for SEO and accessibility
305
+ - When headings need auto-generated anchor IDs for deep-linking
306
+
307
+ ### When Not to Use
308
+
309
+ - **Visual heading style without semantic meaning** — use `Typography` instead (e.g., a styled label in a card or sidebar that isn't actually a section heading)
310
+ - **Headings deeper than h4** — if you need h5/h6, reconsider your document structure
311
+ - **Buttons or links styled as headings** — use the appropriate component
312
+
313
+ ### Best Practices
314
+
315
+ - Use exactly one `h1` per page
316
+ - Never skip heading levels (don't jump from h2 to h4)
317
+ - Keep headings concise and descriptive
318
+ - `Heading` contributes to screen reader document outline; `Typography` does not
319
+
320
+ ### `Heading` vs `Typography`
321
+
322
+ Both can visually render heading-sized text. Use `Heading` when the text represents an actual section of the document that should appear in the table of contents, be navigable by screen readers, and contribute to SEO. Use `Typography` when you want heading visual styles for decorative or non-structural purposes.
212
323
 
213
324
  ### Import
214
325
 
215
326
  ```tsx
216
- import { Heading } from '@roadlittledawn/docs-design-system-react';
327
+ import { Heading } from "@roadlittledawn/docs-design-system-react";
217
328
  ```
218
329
 
219
330
  ### Props
220
331
 
221
332
  | Prop | Type | Default | Description |
222
- |------|------|---------|-------------|
333
+ | --- | --- | --- | --- |
223
334
  | `level` | `1 \| 2 \| 3 \| 4` | — | Heading level — renders as `<h1>` through `<h4>` |
224
335
  | `id` | `string` | auto-generated from text | Override the auto-generated `id` attribute |
225
336
  | `children` | `React.ReactNode` | — | Heading content |
@@ -227,8 +338,6 @@ import { Heading } from '@roadlittledawn/docs-design-system-react';
227
338
 
228
339
  ### Examples
229
340
 
230
- #### Basic
231
-
232
341
  ```tsx
233
342
  <Heading level={1}>Page Title</Heading>
234
343
  <Heading level={2}>Section Title</Heading>
@@ -240,26 +349,36 @@ import { Heading } from '@roadlittledawn/docs-design-system-react';
240
349
 
241
350
  ## Typography
242
351
 
243
- The Typography component renders text with predefined styles for consistency.
352
+ Applies predefined text styles for visual consistency. Can render semantic headings when using `variant="h1" | "h2" | "h3" | "h4"`, but unlike `Heading` it does not auto-generate IDs or anchor links.
353
+
354
+ ### When to Use
355
+
356
+ - Body text and paragraphs
357
+ - Captions and small supplementary text
358
+ - Heading-style visuals where you don't need auto-generated IDs or in-page anchor links (e.g., labels inside cards, widget titles, decorative callout headers)
359
+
360
+ ### When Not to Use
361
+
362
+ - **Section headings that need auto-generated IDs / anchor links / outline integration** — prefer `Heading` so the content appears in navigation, tables of contents, and deep links
363
+ - **Buttons** — use `Button`
364
+ - **Links** — use `Link`
244
365
 
245
366
  ### Import
246
367
 
247
368
  ```tsx
248
- import { Typography } from '@roadlittledawn/docs-design-system-react';
369
+ import { Typography } from "@roadlittledawn/docs-design-system-react";
249
370
  ```
250
371
 
251
372
  ### Props
252
373
 
253
374
  | Prop | Type | Default | Description |
254
- |------|------|---------|-------------|
375
+ | --- | --- | --- | --- |
255
376
  | `variant` | `"h1" \| "h2" \| "h3" \| "h4" \| "p" \| "caption"` | `"p"` | Typography style variant. `h1`–`h4` render as heading elements; `p` and `caption` render as `<p>` |
256
377
  | `children` | `React.ReactNode` | — | Text content |
257
378
  | `className` | `string` | `""` | Additional CSS classes |
258
379
 
259
380
  ### Examples
260
381
 
261
- #### Basic
262
-
263
382
  ```tsx
264
383
  <Typography variant="h1">Heading 1 Style</Typography>
265
384
  <Typography variant="p">
@@ -274,52 +393,101 @@ import { Typography } from '@roadlittledawn/docs-design-system-react';
274
393
 
275
394
  ## Link
276
395
 
277
- The Link component provides consistent link styling and automatically handles external links.
396
+ Inline text link with consistent styling. Automatically detects external URLs and adds `target="_blank"`, `rel="noopener noreferrer"`, and an external link icon.
397
+
398
+ ### When to Use
399
+
400
+ - Navigation between pages within prose text
401
+ - Links to external resources
402
+ - Anchor links within a page (`href="#section-id"`)
403
+ - When you need a text link rather than a button
404
+
405
+ ### When Not to Use
406
+
407
+ - **Primary actions** — use `Button` (actions change state or trigger something; links navigate)
408
+ - **Navigation styled like a button** — use `Button variant="outline"` or similar
409
+ - **Clickable cards** — use `Card` with the `href` prop
410
+
411
+ ### External link behavior
412
+
413
+ URLs starting with `http://` or `https://` automatically:
414
+
415
+ - Open in a new tab (`target="_blank"`)
416
+ - Include security attributes (`rel="noopener noreferrer"`)
417
+ - Display an external link icon after the text
278
418
 
279
419
  ### Import
280
420
 
281
421
  ```tsx
282
- import { Link } from '@roadlittledawn/docs-design-system-react';
422
+ import { Link } from "@roadlittledawn/docs-design-system-react";
283
423
  ```
284
424
 
285
425
  ### Props
286
426
 
287
427
  | Prop | Type | Default | Description |
288
- |------|------|---------|-------------|
428
+ | --- | --- | --- | --- |
289
429
  | `href` | `string` | — | URL to link to. External links (starting with `http://` or `https://`) open in a new tab with an external link icon |
290
- | `children` | `React.ReactNode` | — | Link content (optional in types, but required for accessible usage) |
430
+ | `children` | `React.ReactNode` | — | Link content. Always provide meaningful, descriptive text; avoid empty links or icon-only links without an appropriate `aria-label`. |
291
431
  | `className` | `string` | `""` | Additional CSS classes |
292
432
 
293
433
  ### Examples
294
434
 
295
- #### Internal link
296
-
297
435
  ```tsx
298
- <Link href="/docs/components">View Components Documentation</Link>
299
- ```
436
+ {
437
+ /* Internal link */
438
+ }
439
+ <Link href="/docs/components">View Components Documentation</Link>;
300
440
 
301
- #### External link (opens in new tab)
441
+ {
442
+ /* External link — opens in new tab with icon automatically */
443
+ }
444
+ <Link href="https://github.com/roadlittledawn/docs-design-system">
445
+ View on GitHub
446
+ </Link>;
302
447
 
303
- ```tsx
304
- <Link href="https://github.com/roadlittledawn/docs-design-system">View on GitHub</Link>
448
+ {
449
+ /* Inline in prose */
450
+ }
451
+ <p>
452
+ For more information, check out the{" "}
453
+ <Link href="/docs/getting-started">Getting Started guide</Link>.
454
+ </p>;
305
455
  ```
306
456
 
307
457
  ---
308
458
 
309
459
  ## List
310
460
 
311
- A visually enhanced list component with numbered badges (ordered) or custom bullets (unordered) and connector lines.
461
+ A visually enhanced list with numbered badges (ordered) or custom bullets (unordered) and connector lines between items. Designed for content that deserves more visual prominence than a plain HTML list.
462
+
463
+ ### When to Use
464
+
465
+ - Tutorial or getting-started guides with substantial steps
466
+ - Multi-step workflows where each step contains rich content (paragraphs, code blocks, callouts)
467
+ - Feature lists or benefit lists that need custom emoji or icon bullets
468
+ - Marketing or landing pages where visual polish matters
469
+ - When you want to nest other components (`CodeBlock`, `Callout`, etc.) inside list items
470
+
471
+ ### When Not to Use
472
+
473
+ - **Short, simple text-only lists** — use standard `<ol>` or `<ul>`; this component adds visual weight that's unnecessary for basic lists
474
+ - **Very long lists** — consider breaking into sections with `Tabs` or `CollapserGroup`
475
+ - **When visual simplicity is preferred** — plain HTML lists are perfectly appropriate and less noisy
476
+
477
+ ### `List` vs `CollapserGroup` (numbered)
478
+
479
+ Use `List` when all step content should be permanently visible. Use `CollapserGroup` with `numbered={true}` when each step contains enough content that users benefit from expand/collapse behavior.
312
480
 
313
481
  ### Import
314
482
 
315
483
  ```tsx
316
- import { List } from '@roadlittledawn/docs-design-system-react';
484
+ import { List } from "@roadlittledawn/docs-design-system-react";
317
485
  ```
318
486
 
319
487
  ### List Props
320
488
 
321
489
  | Prop | Type | Default | Description |
322
- |------|------|---------|-------------|
490
+ | --- | --- | --- | --- |
323
491
  | `children` | `ReactNode` | — | `List.Item` components to render |
324
492
  | `className` | `string` | `""` | Additional CSS classes |
325
493
  | `ordered` | `boolean` | `true` | Whether the list is ordered (numbered) or unordered (bullets) |
@@ -328,36 +496,50 @@ import { List } from '@roadlittledawn/docs-design-system-react';
328
496
 
329
497
  ### List.Item Props
330
498
 
331
- | Prop | Type | Default | Description |
332
- |------|------|---------|-------------|
333
- | `children` | `ReactNode` | — | List item content |
334
- | `className` | `string` | `""` | Additional CSS classes |
499
+ | Prop | Type | Default | Description |
500
+ | ----------- | ----------- | ------- | ---------------------- |
501
+ | `children` | `ReactNode` | — | List item content |
502
+ | `className` | `string` | `""` | Additional CSS classes |
335
503
 
336
504
  ### Examples
337
505
 
338
- #### Ordered list
339
-
340
506
  ```tsx
507
+ {
508
+ /* Ordered list with rich content */
509
+ }
341
510
  <List>
342
- <List.Item>Run the following command: <code>npm install</code></List.Item>
511
+ <List.Item>
512
+ Run the following command: <code>npm install</code>
513
+ </List.Item>
343
514
  <List.Item>Configure your project settings.</List.Item>
344
515
  <List.Item>Start the development server.</List.Item>
345
- </List>
346
- ```
516
+ </List>;
347
517
 
348
- #### Unordered list with emoji bullet
349
-
350
- ```tsx
518
+ {
519
+ /* Ordered list with nested CodeBlock and Callout */
520
+ }
521
+ <List>
522
+ <List.Item>
523
+ <strong>Install dependencies</strong>
524
+ <CodeBlock language="bash" code="npm install" />
525
+ </List.Item>
526
+ <List.Item>
527
+ <strong>Configure your project</strong>
528
+ <Callout variant="tip">Review the config file before proceeding.</Callout>
529
+ </List.Item>
530
+ </List>;
531
+
532
+ {
533
+ /* Unordered with emoji bullet */
534
+ }
351
535
  <List ordered={false} bullet="✅">
352
536
  <List.Item>Beautifully designed components</List.Item>
353
537
  <List.Item>Accessible by default</List.Item>
354
- <List.Item>Fully customizable styling</List.Item>
355
- </List>
356
- ```
538
+ </List>;
357
539
 
358
- #### Unordered list with custom icon
359
-
360
- ```tsx
540
+ {
541
+ /* Unordered with custom SVG icon */
542
+ }
361
543
  <List
362
544
  ordered={false}
363
545
  bulletIcon={
@@ -367,27 +549,47 @@ import { List } from '@roadlittledawn/docs-design-system-react';
367
549
  }
368
550
  >
369
551
  <List.Item>Navigate to the settings page</List.Item>
370
- <List.Item>Select your preferences</List.Item>
371
552
  <List.Item>Save your changes</List.Item>
372
- </List>
553
+ </List>;
373
554
  ```
374
555
 
375
556
  ---
376
557
 
377
558
  ## CodeBlock
378
559
 
379
- The CodeBlock component provides syntax highlighting, copy functionality, and support for multiple tabs and languages.
560
+ Syntax-highlighted code display with copy button, line highlighting, multi-tab support, and optional remote snippet loading.
561
+
562
+ ### When to Use
563
+
564
+ - Any code example in documentation
565
+ - Showing the same code in multiple languages (use `snippets` with language filenames)
566
+ - Showing multiple related files together (use `snippets` with tab titles)
567
+ - When users need a one-click copy button
568
+
569
+ ### When Not to Use
570
+
571
+ - **Inline code within prose** — use an HTML `<code>` tag
572
+ - **Interactive / executable code editors** — use a dedicated code sandbox component
573
+ - **Very short snippets in plain text context** — `<code>` is lighter weight
574
+
575
+ ### `CodeBlock` vs `Tabs` for multi-language examples
576
+
577
+ Use `CodeBlock` with `snippets` when all tabs contain code only and the user is choosing between language variants of the same thing. Use `Tabs` when the content within each tab is richer than just code (explanations, images, mixed content).
578
+
579
+ ### Multi-snippet behavior
580
+
581
+ `CodeBlock` groups `snippets` by their `language` value. If there is more than one distinct `language` across the provided snippets, the component renders a **language dropdown** to switch between language groups. Within the active language group, if there are multiple snippets, it renders **tabs** to switch between those snippets.
380
582
 
381
583
  ### Import
382
584
 
383
585
  ```tsx
384
- import { CodeBlock } from '@roadlittledawn/docs-design-system-react';
586
+ import { CodeBlock } from "@roadlittledawn/docs-design-system-react";
385
587
  ```
386
588
 
387
589
  ### CodeBlock Props
388
590
 
389
591
  | Prop | Type | Default | Description |
390
- |------|------|---------|-------------|
592
+ | --- | --- | --- | --- |
391
593
  | `code` | `string` | — | Single code snippet string. Use `snippets` for multi-tab or multi-language layouts |
392
594
  | `language` | `string` | — | Language for syntax highlighting (e.g. `"typescript"`, `"bash"`, `"python"`) |
393
595
  | `filename` | `string` | — | Optional filename label shown in the header when there is only one snippet |
@@ -399,7 +601,7 @@ import { CodeBlock } from '@roadlittledawn/docs-design-system-react';
399
601
  ### CodeSnippet Type
400
602
 
401
603
  | Prop | Type | Default | Description |
402
- |------|------|---------|-------------|
604
+ | --- | --- | --- | --- |
403
605
  | `code` | `string` | — | The code content |
404
606
  | `language` | `string` | — | Language for syntax highlighting |
405
607
  | `filename` | `string` | — | Optional filename to display |
@@ -413,40 +615,39 @@ JavaScript, TypeScript, JSX, TSX, CSS, Markdown, JSON, Bash, Ruby, Python, Java,
413
615
  For additional languages, use `registerLanguages`:
414
616
 
415
617
  ```ts
416
- import { registerLanguages } from '@roadlittledawn/docs-design-system-react';
618
+ import { registerLanguages } from "@roadlittledawn/docs-design-system-react";
417
619
 
418
620
  await registerLanguages(async () => {
419
- await import('prismjs/components/prism-go');
420
- await import('prismjs/components/prism-rust');
621
+ await import("prismjs/components/prism-go");
622
+ await import("prismjs/components/prism-rust");
421
623
  });
422
624
  ```
423
625
 
424
626
  ### Examples
425
627
 
426
- #### Basic
427
-
428
628
  ```tsx
629
+ {
630
+ /* Basic */
631
+ }
429
632
  <CodeBlock
430
633
  language="typescript"
431
634
  code={`function greet(name: string) {
432
635
  return \`Hello, \${name}!\`;
433
636
  }`}
434
- />
435
- ```
637
+ />;
436
638
 
437
- #### With filename
438
-
439
- ```tsx
639
+ {
640
+ /* With filename */
641
+ }
440
642
  <CodeBlock
441
643
  language="bash"
442
644
  filename="setup.sh"
443
645
  code={`npm install\nnpm run build`}
444
- />
445
- ```
446
-
447
- #### With highlighted lines
646
+ />;
448
647
 
449
- ```tsx
648
+ {
649
+ /* With highlighted lines */
650
+ }
450
651
  <CodeBlock
451
652
  language="javascript"
452
653
  highlightLines={[2, 3, 4]}
@@ -457,36 +658,97 @@ await registerLanguages(async () => {
457
658
  }
458
659
  return total;
459
660
  }`}
460
- />
461
- ```
661
+ />;
462
662
 
463
- #### Multiple tabs
663
+ {
664
+ /* Multi-file tabs */
665
+ }
666
+ <CodeBlock
667
+ snippets={[
668
+ {
669
+ code: `export const Button = () => <button>Click</button>;`,
670
+ language: "jsx",
671
+ tabTitle: "Button.jsx",
672
+ },
673
+ {
674
+ code: `.button { padding: 0.5rem 1rem; }`,
675
+ language: "css",
676
+ tabTitle: "Button.css",
677
+ },
678
+ ]}
679
+ />;
464
680
 
465
- ```tsx
681
+ {
682
+ /* Multi-language dropdown (driven by multiple language values; filenames only affect labels) */
683
+ }
466
684
  <CodeBlock
467
685
  snippets={[
468
- { code: `export const Button = () => <button>Click</button>;`, language: 'jsx', tabTitle: 'Button.jsx' },
469
- { code: `.button { padding: 0.5rem 1rem; }`, language: 'css', tabTitle: 'Button.css' },
686
+ {
687
+ code: `function greet(name: string) { return \`Hello, \${name}!\`; }`,
688
+ language: "typescript",
689
+ filename: "greet.ts",
690
+ },
691
+ {
692
+ code: `def greet(name):\n return f"Hello, {name}!"`,
693
+ language: "python",
694
+ filename: "greet.py",
695
+ },
470
696
  ]}
471
- />
697
+ />;
472
698
  ```
473
699
 
474
700
  ---
475
701
 
476
702
  ## Tabs
477
703
 
478
- Tabs organize and segment related content, reducing cognitive load by allowing users to toggle between views.
704
+ Organizes related but distinct content into switchable panels. Users see one panel at a time but know alternatives exist.
705
+
706
+ ### When to Use
707
+
708
+ - **Segmenting related alternatives**: different solutions for the same task (code in Python vs JavaScript vs Java)
709
+ - **Managing complex/long documents**: breaking extensive documentation into smaller sections
710
+ - **Context-switching**: switching between views like "Overview", "Usage", "API Reference" on the same page
711
+ - **Organizing workflows**: separating student work from instructions, setup from troubleshooting
712
+ - **Reducing clutter**: hiding non-essential information that's less frequently needed
713
+
714
+ ### When Not to Use
715
+
716
+ - **Short scrollable content** — if users can easily scroll through it all, don't tab it
717
+ - **When users need to compare all panels simultaneously** — use side-by-side `Grid` or a table instead
718
+ - **Unrelated content** — tabs should feel like variations of the same topic
719
+ - **Page navigation** — use `Link` or a sidebar nav component
720
+
721
+ ### Best Practices
722
+
723
+ - Always set a logical `defaultActiveTab` (the most common language, most important section, etc.)
724
+ - Tab labels should be concise (1–3 words), descriptive, and clearly distinguish options
725
+ - Limit to 5–6 tabs; more tabs create decision fatigue
726
+ - Avoid nesting tabs inside tab panels
727
+
728
+ ### `Tabs` vs `Collapser`/`CollapserGroup`
729
+
730
+ Use **Tabs** for a small number of parallel, horizontal sections where users rarely need to see all content at once. Use **Collapsers** for:
731
+
732
+ - Long vertical content with many sections
733
+ - FAQs where users scan titles to find relevant items
734
+ - Mobile-first layouts (collapsers stack naturally; tabs can crowd horizontally)
735
+ - When all section headings should be visible simultaneously
479
736
 
480
737
  ### Import
481
738
 
482
739
  ```tsx
483
- import { Tabs, TabList, Tab, TabPanel } from '@roadlittledawn/docs-design-system-react';
740
+ import {
741
+ Tabs,
742
+ TabList,
743
+ Tab,
744
+ TabPanel,
745
+ } from "@roadlittledawn/docs-design-system-react";
484
746
  ```
485
747
 
486
748
  ### Tabs Props
487
749
 
488
750
  | Prop | Type | Default | Description |
489
- |------|------|---------|-------------|
751
+ | --- | --- | --- | --- |
490
752
  | `defaultActiveTab` | `string` | — | ID of the tab that is active by default (uncontrolled mode) |
491
753
  | `activeTab` | `string` | — | Controlled active tab ID. Use with `onTabChange` to manage state externally |
492
754
  | `onTabChange` | `(id: string) => void` | — | Callback fired when the active tab changes |
@@ -495,25 +757,26 @@ import { Tabs, TabList, Tab, TabPanel } from '@roadlittledawn/docs-design-system
495
757
 
496
758
  ### Tab Props
497
759
 
498
- | Prop | Type | Default | Description |
499
- |------|------|---------|-------------|
500
- | `id` | `string` | — | Unique identifier for this tab |
501
- | `children` | `React.ReactNode` | — | Tab label |
502
- | `className` | `string` | `""` | Additional CSS classes |
760
+ | Prop | Type | Default | Description |
761
+ | ----------- | ----------------- | ------- | ------------------------------ |
762
+ | `id` | `string` | — | Unique identifier for this tab |
763
+ | `children` | `React.ReactNode` | — | Tab label |
764
+ | `className` | `string` | `""` | Additional CSS classes |
503
765
 
504
766
  ### TabPanel Props
505
767
 
506
768
  | Prop | Type | Default | Description |
507
- |------|------|---------|-------------|
769
+ | --- | --- | --- | --- |
508
770
  | `id` | `string` | — | ID matching the corresponding Tab |
509
771
  | `children` | `React.ReactNode` | — | Panel content |
510
772
  | `className` | `string` | `""` | Additional CSS classes |
511
773
 
512
774
  ### Examples
513
775
 
514
- #### Basic
515
-
516
776
  ```tsx
777
+ {
778
+ /* Basic */
779
+ }
517
780
  <Tabs defaultActiveTab="overview">
518
781
  <TabList>
519
782
  <Tab id="overview">Overview</Tab>
@@ -529,42 +792,76 @@ import { Tabs, TabList, Tab, TabPanel } from '@roadlittledawn/docs-design-system
529
792
  <TabPanel id="api">
530
793
  <p>This is the API reference section.</p>
531
794
  </TabPanel>
532
- </Tabs>
533
- ```
795
+ </Tabs>;
534
796
 
535
- #### Code examples in different languages
536
-
537
- ```tsx
797
+ {
798
+ /* Code examples in different languages */
799
+ }
538
800
  <Tabs defaultActiveTab="javascript">
539
801
  <TabList>
540
802
  <Tab id="javascript">JavaScript</Tab>
541
803
  <Tab id="python">Python</Tab>
542
804
  </TabList>
543
805
  <TabPanel id="javascript">
544
- <CodeBlock language="javascript" code={`const greeting = "Hello, world!";\nconsole.log(greeting);`} />
806
+ <CodeBlock
807
+ language="javascript"
808
+ code={`const greeting = "Hello, world!";\nconsole.log(greeting);`}
809
+ />
545
810
  </TabPanel>
546
811
  <TabPanel id="python">
547
- <CodeBlock language="python" code={`greeting = "Hello, world!"\nprint(greeting)`} />
812
+ <CodeBlock
813
+ language="python"
814
+ code={`greeting = "Hello, world!"\nprint(greeting)`}
815
+ />
548
816
  </TabPanel>
549
- </Tabs>
817
+ </Tabs>;
550
818
  ```
551
819
 
552
820
  ---
553
821
 
554
822
  ## Collapser
555
823
 
556
- The Collapser component allows users to show and hide content sections to reduce visual clutter.
824
+ An expandable/collapsible content section with smooth animation. Content height adjusts automatically to fit all children, including images and other media that load asynchronously. Use a single `Collapser` for standalone sections; use `CollapserGroup` when you have multiple.
825
+
826
+ ### When to Use
827
+
828
+ - FAQ sections where answers can be toggled individually
829
+ - Hiding advanced options or settings that most users don't need
830
+ - Progressive disclosure — showing a summary first, details on demand
831
+ - When you have lengthy content that doesn't need to be visible at all times
832
+
833
+ ### When Not to Use
834
+
835
+ - **Primary navigation** — use proper nav components
836
+ - **Critical information users must read** — always show it; don't hide it in a collapser
837
+ - **When most users will open all sections** — just show the content; the collapser adds interaction cost without benefit
838
+
839
+ ### Header layout variants
840
+
841
+ Collapser supports four header layouts, controlled by `align` and `icon`:
842
+
843
+ - Default: title left, chevron right
844
+ - With `icon`: icon left, title left, chevron right
845
+ - With `align="right"`: title right, chevron right
846
+ - With `icon` + `align="right"`: icon left, title right, chevron right (used with `CollapserGroup numbered`)
847
+
848
+ ### Keyboard shortcuts
849
+
850
+ - **Enter** or **Space**: toggle expand/collapse
851
+ - For **uncontrolled** `Collapser` instances (no `open` prop; not managed by `CollapserGroup`), additional shortcuts are available:
852
+ - **s** or **f**: show/expand
853
+ - **h**: hide/collapse
557
854
 
558
855
  ### Import
559
856
 
560
857
  ```tsx
561
- import { Collapser } from '@roadlittledawn/docs-design-system-react';
858
+ import { Collapser } from "@roadlittledawn/docs-design-system-react";
562
859
  ```
563
860
 
564
861
  ### Props
565
862
 
566
863
  | Prop | Type | Default | Description |
567
- |------|------|---------|-------------|
864
+ | --- | --- | --- | --- |
568
865
  | `title` | `string \| ReactNode` | — | Title text or element displayed in the collapsible header |
569
866
  | `id` | `string` | — | Optional ID for the title element (useful for anchor links) |
570
867
  | `defaultOpen` | `boolean` | `false` | Whether the collapser should be open by default (uncontrolled) |
@@ -578,46 +875,65 @@ import { Collapser } from '@roadlittledawn/docs-design-system-react';
578
875
 
579
876
  ### Examples
580
877
 
581
- #### Basic
582
-
583
878
  ```tsx
879
+ {
880
+ /* Basic */
881
+ }
584
882
  <Collapser title="Click to expand">
585
883
  <p>This content is hidden by default.</p>
586
- </Collapser>
587
- ```
588
-
589
- #### Open by default
884
+ </Collapser>;
590
885
 
591
- ```tsx
886
+ {
887
+ /* Open by default */
888
+ }
592
889
  <Collapser title="This section starts open" defaultOpen>
593
890
  <p>This collapser is open by default.</p>
594
- </Collapser>
595
- ```
891
+ </Collapser>;
596
892
 
597
- #### With icon and right-aligned title
598
-
599
- ```tsx
893
+ {
894
+ /* With icon and right-aligned title */
895
+ }
600
896
  <Collapser title="Quick start guide" align="right" icon={<YourIcon />}>
601
897
  <p>Content here.</p>
602
- </Collapser>
898
+ </Collapser>;
603
899
  ```
604
900
 
605
901
  ---
606
902
 
607
903
  ## CollapserGroup
608
904
 
609
- CollapserGroup provides a container for multiple Collapser components with built-in spacing and optional accordion behavior.
905
+ Container for multiple `Collapser` components with consistent spacing and optional accordion behavior. Always use `CollapserGroup` when you have 2+ collapsers together.
906
+
907
+ ### When to Use
908
+
909
+ - FAQ sections with multiple questions and answers
910
+ - Accordion-style navigation or categorized content sections
911
+ - Any grouped collapsible content that needs consistent spacing
912
+ - When you want only one section open at a time (accordion mode: `allowMultiple={false}`)
913
+ - Numbered step-by-step flows where each step has expand/collapse behavior (use `numbered`)
914
+
915
+ ### When Not to Use
916
+
917
+ - **A single collapser** — use `Collapser` directly; `CollapserGroup` is purely for managing groups
918
+ - **When collapsers need radically different spacing or independent behavior**
919
+
920
+ ### `numbered` prop
921
+
922
+ When `numbered={true}`, `CollapserGroup` automatically injects sequential step numbers into each child `Collapser`. This works in MDX and component-map contexts. Combine with `align="right"` and `icon` on each `Collapser` for a polished step-by-step layout. Override the step number color with `--dds-collapser-step-number-color`.
610
923
 
611
924
  ### Import
612
925
 
613
926
  ```tsx
614
- import { CollapserGroup, Collapser } from '@roadlittledawn/docs-design-system-react';
927
+ import {
928
+ CollapserGroup,
929
+ Collapser,
930
+ } from "@roadlittledawn/docs-design-system-react";
615
931
  ```
616
932
 
617
933
  ### Props
618
934
 
619
935
  | Prop | Type | Default | Description |
620
- |------|------|---------|-------------|
936
+ | --- | --- | --- | --- |
621
937
  | `children` | `React.ReactNode` | — | Collapser components to render inside the group |
622
938
  | `spacing` | `string` | `"0.5rem"` | CSS gap value between collapser items |
623
939
  | `allowMultiple` | `boolean` | `true` | Allow multiple collapsers to be open simultaneously. When false, opening one closes the others (accordion mode) |
@@ -628,9 +944,10 @@ import { CollapserGroup, Collapser } from '@roadlittledawn/docs-design-system-re
628
944
 
629
945
  ### Examples
630
946
 
631
- #### FAQ (accordion mode)
632
-
633
947
  ```tsx
948
+ {
949
+ /* FAQ (accordion mode — only one open at a time) */
950
+ }
634
951
  <CollapserGroup allowMultiple={false}>
635
952
  <Collapser title="What is this documentation system?">
636
953
  <p>A comprehensive design system for documentation sites.</p>
@@ -638,38 +955,63 @@ import { CollapserGroup, Collapser } from '@roadlittledawn/docs-design-system-re
638
955
  <Collapser title="How do I get started?">
639
956
  <p>Install the package and explore the components.</p>
640
957
  </Collapser>
641
- </CollapserGroup>
642
- ```
643
-
644
- #### Numbered steps with icons
958
+ </CollapserGroup>;
645
959
 
646
- ```tsx
960
+ {
961
+ /* Numbered steps with icons */
962
+ }
647
963
  <CollapserGroup numbered>
648
964
  <Collapser title="Install dependencies" align="right" icon={<YourIcon />}>
649
- <p>Run <code>npm install</code>.</p>
965
+ <p>
966
+ Run <code>npm install</code>.
967
+ </p>
650
968
  </Collapser>
651
969
  <Collapser title="Configure your project" align="right" icon={<YourIcon />}>
652
970
  <p>Update configuration files.</p>
653
971
  </Collapser>
654
- </CollapserGroup>
972
+ </CollapserGroup>;
655
973
  ```
656
974
 
657
975
  ---
658
976
 
659
977
  ## Popover
660
978
 
661
- A hover/tap-activated popover for enriching inline content in documentation. Built on the native Popover API for reliable top-layer rendering.
979
+ A hover/tap-activated floating panel for enriching inline documentation content. Built on the native Popover API no z-index conflicts, no overflow clipping.
980
+
981
+ ### When to Use
982
+
983
+ - **Glossary terms** — inline term definitions that would interrupt reading flow if expanded in-place; wrap the term in a `Popover` with the `glossary` prop
984
+ - **Link previews** — let users get context about a page or resource without navigating away; use the `preview` prop
985
+ - **On-demand contextual information** — any content that benefits from being triggered rather than always visible
986
+
987
+ ### When Not to Use
988
+
989
+ - **Critical information users must read** — use `Callout` instead; popovers are opt-in
990
+ - **Primary navigation** — use `Link` or nav components
991
+ - **Content that needs persistent visibility** — if users always need to see it, don't hide it in a popover
992
+
993
+ ### Mobile behavior
994
+
995
+ On screens ≤ 640px, the popover renders as a **bottom sheet** instead of a floating panel. Hover doesn't apply on touch devices; the popover toggles on tap.
996
+
997
+ ### Content modes (choose one)
998
+
999
+ 1. **`content`** — arbitrary `ReactNode`; use when the built-in templates don't fit
1000
+ 2. **`glossary`** — structured `{ term, title, definition }` template for definitions
1001
+ 3. **`preview`** — structured `{ title, excerpt, imageUrl, href }` for Wikipedia-style previews
1002
+
1003
+ Only one mode is used at a time, checked in the order listed above.
662
1004
 
663
1005
  ### Import
664
1006
 
665
1007
  ```tsx
666
- import { Popover } from '@roadlittledawn/docs-design-system-react';
1008
+ import { Popover } from "@roadlittledawn/docs-design-system-react";
667
1009
  ```
668
1010
 
669
1011
  ### Popover Props
670
1012
 
671
1013
  | Prop | Type | Default | Description |
672
- |------|------|---------|-------------|
1014
+ | --- | --- | --- | --- |
673
1015
  | `content` | `ReactNode` | — | Arbitrary React content inside the popover. Use when built-in templates don't fit |
674
1016
  | `glossary` | `GlossaryData` | — | Renders a styled glossary definition popover |
675
1017
  | `preview` | `PreviewData` | — | Renders a Wikipedia-style content preview |
@@ -683,44 +1025,45 @@ import { Popover } from '@roadlittledawn/docs-design-system-react';
683
1025
  ### GlossaryData Type
684
1026
 
685
1027
  | Prop | Type | Description |
686
- |------|------|-------------|
1028
+ | --- | --- | --- |
687
1029
  | `term` | `string` | The canonical term (used for semantic markup) |
688
1030
  | `title` | `string` | Display title shown in the popover header |
689
1031
  | `definition` | `ReactNode` | Definition content. Accepts ReactNode so you can pre-render markdown |
690
1032
 
691
1033
  ### PreviewData Type
692
1034
 
693
- | Prop | Type | Default | Description |
694
- |------|------|---------|-------------|
695
- | `title` | `string` | — | Page or article title |
696
- | `excerpt` | `ReactNode` | — | Short excerpt or summary |
697
- | `imageUrl` | `string` | — | Optional featured image URL |
698
- | `href` | `string` | — | Optional URL to the full content |
699
- | `linkText` | `string` | `"Read more"` | Link text |
1035
+ | Prop | Type | Default | Description |
1036
+ | ---------- | ----------- | ------------- | -------------------------------- |
1037
+ | `title` | `string` | — | Page or article title |
1038
+ | `excerpt` | `ReactNode` | — | Short excerpt or summary |
1039
+ | `imageUrl` | `string` | — | Optional featured image URL |
1040
+ | `href` | `string` | — | Optional URL to the full content |
1041
+ | `linkText` | `string` | `"Read more"` | Link text |
700
1042
 
701
1043
  ### Examples
702
1044
 
703
- #### Glossary definition
704
-
705
1045
  ```tsx
1046
+ {
1047
+ /* Glossary definition */
1048
+ }
706
1049
  <p>
707
- Modern software relies on{' '}
1050
+ Modern software relies on{" "}
708
1051
  <Popover
709
1052
  glossary={{
710
1053
  term: "observability",
711
1054
  title: "Observability",
712
- definition: "The ability to understand the internal state of a system by examining its external outputs.",
1055
+ definition:
1056
+ "The ability to understand the internal state of a system by examining its external outputs.",
713
1057
  }}
714
1058
  >
715
1059
  observability
716
- </Popover>
717
- {' '}to diagnose issues quickly.
718
- </p>
719
- ```
720
-
721
- #### Content preview
1060
+ </Popover>{" "}
1061
+ to diagnose issues quickly.
1062
+ </p>;
722
1063
 
723
- ```tsx
1064
+ {
1065
+ /* Content preview */
1066
+ }
724
1067
  <Popover
725
1068
  size="lg"
726
1069
  preview={{
@@ -731,37 +1074,54 @@ import { Popover } from '@roadlittledawn/docs-design-system-react';
731
1074
  }}
732
1075
  >
733
1076
  New Relic
734
- </Popover>
735
- ```
1077
+ </Popover>;
736
1078
 
737
- #### Custom content
738
-
739
- ```tsx
740
- <Popover content={<div style={{ padding: '1rem' }}>Custom content here</div>}>
1079
+ {
1080
+ /* Custom content */
1081
+ }
1082
+ <Popover content={<div style={{ padding: "1rem" }}>Custom content here</div>}>
741
1083
  hover me
742
- </Popover>
1084
+ </Popover>;
743
1085
  ```
744
1086
 
745
1087
  ---
746
1088
 
747
1089
  ## Grid and Column
748
1090
 
749
- Layout primitive for multi-column documentation content. Supports equal and fractional column splits, configurable responsive stacking, optional column dividers, borders, and background colors.
1091
+ Layout primitive for multi-column documentation content. Use `Grid` when content columns differ in width, type, or purpose. Use `CardGrid` for uniform card grids.
1092
+
1093
+ ### When to Use
1094
+
1095
+ - **Image + annotation** — screenshot or diagram on one side, feature callouts on the other
1096
+ - **Tutorial with live code** — prose instructions on the left, sticky code panel on the right
1097
+ - **Side-by-side comparison** — before/after, two approaches, option A vs option B
1098
+ - **Asymmetric splits** — narrow sidebar label alongside wide content
1099
+ - **Feature highlight panel** — scannable feature collapsers on one side, product screenshot on the other
1100
+
1101
+ ### When Not to Use
1102
+
1103
+ - **Uniform card grids** — use `CardGrid` instead; it's simpler and handles equal-height automatically
1104
+ - **Single column of content** — use standard block-level markup
1105
+ - **Data tables** — use `Table`
1106
+
1107
+ ### `Grid` vs `CardGrid`
1108
+
1109
+ Use `Grid` when the columns have different widths, different content types, or you need layout features like sticky columns, dividers, or background colors. Use `CardGrid` when all columns contain the same type of `Card` component.
750
1110
 
751
1111
  ### Import
752
1112
 
753
1113
  ```tsx
754
- import { Grid, Column } from '@roadlittledawn/docs-design-system-react';
1114
+ import { Grid, Column } from "@roadlittledawn/docs-design-system-react";
755
1115
  ```
756
1116
 
757
1117
  ### Grid Props
758
1118
 
759
1119
  | Prop | Type | Default | Description |
760
- |------|------|---------|-------------|
1120
+ | --- | --- | --- | --- |
761
1121
  | `columns` | `number \| number[]` | `2` | Number of equal columns, or an array of fractional widths (e.g. `[1, 2]` for 1/3 + 2/3) |
762
1122
  | `gap` | `string` | `"md"` | Space between columns. Use `"sm"`, `"md"`, or `"lg"` for design tokens, or any CSS length (e.g. `"16px"`) |
763
1123
  | `stackAt` | `"sm" \| "md" \| "lg" \| "never"` | `"md"` | Breakpoint at which columns collapse to a single vertical stack |
764
- | `columnDivider` | `BorderConfig` | — | Vertical dividing line between columns |
1124
+ | `columnDivider` | `BorderConfig` | — | Vertical dividing line between columns. Converts to a horizontal rule when stacked |
765
1125
  | `topBorder` | `BorderConfig` | — | Horizontal rule rendered above the grid |
766
1126
  | `bottomBorder` | `BorderConfig` | — | Horizontal rule rendered below the grid |
767
1127
  | `align` | `"start" \| "center" \| "end" \| "stretch"` | `"stretch"` | Vertical alignment of content within each column |
@@ -772,9 +1132,9 @@ import { Grid, Column } from '@roadlittledawn/docs-design-system-react';
772
1132
  ### Column Props
773
1133
 
774
1134
  | Prop | Type | Default | Description |
775
- |------|------|---------|-------------|
1135
+ | --- | --- | --- | --- |
776
1136
  | `span` | `number` | `1` | How many grid columns this item should span |
777
- | `sticky` | `boolean` | `false` | Makes the column sticky while adjacent columns scroll. Useful for tutorial-style layouts with a persistent code panel |
1137
+ | `sticky` | `boolean` | `false` | Makes the column sticky while adjacent columns scroll. Useful for tutorial-style layouts with a persistent code panel. Automatically disabled when the grid stacks |
778
1138
  | `backgroundColor` | `string` | — | Background color applied to the column |
779
1139
  | `className` | `string` | `""` | Additional CSS classes |
780
1140
  | `children` | `ReactNode` | — | Column content |
@@ -782,49 +1142,117 @@ import { Grid, Column } from '@roadlittledawn/docs-design-system-react';
782
1142
  ### BorderConfig Type
783
1143
 
784
1144
  | Prop | Type | Default | Description |
785
- |------|------|---------|-------------|
1145
+ | --- | --- | --- | --- |
786
1146
  | `thickness` | `number` | `1` | Line thickness in pixels |
787
1147
  | `color` | `string` | — | Line color (defaults to the `--dds-grid-divider-color` token) |
788
1148
 
789
1149
  ### Examples
790
1150
 
791
- #### Two equal columns
792
-
793
1151
  ```tsx
1152
+ {
1153
+ /* Two equal columns */
1154
+ }
794
1155
  <Grid columns={2}>
795
1156
  <Column>Column 1 content</Column>
796
1157
  <Column>Column 2 content</Column>
797
- </Grid>
798
- ```
1158
+ </Grid>;
799
1159
 
800
- #### Asymmetric 1/3 + 2/3 split
801
-
802
- ```tsx
1160
+ {
1161
+ /* Asymmetric 1/3 + 2/3 split */
1162
+ }
803
1163
  <Grid columns={[1, 2]}>
804
1164
  <Column>Narrow (1/3)</Column>
805
1165
  <Column>Wide (2/3)</Column>
806
- </Grid>
807
- ```
1166
+ </Grid>;
808
1167
 
809
- #### Tutorial with sticky code panel
810
-
811
- ```tsx
1168
+ {
1169
+ /* Tutorial with sticky code panel */
1170
+ }
812
1171
  <Grid columns={2} stackAt="lg" gap="lg" columnDivider={{ thickness: 2 }}>
813
1172
  <Column>
814
- <p><strong>Step 1 — Install dependencies</strong></p>
1173
+ <p>
1174
+ <strong>Step 1 — Install dependencies</strong>
1175
+ </p>
815
1176
  <p>Run the installer and follow the prompts.</p>
816
1177
  </Column>
817
1178
  <Column sticky>
818
1179
  <CodeBlock language="bash" code="npm install" />
819
1180
  </Column>
820
- </Grid>
1181
+ </Grid>;
1182
+
1183
+ {/* Feature highlight panel — collapsers + product screenshot */}
1184
+ <Grid columns={[1, 2]} gap="lg" align="start">
1185
+ <Column>
1186
+ <CollapserGroup>
1187
+ <Collapser title="Real-time alerts" align="right" icon={<YourIcon />}>
1188
+ Get notified the moment a threshold is crossed, with no polling delay.
1189
+ </Collapser>
1190
+ <Collapser title="Custom dashboards" align="right" icon={<YourIcon />}>
1191
+ Drag-and-drop widgets let you arrange metrics exactly as you need them.
1192
+ </Collapser>
1193
+ <Collapser title="Role-based access" align="right" icon={<YourIcon />}>
1194
+ Grant view-only, editor, or admin rights per team without extra tooling.
1195
+ </Collapser>
1196
+ <Collapser title="One-click integrations" align="right" icon={<YourIcon />}>
1197
+ Connect to Slack, PagerDuty, and 40+ other tools from the settings panel.
1198
+ </Collapser>
1199
+ </CollapserGroup>
1200
+ </Column>
1201
+ <Column>
1202
+ <img
1203
+ src="/images/product-screenshot.png"
1204
+ alt="Product dashboard showing real-time alert panel"
1205
+ style={{ width: "100%", borderRadius: "8px" }}
1206
+ />
1207
+ </Column>
1208
+ </Grid>;
1209
+
1210
+ {
1211
+ /* Three columns with top/bottom borders (feature grid panel) */
1212
+ }
1213
+ <Grid
1214
+ columns={3}
1215
+ topBorder={{ color: "#ccc" }}
1216
+ bottomBorder={{ color: "#ccc" }}
1217
+ >
1218
+ <Column>
1219
+ <strong>Feature A</strong>
1220
+ <p>Description.</p>
1221
+ </Column>
1222
+ <Column>
1223
+ <strong>Feature B</strong>
1224
+ <p>Description.</p>
1225
+ </Column>
1226
+ <Column>
1227
+ <strong>Feature C</strong>
1228
+ <p>Description.</p>
1229
+ </Column>
1230
+ </Grid>;
821
1231
  ```
822
1232
 
823
1233
  ---
824
1234
 
825
1235
  ## Table
826
1236
 
827
- Table displays structured, relational data in rows and columns. Supports sortable columns, sticky header, borderless variant, and responsive horizontal scrolling.
1237
+ Structured relational data in rows and columns for reference documentation.
1238
+
1239
+ ### When to Use
1240
+
1241
+ - Documenting configuration options, API parameters, or CLI flags
1242
+ - Comparing multiple items across the same set of attributes (e.g., pricing tiers, OS compatibility)
1243
+ - Reference data that users want to scan or sort (package versions, settings)
1244
+ - Prefer using `Table` component over markdown syntax in MDX files
1245
+
1246
+ ### When Not to Use
1247
+
1248
+ - **Page layout** — use CSS Grid or Flexbox; `Table` is for data, not layout
1249
+ - **Fewer than two meaningful columns** — use a list instead
1250
+ - **Rows with very different shapes** — if rows don't share the same columns, a table isn't the right format
1251
+
1252
+ ### Variants
1253
+
1254
+ - `default` — all cell and outer borders; good for dense reference tables
1255
+ - `borderless` — only row dividers; cleaner look for modern documentation sites; common for prop reference tables
828
1256
 
829
1257
  ### Import
830
1258
 
@@ -836,13 +1264,13 @@ import {
836
1264
  TableRow,
837
1265
  TableHeaderCell,
838
1266
  TableCell,
839
- } from '@roadlittledawn/docs-design-system-react';
1267
+ } from "@roadlittledawn/docs-design-system-react";
840
1268
  ```
841
1269
 
842
1270
  ### Table Props
843
1271
 
844
1272
  | Prop | Type | Default | Description |
845
- |------|------|---------|-------------|
1273
+ | --- | --- | --- | --- |
846
1274
  | `children` | `React.ReactNode` | — | Typically `TableHead` and `TableBody` |
847
1275
  | `variant` | `"default" \| "borderless"` | `"default"` | `"default"` renders all borders; `"borderless"` shows only row top/bottom borders |
848
1276
  | `stickyHeader` | `boolean` | `false` | When true, the header row sticks to the top of the scroll container while scrolling. Pair with `style={{ maxHeight: '...' }}` |
@@ -854,7 +1282,7 @@ import {
854
1282
  ### TableHeaderCell Props
855
1283
 
856
1284
  | Prop | Type | Default | Description |
857
- |------|------|---------|-------------|
1285
+ | --- | --- | --- | --- |
858
1286
  | `children` | `React.ReactNode` | — | Cell content / column label |
859
1287
  | `sortKey` | `string` | — | Unique key for this column. When provided the column becomes sortable |
860
1288
  | `align` | `"left" \| "center" \| "right"` | `"left"` | Text alignment |
@@ -863,16 +1291,17 @@ import {
863
1291
  ### TableCell Props
864
1292
 
865
1293
  | Prop | Type | Default | Description |
866
- |------|------|---------|-------------|
1294
+ | --- | --- | --- | --- |
867
1295
  | `children` | `React.ReactNode` | — | Cell content |
868
1296
  | `align` | `"left" \| "center" \| "right"` | `"left"` | Text alignment |
869
1297
  | `className` | `string` | `""` | Additional CSS classes |
870
1298
 
871
1299
  ### Examples
872
1300
 
873
- #### Basic table
874
-
875
1301
  ```tsx
1302
+ {
1303
+ /* Basic table */
1304
+ }
876
1305
  <Table>
877
1306
  <TableHead>
878
1307
  <TableRow>
@@ -888,13 +1317,17 @@ import {
888
1317
  <TableCell>Active</TableCell>
889
1318
  </TableRow>
890
1319
  </TableBody>
891
- </Table>
892
- ```
893
-
894
- #### Borderless with sorting
1320
+ </Table>;
895
1321
 
896
- ```tsx
897
- <Table variant="borderless" onSort={(key, direction) => { /* sort your data */ }}>
1322
+ {
1323
+ /* Borderless with sortable columns */
1324
+ }
1325
+ <Table
1326
+ variant="borderless"
1327
+ onSort={(key, direction) => {
1328
+ /* sort your data */
1329
+ }}
1330
+ >
898
1331
  <TableHead>
899
1332
  <TableRow>
900
1333
  <TableHeaderCell sortKey="name">Name</TableHeaderCell>
@@ -909,50 +1342,67 @@ import {
909
1342
  </TableRow>
910
1343
  ))}
911
1344
  </TableBody>
912
- </Table>
913
- ```
1345
+ </Table>;
914
1346
 
915
- #### Sticky header
916
-
917
- ```tsx
918
- <Table stickyHeader style={{ maxHeight: '300px' }}>
1347
+ {
1348
+ /* Sticky header for long tables */
1349
+ }
1350
+ <Table stickyHeader style={{ maxHeight: "300px" }}>
919
1351
  <TableHead>
920
1352
  <TableRow>
921
1353
  <TableHeaderCell>Name</TableHeaderCell>
922
1354
  <TableHeaderCell>Department</TableHeaderCell>
923
1355
  </TableRow>
924
1356
  </TableHead>
925
- <TableBody>
926
- {/* many rows */}
927
- </TableBody>
928
- </Table>
1357
+ <TableBody>{/* many rows */}</TableBody>
1358
+ </Table>;
929
1359
  ```
930
1360
 
931
1361
  ---
932
1362
 
933
1363
  ## Breadcrumb
934
1364
 
935
- Breadcrumb navigation component. Renders a `<nav aria-label="Breadcrumb">` with an ordered list of segments. The last item receives `aria-current="page"`. Delimiters are marked `aria-hidden` so screen readers skip them.
1365
+ Hierarchical navigation trail showing a user's current location within the documentation structure.
1366
+
1367
+ ### When to Use
1368
+
1369
+ - Showing location within a multi-level documentation hierarchy
1370
+ - Providing quick navigation back to parent sections
1371
+ - Pages nested 2 or more levels deep
1372
+
1373
+ ### When Not to Use
1374
+
1375
+ - **Top-level landing pages** — breadcrumbs have no value when hierarchy is obvious (the user is already at the root)
1376
+ - **Sequential step indicators** — use a stepper or progress component; breadcrumbs represent hierarchy, not sequence
1377
+
1378
+ ### Mobile behavior
1379
+
1380
+ For long breadcrumb trails on mobile:
1381
+
1382
+ - `collapseOnMobile` — hides middle segments behind an ellipsis; tap to expand
1383
+ - `scrollOnMobile` — allows the full trail to scroll horizontally
1384
+
1385
+ These can be combined: collapse first, and if expanded, scroll horizontally.
936
1386
 
937
1387
  ### Import
938
1388
 
939
1389
  ```tsx
940
- import { Breadcrumb } from '@roadlittledawn/docs-design-system-react';
1390
+ import { Breadcrumb } from "@roadlittledawn/docs-design-system-react";
941
1391
  ```
942
1392
 
943
1393
  ### Types
944
1394
 
945
1395
  ```ts
946
1396
  interface BreadcrumbItem {
947
- label: string; // Display text for the segment
948
- href?: string; // Optional URL; omit for the current (last) page
1397
+ label: string; // Display text for the segment
1398
+ href?: string; // Optional URL; omit for the current (last) page
949
1399
  }
950
1400
  ```
951
1401
 
952
1402
  ### Props
953
1403
 
954
1404
  | Prop | Type | Default | Description |
955
- |------|------|---------|-------------|
1405
+ | --- | --- | --- | --- |
956
1406
  | `items` | `BreadcrumbItem[]` | — | Ordered list of path segments, root first |
957
1407
  | `delimiter` | `ReactNode` | `"/"` | Separator between segments. Accepts a string or any ReactNode |
958
1408
  | `size` | `"sm" \| "md"` | `"md"` | Size variant controlling font size |
@@ -962,62 +1412,82 @@ interface BreadcrumbItem {
962
1412
 
963
1413
  ### Examples
964
1414
 
965
- #### Basic
966
-
967
1415
  ```tsx
1416
+ {
1417
+ /* Basic */
1418
+ }
968
1419
  <Breadcrumb
969
1420
  items={[
970
- { label: 'Home', href: '/' },
971
- { label: 'Docs', href: '/docs' },
972
- { label: 'Getting Started' },
1421
+ { label: "Home", href: "/" },
1422
+ { label: "Docs", href: "/docs" },
1423
+ { label: "Getting Started" },
973
1424
  ]}
974
- />
975
- ```
1425
+ />;
976
1426
 
977
- #### Small size with custom delimiter
978
-
979
- ```tsx
1427
+ {
1428
+ /* Small size with custom delimiter */
1429
+ }
980
1430
  <Breadcrumb
981
1431
  size="sm"
982
1432
  delimiter="›"
983
1433
  items={[
984
- { label: 'Home', href: '/' },
985
- { label: 'Reference', href: '/reference' },
986
- { label: 'API' },
1434
+ { label: "Home", href: "/" },
1435
+ { label: "Reference", href: "/reference" },
1436
+ { label: "API" },
987
1437
  ]}
988
- />
989
- ```
990
-
991
- #### Collapse middle items on mobile
1438
+ />;
992
1439
 
993
- ```tsx
1440
+ {
1441
+ /* Collapse middle items on mobile */
1442
+ }
994
1443
  <Breadcrumb
995
1444
  collapseOnMobile
996
1445
  items={[
997
- { label: 'Home', href: '/' },
998
- { label: 'Products', href: '/products' },
999
- { label: 'Widgets', href: '/products/widgets' },
1000
- { label: 'Details' },
1446
+ { label: "Home", href: "/" },
1447
+ { label: "Products", href: "/products" },
1448
+ { label: "Widgets", href: "/products/widgets" },
1449
+ { label: "Details" },
1001
1450
  ]}
1002
- />
1451
+ />;
1003
1452
  ```
1004
1453
 
1005
1454
  ---
1006
1455
 
1007
1456
  ## Icon
1008
1457
 
1009
- Renders an SVG icon without bundling any specific icon library. Accepts a React SVG component (e.g. imported with SVGR or defined inline) or a raw SVG string, making it easy to use your own icon library.
1458
+ Renders an SVG icon without bundling any specific icon library. You bring your own SVG either as a React component or a raw SVG string.
1459
+
1460
+ ### When to Use
1461
+
1462
+ - Rendering icons imported with SVGR (`import { ReactComponent as Star } from './star.svg'`)
1463
+ - Rendering inline SVG components defined in your code
1464
+ - Rendering a trusted raw SVG string from your project's assets
1465
+ - When you need consistent accessible handling (decorative vs meaningful icons)
1466
+
1467
+ ### When Not to Use
1468
+
1469
+ - **Untrusted or user-supplied SVG strings** — the raw string path uses `dangerouslySetInnerHTML` without sanitization. Only use this with SVGs you control
1470
+ - **Purely decorative shapes achievable with CSS** — no need for the component overhead
1471
+
1472
+ ### Accessibility
1473
+
1474
+ The `Icon` component manages all accessibility attributes automatically:
1475
+
1476
+ - **Decorative icons** (no `aria-label`) — receive `aria-hidden="true"` and are ignored by screen readers
1477
+ - **Meaningful icons** (with `aria-label`) — receive `role="img"` and are announced by screen readers
1478
+
1479
+ Do **not** include `aria-hidden`, `role`, or `aria-label` inside your SVG component itself — let `Icon` handle this.
1010
1480
 
1011
1481
  ### Import
1012
1482
 
1013
1483
  ```tsx
1014
- import { Icon } from '@roadlittledawn/docs-design-system-react';
1484
+ import { Icon } from "@roadlittledawn/docs-design-system-react";
1015
1485
  ```
1016
1486
 
1017
1487
  ### Props
1018
1488
 
1019
1489
  | Prop | Type | Default | Description |
1020
- |------|------|---------|-------------|
1490
+ | --- | --- | --- | --- |
1021
1491
  | `svg` | `React.ComponentType<React.SVGProps<SVGSVGElement>> \| string` | — | SVG to render — accepts a React SVG component or a raw SVG string |
1022
1492
  | `size` | `number` | `16` | Width and height in pixels |
1023
1493
  | `className` | `string` | `""` | Additional CSS class names |
@@ -1025,17 +1495,13 @@ import { Icon } from '@roadlittledawn/docs-design-system-react';
1025
1495
 
1026
1496
  ### Examples
1027
1497
 
1028
- #### React SVG component (SVGR)
1029
-
1030
1498
  ```tsx
1499
+ {/* React SVG component (SVGR) */}
1031
1500
  import { ReactComponent as ChevronIcon } from './chevron.svg';
1032
1501
 
1033
1502
  <Icon svg={ChevronIcon} size={20} aria-label="Expand" />
1034
- ```
1035
1503
 
1036
- #### Inline SVG function (define props to forward size/className/aria-*)
1037
-
1038
- ```tsx
1504
+ {/* Inline SVG function */}
1039
1505
  const StarIcon = (props: React.SVGProps<SVGSVGElement>) => (
1040
1506
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" {...props}>
1041
1507
  <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" />
@@ -1043,28 +1509,13 @@ const StarIcon = (props: React.SVGProps<SVGSVGElement>) => (
1043
1509
  );
1044
1510
 
1045
1511
  <Icon svg={StarIcon} size={24} />
1046
- ```
1047
-
1048
- #### Raw SVG string
1049
1512
 
1050
- ```tsx
1513
+ {/* Raw SVG string (only use with trusted content) */}
1051
1514
  const closeIconSvg = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>`;
1052
1515
 
1053
1516
  <Icon svg={closeIconSvg} size={24} aria-label="Close" />
1054
- ```
1055
-
1056
- #### Decorative vs meaningful icons
1057
1517
 
1058
- ```tsx
1059
- {/* Decorative hidden from screen readers */}
1060
- <Icon svg={StarIcon} size={16} />
1061
-
1062
- {/* Meaningful — announced as "Favorite" */}
1063
- <Icon svg={StarIcon} size={16} aria-label="Favorite" />
1518
+ {/* Decorative vs meaningful */}
1519
+ <Icon svg={StarIcon} size={16} /> {/* hidden from screen readers */}
1520
+ <Icon svg={StarIcon} size={16} aria-label="Favorite" /> {/* announced as "Favorite" */}
1064
1521
  ```
1065
-
1066
- ### Accessibility notes
1067
-
1068
- - Do **not** include `aria-hidden`, `role`, or `aria-label` attributes inside your SVG component. The `Icon` component manages all accessibility attributes.
1069
- - When passing a raw SVG string, do **not** include accessibility attributes in the string itself.
1070
- - Do **not** pass untrusted or user-supplied SVG strings — the raw string path uses `dangerouslySetInnerHTML` without sanitization.