@discourser/design-system 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/guidelines/Guidelines.md +88 -0
- package/guidelines/components/button.md +314 -0
- package/guidelines/components/card.md +353 -0
- package/guidelines/components/dialog.md +465 -0
- package/guidelines/components/icon-button.md +417 -0
- package/guidelines/components/input.md +499 -0
- package/guidelines/components/switch.md +457 -0
- package/guidelines/design-tokens/colors.md +187 -0
- package/guidelines/design-tokens/elevation.md +274 -0
- package/guidelines/design-tokens/spacing.md +289 -0
- package/guidelines/design-tokens/typography.md +226 -0
- package/guidelines/overview-components.md +156 -0
- package/package.json +3 -2
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# Typography Tokens
|
|
2
|
+
|
|
3
|
+
The design system uses Material Design 3 typography scale with semantic naming.
|
|
4
|
+
|
|
5
|
+
## Font Families
|
|
6
|
+
|
|
7
|
+
| Token | Font | Usage |
|
|
8
|
+
|-------|------|-------|
|
|
9
|
+
| `display` | "Fraunces", Georgia, serif | Display text, headings, editorial content |
|
|
10
|
+
| `body` | "Poppins", -apple-system, BlinkMacSystemFont, sans-serif | Body text, UI elements, most content |
|
|
11
|
+
| `mono` | "JetBrains Mono", "Fira Code", Consolas, monospace | Code snippets, technical text |
|
|
12
|
+
|
|
13
|
+
## Type Scale
|
|
14
|
+
|
|
15
|
+
Material Design 3 provides a comprehensive type scale with specific roles. Always use `textStyle` tokens instead of manual font sizing.
|
|
16
|
+
|
|
17
|
+
### Display (Hero Sections, Large Marketing Text)
|
|
18
|
+
|
|
19
|
+
Use for hero sections, large marketing content, or prominent display text.
|
|
20
|
+
|
|
21
|
+
| Token | Size | Line Height | Weight | Letter Spacing | Font Family |
|
|
22
|
+
|-------|------|-------------|--------|----------------|-------------|
|
|
23
|
+
| `displayLarge` | 57px | 64px | 400 | -0.25px | display |
|
|
24
|
+
| `displayMedium` | 45px | 52px | 400 | 0px | display |
|
|
25
|
+
| `displaySmall` | 36px | 44px | 400 | 0px | display |
|
|
26
|
+
|
|
27
|
+
**Use cases**: Landing page heroes, large feature announcements, major section breaks
|
|
28
|
+
|
|
29
|
+
### Headline (Page and Section Headers)
|
|
30
|
+
|
|
31
|
+
Use for page titles and major section headings.
|
|
32
|
+
|
|
33
|
+
| Token | Size | Line Height | Weight | Letter Spacing | Font Family |
|
|
34
|
+
|-------|------|-------------|--------|----------------|-------------|
|
|
35
|
+
| `headlineLarge` | 32px | 40px | 400 | 0px | display |
|
|
36
|
+
| `headlineMedium` | 28px | 36px | 400 | 0px | display |
|
|
37
|
+
| `headlineSmall` | 24px | 32px | 400 | 0px | display |
|
|
38
|
+
|
|
39
|
+
**Use cases**: Page titles (h1), section headings (h2), major card headers
|
|
40
|
+
|
|
41
|
+
### Title (Card Titles, Dialog Headers, List Items)
|
|
42
|
+
|
|
43
|
+
Use for card titles, dialog headers, and prominent list items.
|
|
44
|
+
|
|
45
|
+
| Token | Size | Line Height | Weight | Letter Spacing | Font Family |
|
|
46
|
+
|-------|------|-------------|--------|----------------|-------------|
|
|
47
|
+
| `titleLarge` | 22px | 28px | 500 | 0px | body |
|
|
48
|
+
| `titleMedium` | 16px | 24px | 500 | 0.15px | body |
|
|
49
|
+
| `titleSmall` | 14px | 20px | 500 | 0.1px | body |
|
|
50
|
+
|
|
51
|
+
**Use cases**: Dialog titles, card headers, list item titles, h3-h4 equivalents
|
|
52
|
+
|
|
53
|
+
### Body (Content Text)
|
|
54
|
+
|
|
55
|
+
Use for main content, paragraphs, and body copy.
|
|
56
|
+
|
|
57
|
+
| Token | Size | Line Height | Weight | Letter Spacing | Font Family |
|
|
58
|
+
|-------|------|-------------|--------|----------------|-------------|
|
|
59
|
+
| `bodyLarge` | 16px | 24px | 400 | 0.5px | body |
|
|
60
|
+
| `bodyMedium` | 14px | 20px | 400 | 0.25px | body |
|
|
61
|
+
| `bodySmall` | 12px | 16px | 400 | 0.4px | body |
|
|
62
|
+
|
|
63
|
+
**Use cases**:
|
|
64
|
+
- `bodyLarge`: Primary paragraphs, important content
|
|
65
|
+
- `bodyMedium`: Default body text (most common)
|
|
66
|
+
- `bodySmall`: Secondary text, captions, hints
|
|
67
|
+
|
|
68
|
+
### Label (Buttons, Form Labels, UI Elements)
|
|
69
|
+
|
|
70
|
+
Use for buttons, form labels, chips, and other UI elements.
|
|
71
|
+
|
|
72
|
+
| Token | Size | Line Height | Weight | Letter Spacing | Font Family |
|
|
73
|
+
|-------|------|-------------|--------|----------------|-------------|
|
|
74
|
+
| `labelLarge` | 14px | 20px | 500 | 0.1px | body |
|
|
75
|
+
| `labelMedium` | 12px | 16px | 500 | 0.5px | body |
|
|
76
|
+
| `labelSmall` | 11px | 16px | 500 | 0.5px | body |
|
|
77
|
+
|
|
78
|
+
**Use cases**:
|
|
79
|
+
- `labelLarge`: Button text, tab labels
|
|
80
|
+
- `labelMedium`: Form field labels, input labels
|
|
81
|
+
- `labelSmall`: Small badges, overline text, timestamps
|
|
82
|
+
|
|
83
|
+
## Usage in Code
|
|
84
|
+
|
|
85
|
+
### Using Text Styles
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
import { css } from '@discourser/design-system/styled-system/css';
|
|
89
|
+
|
|
90
|
+
// ✅ Correct - Use textStyle tokens
|
|
91
|
+
const heading = css({ textStyle: 'headlineMedium' });
|
|
92
|
+
const body = css({ textStyle: 'bodyMedium' });
|
|
93
|
+
const label = css({ textStyle: 'labelLarge' });
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Common Patterns
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
// Page title
|
|
100
|
+
<h1 className={css({ textStyle: 'headlineLarge' })}>
|
|
101
|
+
Welcome to Our App
|
|
102
|
+
</h1>
|
|
103
|
+
|
|
104
|
+
// Section heading
|
|
105
|
+
<h2 className={css({ textStyle: 'headlineMedium' })}>
|
|
106
|
+
Features
|
|
107
|
+
</h2>
|
|
108
|
+
|
|
109
|
+
// Card title
|
|
110
|
+
<h3 className={css({ textStyle: 'titleLarge' })}>
|
|
111
|
+
Card Title
|
|
112
|
+
</h3>
|
|
113
|
+
|
|
114
|
+
// Body text
|
|
115
|
+
<p className={css({ textStyle: 'bodyMedium' })}>
|
|
116
|
+
This is the main content text that users will read.
|
|
117
|
+
</p>
|
|
118
|
+
|
|
119
|
+
// Secondary text
|
|
120
|
+
<span className={css({ textStyle: 'bodySmall', color: 'onSurfaceVariant' })}>
|
|
121
|
+
Updated 2 hours ago
|
|
122
|
+
</span>
|
|
123
|
+
|
|
124
|
+
// Form label
|
|
125
|
+
<label className={css({ textStyle: 'labelMedium' })}>
|
|
126
|
+
Email Address
|
|
127
|
+
</label>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Combining with Color Tokens
|
|
131
|
+
|
|
132
|
+
Always combine typography with semantic color tokens:
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
// Primary heading
|
|
136
|
+
const heading = css({
|
|
137
|
+
textStyle: 'headlineLarge',
|
|
138
|
+
color: 'onSurface'
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// Secondary text
|
|
142
|
+
const secondary = css({
|
|
143
|
+
textStyle: 'bodySmall',
|
|
144
|
+
color: 'onSurfaceVariant'
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// Error message
|
|
148
|
+
const errorText = css({
|
|
149
|
+
textStyle: 'bodySmall',
|
|
150
|
+
color: 'error'
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// Button text (components handle this automatically)
|
|
154
|
+
const buttonText = css({
|
|
155
|
+
textStyle: 'labelLarge',
|
|
156
|
+
color: 'onPrimary'
|
|
157
|
+
});
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## What NOT to Do
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
// ❌ NEVER use manual font sizes
|
|
164
|
+
const wrong = css({ fontSize: '16px', lineHeight: '24px' });
|
|
165
|
+
|
|
166
|
+
// ❌ NEVER hardcode font families
|
|
167
|
+
const wrong = css({ fontFamily: 'Arial, sans-serif' });
|
|
168
|
+
|
|
169
|
+
// ❌ NEVER use arbitrary font weights outside the scale
|
|
170
|
+
const wrong = css({ fontWeight: 600 });
|
|
171
|
+
|
|
172
|
+
// ✅ ALWAYS use textStyle tokens
|
|
173
|
+
const correct = css({ textStyle: 'bodyMedium' });
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Semantic HTML Mapping
|
|
177
|
+
|
|
178
|
+
Recommended mapping of textStyle tokens to HTML semantic elements:
|
|
179
|
+
|
|
180
|
+
| HTML Element | Recommended textStyle | Alternative |
|
|
181
|
+
|--------------|----------------------|-------------|
|
|
182
|
+
| `<h1>` | `headlineLarge` or `displaySmall` | `headlineMedium` |
|
|
183
|
+
| `<h2>` | `headlineMedium` | `headlineSmall` |
|
|
184
|
+
| `<h3>` | `headlineSmall` or `titleLarge` | `titleMedium` |
|
|
185
|
+
| `<h4>` | `titleLarge` | `titleMedium` |
|
|
186
|
+
| `<h5>` | `titleMedium` | `titleSmall` |
|
|
187
|
+
| `<h6>` | `titleSmall` | `labelLarge` |
|
|
188
|
+
| `<p>` | `bodyMedium` | `bodyLarge` or `bodySmall` |
|
|
189
|
+
| `<button>` | `labelLarge` | (handled by Button component) |
|
|
190
|
+
| `<label>` | `labelMedium` | (handled by Input component) |
|
|
191
|
+
| `<caption>` | `bodySmall` | `labelSmall` |
|
|
192
|
+
|
|
193
|
+
## Responsive Typography
|
|
194
|
+
|
|
195
|
+
The type scale is fixed and does not change at different breakpoints. However, you can choose different scales for different screen sizes:
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
// Mobile: Use smaller scales
|
|
199
|
+
<h1 className={css({ textStyle: 'headlineMedium' })}>Title</h1>
|
|
200
|
+
|
|
201
|
+
// Desktop: Use larger scales
|
|
202
|
+
<h1 className={css({
|
|
203
|
+
textStyle: { base: 'headlineMedium', lg: 'headlineLarge' }
|
|
204
|
+
})}>Title</h1>
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Accessibility
|
|
208
|
+
|
|
209
|
+
- All type scales meet WCAG 2.1 readability guidelines
|
|
210
|
+
- Line heights provide adequate spacing for readability
|
|
211
|
+
- Letter spacing improves legibility at different sizes
|
|
212
|
+
- Font weights ensure sufficient contrast and hierarchy
|
|
213
|
+
|
|
214
|
+
**Important**: Never reduce line-height below the specified values in the scale, as this can harm readability and accessibility.
|
|
215
|
+
|
|
216
|
+
## Font Loading
|
|
217
|
+
|
|
218
|
+
The design system expects these fonts to be loaded in your application:
|
|
219
|
+
|
|
220
|
+
```html
|
|
221
|
+
<!-- In your HTML head or CSS -->
|
|
222
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
223
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
224
|
+
<link href="https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,300;0,9..144,400;0,9..144,500;0,9..144,600;0,9..144,700;1,9..144,300;1,9..144,400;1,9..144,500;1,9..144,600;1,9..144,700&family=Poppins:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
|
225
|
+
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono&display=swap" rel="stylesheet">
|
|
226
|
+
```
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# Components Overview
|
|
2
|
+
|
|
3
|
+
Always prefer components from `@discourser/design-system` if available. Do not use native HTML elements when a design system component exists.
|
|
4
|
+
|
|
5
|
+
## Available Components
|
|
6
|
+
|
|
7
|
+
| Component | Purpose | Guidelines |
|
|
8
|
+
|-----------|---------|------------|
|
|
9
|
+
| Button | Primary interactive element for actions | [button.md](components/button.md) |
|
|
10
|
+
| Card | Container for related content with elevation | [card.md](components/card.md) |
|
|
11
|
+
| IconButton | Icon-only interactive element | [icon-button.md](components/icon-button.md) |
|
|
12
|
+
| Input | Text input with label and validation states | [input.md](components/input.md) |
|
|
13
|
+
| Dialog | Modal overlay for focused tasks or confirmations | [dialog.md](components/dialog.md) |
|
|
14
|
+
| Switch | Toggle control for binary on/off states | [switch.md](components/switch.md) |
|
|
15
|
+
|
|
16
|
+
## Common Props
|
|
17
|
+
|
|
18
|
+
Most components accept these standard props:
|
|
19
|
+
|
|
20
|
+
- `variant` - Visual style variant (e.g., filled, outlined, text)
|
|
21
|
+
- `size` - Size variant (sm, md, lg)
|
|
22
|
+
- `disabled` - Disable interaction
|
|
23
|
+
- `className` - Additional CSS classes (use sparingly)
|
|
24
|
+
- `ref` - React ref for DOM access (all components use forwardRef)
|
|
25
|
+
|
|
26
|
+
## Styling Guidelines
|
|
27
|
+
|
|
28
|
+
### ✅ DO:
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
// Use design system components with variants
|
|
32
|
+
<Button variant="filled" size="md">Submit</Button>
|
|
33
|
+
<Card variant="elevated">Content</Card>
|
|
34
|
+
<Input variant="outlined" label="Email" />
|
|
35
|
+
|
|
36
|
+
// Use semantic color tokens when custom styling is needed
|
|
37
|
+
import { css } from '@discourser/design-system/styled-system/css';
|
|
38
|
+
const customStyle = css({ bg: 'primary', color: 'onPrimary' });
|
|
39
|
+
|
|
40
|
+
// Compose multiple components together
|
|
41
|
+
<Card variant="elevated">
|
|
42
|
+
<Input label="Username" />
|
|
43
|
+
<Button variant="filled">Submit</Button>
|
|
44
|
+
</Card>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### ❌ DO NOT:
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
// Don't use raw HTML when components exist
|
|
51
|
+
<button className="...">Submit</button> // Use <Button> instead
|
|
52
|
+
<input type="text" /> // Use <Input> instead
|
|
53
|
+
<div className="card">...</div> // Use <Card> instead
|
|
54
|
+
|
|
55
|
+
// Don't override styles with inline styles
|
|
56
|
+
<Button style={{ backgroundColor: 'blue' }}>Submit</Button>
|
|
57
|
+
|
|
58
|
+
// Don't use raw color values
|
|
59
|
+
<div style={{ backgroundColor: '#4C662B' }}>...</div>
|
|
60
|
+
const style = css({ bg: '#4C662B' }); // Use semantic tokens instead
|
|
61
|
+
|
|
62
|
+
// Don't skip required props like labels
|
|
63
|
+
<Input placeholder="Email" /> // Missing label (accessibility issue)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Component Categories
|
|
67
|
+
|
|
68
|
+
### Interactive Elements
|
|
69
|
+
- **Button** - For user actions (submit, cancel, etc.)
|
|
70
|
+
- **IconButton** - For icon-only actions (close, menu, etc.)
|
|
71
|
+
- **Switch** - For toggle states (enable/disable features)
|
|
72
|
+
|
|
73
|
+
### Input Elements
|
|
74
|
+
- **Input** - For text input fields with built-in label and validation
|
|
75
|
+
|
|
76
|
+
### Layout Elements
|
|
77
|
+
- **Card** - For grouping related content with visual hierarchy
|
|
78
|
+
|
|
79
|
+
### Overlay Elements
|
|
80
|
+
- **Dialog** - For modal dialogs and confirmations
|
|
81
|
+
|
|
82
|
+
## Controlled vs Uncontrolled
|
|
83
|
+
|
|
84
|
+
### Controlled Components
|
|
85
|
+
Component receives `value` and `onChange` props from parent:
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
const [email, setEmail] = useState('');
|
|
89
|
+
<Input
|
|
90
|
+
label="Email"
|
|
91
|
+
value={email}
|
|
92
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
93
|
+
/>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Uncontrolled Components
|
|
97
|
+
Component manages own state, use `defaultValue`:
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
<Input label="Email" defaultValue="user@example.com" />
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Recommendation**: Prefer controlled components for form inputs to maintain single source of truth.
|
|
104
|
+
|
|
105
|
+
## Accessibility
|
|
106
|
+
|
|
107
|
+
All components follow WCAG 2.1 Level AA standards:
|
|
108
|
+
|
|
109
|
+
- Keyboard navigation is built-in
|
|
110
|
+
- Focus management is automatic
|
|
111
|
+
- ARIA attributes are applied correctly
|
|
112
|
+
- Color contrast meets accessibility requirements
|
|
113
|
+
- Screen reader support is included
|
|
114
|
+
|
|
115
|
+
**Important**: Always provide labels for form inputs:
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
// ✅ Correct
|
|
119
|
+
<Input label="Email" />
|
|
120
|
+
|
|
121
|
+
// ❌ Wrong - Missing label
|
|
122
|
+
<Input placeholder="Enter email" />
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Responsive Design
|
|
126
|
+
|
|
127
|
+
Components are designed to work on all screen sizes. Use the `size` prop to control component sizing:
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
// Mobile-friendly larger touch targets
|
|
131
|
+
<Button size="lg">Submit</Button>
|
|
132
|
+
|
|
133
|
+
// Desktop compact layouts
|
|
134
|
+
<Button size="sm">Save</Button>
|
|
135
|
+
|
|
136
|
+
// Default for most use cases
|
|
137
|
+
<Button size="md">Submit</Button>
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Theme Integration
|
|
141
|
+
|
|
142
|
+
All components automatically respond to theme changes via `data-theme` attribute:
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
// Light theme
|
|
146
|
+
<html data-theme="light">
|
|
147
|
+
<Button variant="filled">Submit</Button> // Uses light theme colors
|
|
148
|
+
</html>
|
|
149
|
+
|
|
150
|
+
// Dark theme
|
|
151
|
+
<html data-theme="dark">
|
|
152
|
+
<Button variant="filled">Submit</Button> // Uses dark theme colors
|
|
153
|
+
</html>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
No additional code is needed for theme support - it works automatically.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@discourser/design-system",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Aesthetic-agnostic design system with Panda CSS and Ark UI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -48,7 +48,8 @@
|
|
|
48
48
|
},
|
|
49
49
|
"files": [
|
|
50
50
|
"dist",
|
|
51
|
-
"styled-system"
|
|
51
|
+
"styled-system",
|
|
52
|
+
"guidelines"
|
|
52
53
|
],
|
|
53
54
|
"scripts": {
|
|
54
55
|
"dev": "pnpm docs:generate && storybook dev -p 6006",
|