@discourser/design-system 0.3.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -4
- package/dist/styles.css +5126 -0
- package/guidelines/Guidelines.md +92 -41
- package/guidelines/components/accordion.md +732 -0
- package/guidelines/components/avatar.md +1015 -0
- package/guidelines/components/badge.md +728 -0
- package/guidelines/components/button.md +75 -40
- package/guidelines/components/card.md +84 -25
- package/guidelines/components/checkbox.md +671 -0
- package/guidelines/components/dialog.md +619 -31
- package/guidelines/components/drawer.md +1616 -0
- package/guidelines/components/heading.md +576 -0
- package/guidelines/components/icon-button.md +92 -37
- package/guidelines/components/input-addon.md +685 -0
- package/guidelines/components/input-group.md +830 -0
- package/guidelines/components/input.md +92 -37
- package/guidelines/components/popover.md +1271 -0
- package/guidelines/components/progress.md +836 -0
- package/guidelines/components/radio-group.md +852 -0
- package/guidelines/components/select.md +1662 -0
- package/guidelines/components/skeleton.md +802 -0
- package/guidelines/components/slider.md +911 -0
- package/guidelines/components/spinner.md +783 -0
- package/guidelines/components/switch.md +105 -38
- package/guidelines/components/tabs.md +1488 -0
- package/guidelines/components/textarea.md +495 -0
- package/guidelines/components/toast.md +784 -0
- package/guidelines/components/tooltip.md +912 -0
- package/guidelines/design-tokens/colors.md +309 -72
- package/guidelines/design-tokens/elevation.md +615 -45
- package/guidelines/design-tokens/spacing.md +654 -74
- package/guidelines/design-tokens/typography.md +432 -50
- package/guidelines/overview-components.md +60 -8
- package/guidelines/overview-imports.md +314 -0
- package/guidelines/overview-patterns.md +3852 -0
- package/package.json +4 -2
|
@@ -0,0 +1,576 @@
|
|
|
1
|
+
# Heading
|
|
2
|
+
|
|
3
|
+
**Purpose:** Semantic heading component for establishing content hierarchy and structure following Material Design 3 typography patterns.
|
|
4
|
+
|
|
5
|
+
## When to Use This Component
|
|
6
|
+
|
|
7
|
+
Use Heading when you need to **establish semantic document structure and visual hierarchy** with properly ordered heading levels (h1-h6).
|
|
8
|
+
|
|
9
|
+
### Decision Tree
|
|
10
|
+
|
|
11
|
+
| Scenario | Use Heading? | Alternative | Reasoning |
|
|
12
|
+
| ---------------------------- | ------------ | ----------------------------- | ----------------------------------------------------- |
|
|
13
|
+
| Page titles, section headers | ✅ Yes | - | Headings provide semantic structure for accessibility |
|
|
14
|
+
| Article titles, card headers | ✅ Yes | - | Establishes content hierarchy |
|
|
15
|
+
| Document outline structure | ✅ Yes | - | Screen readers use headings for navigation |
|
|
16
|
+
| Emphasized body text | ❌ No | Text with `fontWeight="bold"` | Don't use headings just for styling |
|
|
17
|
+
| Navigation labels | ❌ No | Text or label elements | Navigation isn't part of content hierarchy |
|
|
18
|
+
| Button labels or UI text | ❌ No | Button or Text | Headings are for content structure |
|
|
19
|
+
|
|
20
|
+
### Component Comparison
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
// ✅ Heading - Page and section structure
|
|
24
|
+
<article>
|
|
25
|
+
<Heading as="h1" size="4xl">
|
|
26
|
+
Main Article Title
|
|
27
|
+
</Heading>
|
|
28
|
+
|
|
29
|
+
<Heading as="h2" size="2xl">
|
|
30
|
+
Section One
|
|
31
|
+
</Heading>
|
|
32
|
+
<p>Content...</p>
|
|
33
|
+
|
|
34
|
+
<Heading as="h3" size="xl">
|
|
35
|
+
Subsection
|
|
36
|
+
</Heading>
|
|
37
|
+
<p>More content...</p>
|
|
38
|
+
|
|
39
|
+
<Heading as="h2" size="2xl">
|
|
40
|
+
Section Two
|
|
41
|
+
</Heading>
|
|
42
|
+
<p>Content...</p>
|
|
43
|
+
</article>
|
|
44
|
+
|
|
45
|
+
// ❌ Don't use Heading for emphasized text - Use Text
|
|
46
|
+
<Heading as="h3" size="md">
|
|
47
|
+
Just some bold text
|
|
48
|
+
</Heading>
|
|
49
|
+
|
|
50
|
+
// ✅ Better: Use Text with fontWeight for emphasis
|
|
51
|
+
<Text fontSize="md" fontWeight="bold">
|
|
52
|
+
Just some bold text
|
|
53
|
+
</Text>
|
|
54
|
+
|
|
55
|
+
// ❌ Don't skip heading levels (h1 → h3)
|
|
56
|
+
<Heading as="h1" size="3xl">Title</Heading>
|
|
57
|
+
<Heading as="h3" size="xl">Section</Heading> {/* Should be h2 */}
|
|
58
|
+
|
|
59
|
+
// ✅ Better: Use proper heading hierarchy
|
|
60
|
+
<Heading as="h1" size="3xl">Title</Heading>
|
|
61
|
+
<Heading as="h2" size="xl">Section</Heading>
|
|
62
|
+
|
|
63
|
+
// ❌ Don't use Heading for navigation - Use Text
|
|
64
|
+
<nav>
|
|
65
|
+
<Heading as="h3" size="sm">Menu</Heading>
|
|
66
|
+
<a href="/home">Home</a>
|
|
67
|
+
</nav>
|
|
68
|
+
|
|
69
|
+
// ✅ Better: Use Text for navigation labels
|
|
70
|
+
<nav aria-label="Main navigation">
|
|
71
|
+
<Text fontSize="sm" fontWeight="medium">Menu</Text>
|
|
72
|
+
<a href="/home">Home</a>
|
|
73
|
+
</nav>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Import
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { Heading } from '@discourser/design-system';
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Sizes
|
|
83
|
+
|
|
84
|
+
The Heading component supports 11 size variants, each corresponding to Material Design 3 text styles:
|
|
85
|
+
|
|
86
|
+
| Size | Material Design 3 Style | Font Size | Line Height | Font Weight | Usage |
|
|
87
|
+
| ----- | ----------------------- | --------- | ----------- | ----------- | -------------------------------------------------- |
|
|
88
|
+
| `xs` | labelLarge | 14px | 20px | 500 | Overlines, captions, small section labels |
|
|
89
|
+
| `sm` | titleSmall | 14px | 20px | 500 | Card titles, list headers, tertiary headings |
|
|
90
|
+
| `md` | titleMedium | 16px | 24px | 500 | Secondary headings, dialog titles, section headers |
|
|
91
|
+
| `lg` | titleLarge | 22px | 28px | 400 | Primary page headings, prominent section titles |
|
|
92
|
+
| `xl` | headlineSmall | 24px | 32px | 400 | Main page headings, article titles (default) |
|
|
93
|
+
| `2xl` | headlineMedium | 28px | 36px | 400 | Major section headings, featured content titles |
|
|
94
|
+
| `3xl` | headlineLarge | 32px | 40px | 400 | Page heroes, landing page headings |
|
|
95
|
+
| `4xl` | displaySmall | 36px | 44px | 400 | Large promotional headings, marketing content |
|
|
96
|
+
| `5xl` | displayMedium | 45px | 52px | 400 | Hero sections, major announcements |
|
|
97
|
+
| `6xl` | displayLarge | 57px | 64px | 400 | Landing page heroes, splash screens |
|
|
98
|
+
| `7xl` | displayLarge | 57px | 64px | 400 | Maximum emphasis (same as 6xl) |
|
|
99
|
+
|
|
100
|
+
### Visual Characteristics
|
|
101
|
+
|
|
102
|
+
- **Default Color**: Uses `fg.default` token for consistent foreground color
|
|
103
|
+
- **Semantic HTML**: Renders as `<h2>` by default, but can be overridden with `as` prop
|
|
104
|
+
- **Responsive**: Font sizes and line heights follow Material Design 3 type scale
|
|
105
|
+
|
|
106
|
+
## Props
|
|
107
|
+
|
|
108
|
+
| Prop | Type | Default | Description |
|
|
109
|
+
| ----------- | -------------------------------------------------------------------------------------------- | -------- | ------------------------------------------------------------- |
|
|
110
|
+
| `size` | `'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl' \| '2xl' \| '3xl' \| '4xl' \| '5xl' \| '6xl' \| '7xl'` | `'xl'` | Heading size using Material Design 3 text styles |
|
|
111
|
+
| `as` | `ElementType` | `'h2'` | HTML heading element (h1, h2, h3, h4, h5, h6, or any element) |
|
|
112
|
+
| `children` | `ReactNode` | Required | Heading text content |
|
|
113
|
+
| `className` | `string` | - | Additional CSS classes (use sparingly) |
|
|
114
|
+
|
|
115
|
+
**Note:** Heading extends all standard HTML element attributes for the specified element type.
|
|
116
|
+
|
|
117
|
+
## Examples
|
|
118
|
+
|
|
119
|
+
### Basic Usage
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
// Default heading (h2, xl size)
|
|
123
|
+
<Heading>Welcome to Our Platform</Heading>
|
|
124
|
+
|
|
125
|
+
// Different sizes
|
|
126
|
+
<Heading size="xs">Small Label</Heading>
|
|
127
|
+
<Heading size="sm">Card Title</Heading>
|
|
128
|
+
<Heading size="md">Section Header</Heading>
|
|
129
|
+
<Heading size="lg">Page Title</Heading>
|
|
130
|
+
<Heading size="xl">Main Heading</Heading>
|
|
131
|
+
<Heading size="2xl">Featured Title</Heading>
|
|
132
|
+
<Heading size="3xl">Hero Heading</Heading>
|
|
133
|
+
<Heading size="4xl">Large Display</Heading>
|
|
134
|
+
<Heading size="5xl">Promotional Banner</Heading>
|
|
135
|
+
<Heading size="6xl">Landing Hero</Heading>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Semantic HTML Elements
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
// Use appropriate heading levels for document structure
|
|
142
|
+
<Heading as="h1" size="3xl">Page Title</Heading>
|
|
143
|
+
<Heading as="h2" size="2xl">Major Section</Heading>
|
|
144
|
+
<Heading as="h3" size="xl">Subsection Title</Heading>
|
|
145
|
+
<Heading as="h4" size="lg">Content Block Header</Heading>
|
|
146
|
+
<Heading as="h5" size="md">Minor Section</Heading>
|
|
147
|
+
<Heading as="h6" size="sm">Smallest Heading</Heading>
|
|
148
|
+
|
|
149
|
+
// Use non-heading element when semantic heading isn't appropriate
|
|
150
|
+
<Heading as="div" size="lg">Stylistic Display Text</Heading>
|
|
151
|
+
<Heading as="span" size="md">Inline Heading</Heading>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Page Structure
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
// Article layout
|
|
158
|
+
<article>
|
|
159
|
+
<Heading as="h1" size="4xl">
|
|
160
|
+
The Future of Web Development
|
|
161
|
+
</Heading>
|
|
162
|
+
|
|
163
|
+
<Heading as="h2" size="2xl">
|
|
164
|
+
Introduction
|
|
165
|
+
</Heading>
|
|
166
|
+
<p>Article introduction...</p>
|
|
167
|
+
|
|
168
|
+
<Heading as="h2" size="2xl">
|
|
169
|
+
Main Concepts
|
|
170
|
+
</Heading>
|
|
171
|
+
|
|
172
|
+
<Heading as="h3" size="xl">
|
|
173
|
+
Core Principles
|
|
174
|
+
</Heading>
|
|
175
|
+
<p>Content about principles...</p>
|
|
176
|
+
|
|
177
|
+
<Heading as="h3" size="xl">
|
|
178
|
+
Best Practices
|
|
179
|
+
</Heading>
|
|
180
|
+
<p>Content about practices...</p>
|
|
181
|
+
</article>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Dashboard Layout
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
// Dashboard with sections
|
|
188
|
+
<div>
|
|
189
|
+
<Heading as="h1" size="3xl">Dashboard</Heading>
|
|
190
|
+
|
|
191
|
+
<section>
|
|
192
|
+
<Heading as="h2" size="xl">Recent Activity</Heading>
|
|
193
|
+
{/* Activity content */}
|
|
194
|
+
</section>
|
|
195
|
+
|
|
196
|
+
<section>
|
|
197
|
+
<Heading as="h2" size="xl">Analytics Overview</Heading>
|
|
198
|
+
{/* Analytics content */}
|
|
199
|
+
</section>
|
|
200
|
+
|
|
201
|
+
<section>
|
|
202
|
+
<Heading as="h2" size="xl">Team Members</Heading>
|
|
203
|
+
{/* Team members list */}
|
|
204
|
+
</section>
|
|
205
|
+
</div>
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Card Headers
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
// Card with heading
|
|
212
|
+
<Card>
|
|
213
|
+
<Heading as="h3" size="sm">Project Overview</Heading>
|
|
214
|
+
<p>Project details and information...</p>
|
|
215
|
+
</Card>
|
|
216
|
+
|
|
217
|
+
// Feature card
|
|
218
|
+
<Card>
|
|
219
|
+
<Heading as="h3" size="md">Advanced Analytics</Heading>
|
|
220
|
+
<p>Track and analyze your data with powerful tools.</p>
|
|
221
|
+
<Button>Learn More</Button>
|
|
222
|
+
</Card>
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Hero Sections
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
// Landing page hero
|
|
229
|
+
<section className={css({ textAlign: 'center', py: '20' })}>
|
|
230
|
+
<Heading as="h1" size="6xl">
|
|
231
|
+
Build Better Products Faster
|
|
232
|
+
</Heading>
|
|
233
|
+
<Heading as="h2" size="lg" className={css({ mt: '4', opacity: 0.8 })}>
|
|
234
|
+
The complete platform for modern teams
|
|
235
|
+
</Heading>
|
|
236
|
+
<Button size="lg" className={css({ mt: '8' })}>
|
|
237
|
+
Get Started
|
|
238
|
+
</Button>
|
|
239
|
+
</section>
|
|
240
|
+
|
|
241
|
+
// Marketing banner
|
|
242
|
+
<section className={css({ bg: 'primary', color: 'white', p: '16' })}>
|
|
243
|
+
<Heading as="h2" size="5xl">
|
|
244
|
+
Special Offer - 50% Off
|
|
245
|
+
</Heading>
|
|
246
|
+
<Heading as="h3" size="xl" className={css({ mt: '2' })}>
|
|
247
|
+
Limited time only
|
|
248
|
+
</Heading>
|
|
249
|
+
</section>
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Modal and Dialog Titles
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
// Dialog with heading
|
|
256
|
+
<Dialog>
|
|
257
|
+
<Dialog.Content>
|
|
258
|
+
<Heading as="h2" size="lg">
|
|
259
|
+
Confirm Action
|
|
260
|
+
</Heading>
|
|
261
|
+
<p>Are you sure you want to proceed with this action?</p>
|
|
262
|
+
<div className={css({ display: 'flex', gap: 'sm', justifyContent: 'flex-end' })}>
|
|
263
|
+
<Button variant="text">Cancel</Button>
|
|
264
|
+
<Button>Confirm</Button>
|
|
265
|
+
</div>
|
|
266
|
+
</Dialog.Content>
|
|
267
|
+
</Dialog>
|
|
268
|
+
|
|
269
|
+
// Modal with structured content
|
|
270
|
+
<Dialog>
|
|
271
|
+
<Dialog.Content>
|
|
272
|
+
<Heading as="h2" size="xl">
|
|
273
|
+
User Settings
|
|
274
|
+
</Heading>
|
|
275
|
+
|
|
276
|
+
<Heading as="h3" size="md" className={css({ mt: '6' })}>
|
|
277
|
+
Profile Information
|
|
278
|
+
</Heading>
|
|
279
|
+
{/* Profile fields */}
|
|
280
|
+
|
|
281
|
+
<Heading as="h3" size="md" className={css({ mt: '4' })}>
|
|
282
|
+
Privacy Settings
|
|
283
|
+
</Heading>
|
|
284
|
+
{/* Privacy fields */}
|
|
285
|
+
</Dialog.Content>
|
|
286
|
+
</Dialog>
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## Common Patterns
|
|
290
|
+
|
|
291
|
+
### Visual Hierarchy
|
|
292
|
+
|
|
293
|
+
```typescript
|
|
294
|
+
// Establish clear content hierarchy
|
|
295
|
+
<div>
|
|
296
|
+
<Heading as="h1" size="4xl">Main Topic</Heading>
|
|
297
|
+
<Heading as="h2" size="2xl" className={css({ mt: '8' })}>
|
|
298
|
+
Subtopic One
|
|
299
|
+
</Heading>
|
|
300
|
+
<Heading as="h3" size="xl" className={css({ mt: '6' })}>
|
|
301
|
+
Detail Section
|
|
302
|
+
</Heading>
|
|
303
|
+
<Heading as="h4" size="md" className={css({ mt: '4' })}>
|
|
304
|
+
Subsection
|
|
305
|
+
</Heading>
|
|
306
|
+
</div>
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Section with Description
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
// Heading with supporting text
|
|
313
|
+
<section>
|
|
314
|
+
<Heading as="h2" size="2xl">Features</Heading>
|
|
315
|
+
<p className={css({ fontSize: 'lg', opacity: 0.8, mt: '2' })}>
|
|
316
|
+
Discover what makes our platform unique
|
|
317
|
+
</p>
|
|
318
|
+
{/* Feature content */}
|
|
319
|
+
</section>
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Grid Layout Headers
|
|
323
|
+
|
|
324
|
+
```typescript
|
|
325
|
+
// Headers for grid sections
|
|
326
|
+
<div className={css({ display: 'grid', gridTemplateColumns: '3', gap: '6' })}>
|
|
327
|
+
<div>
|
|
328
|
+
<Heading as="h3" size="md">Performance</Heading>
|
|
329
|
+
<p>Lightning-fast load times</p>
|
|
330
|
+
</div>
|
|
331
|
+
<div>
|
|
332
|
+
<Heading as="h3" size="md">Security</Heading>
|
|
333
|
+
<p>Enterprise-grade protection</p>
|
|
334
|
+
</div>
|
|
335
|
+
<div>
|
|
336
|
+
<Heading as="h3" size="md">Scalability</Heading>
|
|
337
|
+
<p>Grows with your needs</p>
|
|
338
|
+
</div>
|
|
339
|
+
</div>
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### List Headers
|
|
343
|
+
|
|
344
|
+
```typescript
|
|
345
|
+
// Heading for list sections
|
|
346
|
+
<div>
|
|
347
|
+
<Heading as="h3" size="lg">Team Members</Heading>
|
|
348
|
+
<ul className={css({ mt: '4' })}>
|
|
349
|
+
{members.map(member => (
|
|
350
|
+
<li key={member.id}>
|
|
351
|
+
<Heading as="h4" size="sm">{member.name}</Heading>
|
|
352
|
+
<p>{member.role}</p>
|
|
353
|
+
</li>
|
|
354
|
+
))}
|
|
355
|
+
</ul>
|
|
356
|
+
</div>
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
## DO NOT
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
// ❌ Don't skip heading levels (affects screen readers)
|
|
363
|
+
<Heading as="h1" size="3xl">Main Title</Heading>
|
|
364
|
+
<Heading as="h4" size="md">Subsection</Heading> // Should be h2, not h4
|
|
365
|
+
|
|
366
|
+
// ❌ Don't use multiple h1 elements on a page
|
|
367
|
+
<Heading as="h1" size="3xl">First Title</Heading>
|
|
368
|
+
<Heading as="h1" size="2xl">Second Title</Heading> // Should be h2
|
|
369
|
+
|
|
370
|
+
// ❌ Don't use headings for styling text (use Text component instead)
|
|
371
|
+
<Heading as="h2" size="sm">Just some bold text</Heading> // Use <Text> instead
|
|
372
|
+
|
|
373
|
+
// ❌ Don't mismatch size and semantic level
|
|
374
|
+
<Heading as="h1" size="xs">Main Page Title</Heading> // h1 should be visually prominent
|
|
375
|
+
|
|
376
|
+
// ❌ Don't use headings inside paragraphs
|
|
377
|
+
<p>
|
|
378
|
+
<Heading as="h3" size="md">Title</Heading> // Invalid HTML
|
|
379
|
+
Some content here
|
|
380
|
+
</p>
|
|
381
|
+
|
|
382
|
+
// ❌ Don't use empty headings
|
|
383
|
+
<Heading as="h2" size="xl"></Heading> // No accessible name
|
|
384
|
+
|
|
385
|
+
// ✅ Use proper heading hierarchy
|
|
386
|
+
<Heading as="h1" size="3xl">Main Title</Heading>
|
|
387
|
+
<Heading as="h2" size="2xl">Section</Heading>
|
|
388
|
+
<Heading as="h3" size="xl">Subsection</Heading>
|
|
389
|
+
|
|
390
|
+
// ✅ Single h1 per page
|
|
391
|
+
<Heading as="h1" size="4xl">Page Title</Heading>
|
|
392
|
+
<Heading as="h2" size="2xl">Section One</Heading>
|
|
393
|
+
<Heading as="h2" size="2xl">Section Two</Heading>
|
|
394
|
+
|
|
395
|
+
// ✅ Match visual size to importance
|
|
396
|
+
<Heading as="h1" size="4xl">Most Important</Heading>
|
|
397
|
+
<Heading as="h2" size="2xl">Secondary</Heading>
|
|
398
|
+
<Heading as="h3" size="xl">Tertiary</Heading>
|
|
399
|
+
|
|
400
|
+
// ✅ Use Text component for non-heading bold text
|
|
401
|
+
<Text fontSize="lg" fontWeight="bold">Emphasized text</Text>
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
## Accessibility
|
|
405
|
+
|
|
406
|
+
The Heading component follows WCAG 2.1 Level AA standards:
|
|
407
|
+
|
|
408
|
+
- **Semantic HTML**: Uses proper heading elements (h1-h6) for document structure
|
|
409
|
+
- **Heading Hierarchy**: Screen readers rely on heading levels for navigation
|
|
410
|
+
- **Color Contrast**: Default color meets 4.5:1 contrast ratio requirement
|
|
411
|
+
- **Keyboard Navigation**: Heading landmarks allow users to jump between sections
|
|
412
|
+
- **Screen Readers**: Announce heading level and content
|
|
413
|
+
|
|
414
|
+
### Accessibility Best Practices
|
|
415
|
+
|
|
416
|
+
```typescript
|
|
417
|
+
// ✅ Maintain logical heading order
|
|
418
|
+
<Heading as="h1" size="3xl">Page Title</Heading>
|
|
419
|
+
<Heading as="h2" size="2xl">Main Section</Heading>
|
|
420
|
+
<Heading as="h3" size="xl">Subsection</Heading>
|
|
421
|
+
<Heading as="h3" size="xl">Another Subsection</Heading>
|
|
422
|
+
<Heading as="h2" size="2xl">Next Main Section</Heading>
|
|
423
|
+
|
|
424
|
+
// ✅ Only one h1 per page
|
|
425
|
+
<Heading as="h1" size="4xl">Dashboard Overview</Heading>
|
|
426
|
+
|
|
427
|
+
// ✅ Don't skip levels (h1 → h3 without h2)
|
|
428
|
+
<Heading as="h1" size="3xl">Title</Heading>
|
|
429
|
+
<Heading as="h2" size="xl">Section</Heading> // Not h3
|
|
430
|
+
|
|
431
|
+
// ✅ Use descriptive heading text
|
|
432
|
+
<Heading as="h2" size="xl">Shipping Information</Heading> // Clear and descriptive
|
|
433
|
+
|
|
434
|
+
// ✅ Separate visual size from semantic level
|
|
435
|
+
<Heading as="h1" size="6xl">Hero Title</Heading>
|
|
436
|
+
<Heading as="h2" size="sm">Card Subtitle</Heading> // Small visually, but correct level
|
|
437
|
+
|
|
438
|
+
// ✅ Provide meaningful content
|
|
439
|
+
<Heading as="h2" size="lg">
|
|
440
|
+
{userName}'s Profile
|
|
441
|
+
</Heading>
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
### Screen Reader Considerations
|
|
445
|
+
|
|
446
|
+
```typescript
|
|
447
|
+
// Screen readers announce: "Heading level 1, Dashboard"
|
|
448
|
+
<Heading as="h1" size="3xl">Dashboard</Heading>
|
|
449
|
+
|
|
450
|
+
// Screen readers can list all headings to navigate
|
|
451
|
+
<Heading as="h1" size="4xl">Product Overview</Heading>
|
|
452
|
+
<Heading as="h2" size="2xl">Features</Heading>
|
|
453
|
+
<Heading as="h2" size="2xl">Pricing</Heading>
|
|
454
|
+
<Heading as="h2" size="2xl">FAQ</Heading>
|
|
455
|
+
|
|
456
|
+
// Users can jump to specific sections using heading navigation
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
## Size Selection Guide
|
|
460
|
+
|
|
461
|
+
| Context | Recommended Size | Semantic Level | Reasoning |
|
|
462
|
+
| ------------- | ---------------- | -------------------- | ----------------------------------------------- |
|
|
463
|
+
| Page title | `4xl` - `6xl` | `h1` | Maximum visual prominence for main page heading |
|
|
464
|
+
| Hero section | `5xl` - `6xl` | `h1` | Large display for landing pages |
|
|
465
|
+
| Main sections | `2xl` - `3xl` | `h2` | Clear hierarchy, major content divisions |
|
|
466
|
+
| Subsections | `xl` - `2xl` | `h3` | Secondary content organization |
|
|
467
|
+
| Card titles | `sm` - `md` | `h3` or `h4` | Compact, readable headers |
|
|
468
|
+
| List headers | `md` - `lg` | `h3` or `h4` | Clear labeling without overwhelming |
|
|
469
|
+
| Dialog titles | `lg` - `xl` | `h2` | Prominent but not overpowering |
|
|
470
|
+
| Small labels | `xs` - `sm` | `h4` - `h6` or `div` | Minimal hierarchy markers |
|
|
471
|
+
|
|
472
|
+
## Responsive Typography
|
|
473
|
+
|
|
474
|
+
```typescript
|
|
475
|
+
// Responsive heading sizes using Panda CSS
|
|
476
|
+
<Heading
|
|
477
|
+
as="h1"
|
|
478
|
+
size={{ base: '3xl', md: '5xl', lg: '6xl' }}
|
|
479
|
+
>
|
|
480
|
+
Responsive Hero Title
|
|
481
|
+
</Heading>
|
|
482
|
+
|
|
483
|
+
// Scale down on mobile
|
|
484
|
+
<Heading
|
|
485
|
+
as="h1"
|
|
486
|
+
className={css({
|
|
487
|
+
fontSize: { base: '3xl', md: '4xl' },
|
|
488
|
+
lineHeight: { base: 'tight', md: 'normal' }
|
|
489
|
+
})}
|
|
490
|
+
>
|
|
491
|
+
Mobile-Optimized Title
|
|
492
|
+
</Heading>
|
|
493
|
+
|
|
494
|
+
// Adjust spacing between headings responsively
|
|
495
|
+
<div>
|
|
496
|
+
<Heading as="h2" size="2xl">Section Title</Heading>
|
|
497
|
+
<Heading
|
|
498
|
+
as="h3"
|
|
499
|
+
size="xl"
|
|
500
|
+
className={css({ mt: { base: '4', md: '6' } })}
|
|
501
|
+
>
|
|
502
|
+
Subsection
|
|
503
|
+
</Heading>
|
|
504
|
+
</div>
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
## Testing
|
|
508
|
+
|
|
509
|
+
When testing Heading components:
|
|
510
|
+
|
|
511
|
+
```typescript
|
|
512
|
+
import { render, screen } from '@testing-library/react';
|
|
513
|
+
|
|
514
|
+
test('renders heading with correct text', () => {
|
|
515
|
+
render(<Heading as="h1" size="3xl">Test Heading</Heading>);
|
|
516
|
+
|
|
517
|
+
const heading = screen.getByRole('heading', {
|
|
518
|
+
name: 'Test Heading',
|
|
519
|
+
level: 1
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
expect(heading).toBeInTheDocument();
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
test('renders with specified element type', () => {
|
|
526
|
+
const { container } = render(
|
|
527
|
+
<Heading as="h3" size="lg">Section Title</Heading>
|
|
528
|
+
);
|
|
529
|
+
|
|
530
|
+
const heading = container.querySelector('h3');
|
|
531
|
+
expect(heading).toBeInTheDocument();
|
|
532
|
+
expect(heading).toHaveTextContent('Section Title');
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
test('applies correct size variant', () => {
|
|
536
|
+
render(<Heading size="2xl">Large Heading</Heading>);
|
|
537
|
+
|
|
538
|
+
const heading = screen.getByRole('heading', { name: 'Large Heading' });
|
|
539
|
+
expect(heading).toHaveClass('heading');
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
test('maintains heading hierarchy', () => {
|
|
543
|
+
render(
|
|
544
|
+
<div>
|
|
545
|
+
<Heading as="h1" size="4xl">Main Title</Heading>
|
|
546
|
+
<Heading as="h2" size="2xl">Section</Heading>
|
|
547
|
+
<Heading as="h3" size="xl">Subsection</Heading>
|
|
548
|
+
</div>
|
|
549
|
+
);
|
|
550
|
+
|
|
551
|
+
const h1 = screen.getByRole('heading', { level: 1 });
|
|
552
|
+
const h2 = screen.getByRole('heading', { level: 2 });
|
|
553
|
+
const h3 = screen.getByRole('heading', { level: 3 });
|
|
554
|
+
|
|
555
|
+
expect(h1).toHaveTextContent('Main Title');
|
|
556
|
+
expect(h2).toHaveTextContent('Section');
|
|
557
|
+
expect(h3).toHaveTextContent('Subsection');
|
|
558
|
+
});
|
|
559
|
+
|
|
560
|
+
test('accepts custom className', () => {
|
|
561
|
+
const { container } = render(
|
|
562
|
+
<Heading className="custom-class">Custom Heading</Heading>
|
|
563
|
+
);
|
|
564
|
+
|
|
565
|
+
const heading = container.firstChild;
|
|
566
|
+
expect(heading).toHaveClass('custom-class');
|
|
567
|
+
});
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
## Related Components
|
|
571
|
+
|
|
572
|
+
- **Text**: For body text and non-heading typography
|
|
573
|
+
- **Badge**: For labels and small status indicators
|
|
574
|
+
- **Button**: Often paired with headings in hero sections
|
|
575
|
+
- **Card**: Headings commonly used as card titles
|
|
576
|
+
- **Dialog**: Headings used for dialog titles
|