@maxsteinwender/sort-ui 1.0.6 → 1.0.8
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 +294 -0
- package/guidelines/components.md +406 -0
- package/guidelines/icon-discovery.md +247 -0
- package/guidelines/setup.md +343 -0
- package/guidelines/styles.md +356 -0
- package/guidelines/tokens.md +354 -0
- package/package.json +11 -3
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
# Style System Guidelines
|
|
2
|
+
|
|
3
|
+
Spacing, layout, responsive patterns, and CSS methodology for SortUI.
|
|
4
|
+
|
|
5
|
+
## CSS Methodology
|
|
6
|
+
|
|
7
|
+
SortUI uses **Tailwind CSS v3** (`^3.4.1`). It is **NOT** Tailwind v4. The design system provides:
|
|
8
|
+
|
|
9
|
+
1. **Design tokens** (CSS custom properties)
|
|
10
|
+
2. **Tailwind v3 preset** (extends Tailwind with SUI tokens)
|
|
11
|
+
3. **Component classes** (component-specific styles)
|
|
12
|
+
|
|
13
|
+
**Never emit Tailwind v4 syntax** (`@theme` directive, v4-only APIs). Always author styles for Tailwind v3.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Spacing Scale (WITH `sui-` prefix)
|
|
18
|
+
|
|
19
|
+
SortUI uses a numeric spacing scale based on pixels. Use with `gap-`, `p-`, `m-`, `space-x-`, `space-y-`, etc.
|
|
20
|
+
|
|
21
|
+
| Class | Size | Common Usage |
|
|
22
|
+
|-------|------|--------------|
|
|
23
|
+
| `gap-sui-none` | 0px | No spacing |
|
|
24
|
+
| `gap-sui-1` | 1px | Hairline |
|
|
25
|
+
| `gap-sui-2` | 2px | Minimal |
|
|
26
|
+
| `gap-sui-4` | 4px | Extra small |
|
|
27
|
+
| `gap-sui-6` | 6px | Small− |
|
|
28
|
+
| `gap-sui-8` | 8px | Small |
|
|
29
|
+
| `gap-sui-12` | 12px | Medium small |
|
|
30
|
+
| `gap-sui-16` | 16px | Medium — form field gap |
|
|
31
|
+
| `gap-sui-20` | 20px | Medium+ |
|
|
32
|
+
| `gap-sui-24` | 24px | Large — card padding |
|
|
33
|
+
| `gap-sui-32` | 32px | Section gap |
|
|
34
|
+
| `gap-sui-40` | 40px | XXL |
|
|
35
|
+
| `gap-sui-48` | 48px | XXXL |
|
|
36
|
+
| `gap-sui-64` | 64px | Large sections |
|
|
37
|
+
| `gap-sui-80` | 80px | Hero |
|
|
38
|
+
| `gap-sui-96` – `gap-sui-384` | 96–384px | Page sections, hero spacing |
|
|
39
|
+
|
|
40
|
+
**Usage:**
|
|
41
|
+
```tsx
|
|
42
|
+
<div className="p-sui-24" /> {/* padding: 24px */}
|
|
43
|
+
<div className="m-sui-16" /> {/* margin: 16px */}
|
|
44
|
+
<div className="gap-sui-12" /> {/* gap: 12px */}
|
|
45
|
+
<div className="space-x-sui-8" /> {/* horizontal spacing */}
|
|
46
|
+
<div className="space-y-sui-16" /> {/* vertical spacing */}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Common Spacing Patterns
|
|
52
|
+
|
|
53
|
+
### Component Spacing
|
|
54
|
+
|
|
55
|
+
| Pattern | Class |
|
|
56
|
+
|---------|-------|
|
|
57
|
+
| Input field padding | `px-sui-12 py-sui-10` |
|
|
58
|
+
| Button padding (md) | `px-sui-12 py-sui-8` |
|
|
59
|
+
| Button padding (lg) | `px-sui-16 py-sui-12` |
|
|
60
|
+
| Card padding | `p-sui-24` |
|
|
61
|
+
| Form field gap | `gap-sui-16` |
|
|
62
|
+
| Section gap | `gap-sui-32` or `gap-sui-48` |
|
|
63
|
+
| Page margins | `mx-sui-24` or `mx-sui-32` |
|
|
64
|
+
|
|
65
|
+
### Layout Spacing
|
|
66
|
+
|
|
67
|
+
| Context | Class | Rationale |
|
|
68
|
+
|---------|-------|-----------|
|
|
69
|
+
| Between form fields | `gap-sui-16` | Comfortable reading distance |
|
|
70
|
+
| Between form sections | `gap-sui-32` | Clear visual grouping |
|
|
71
|
+
| Card internal padding | `p-sui-24` | Balanced white space |
|
|
72
|
+
| Modal/dialog padding | `p-sui-24` or `p-sui-32` | |
|
|
73
|
+
| Navigation items | `gap-sui-8` or `gap-sui-12` | |
|
|
74
|
+
|
|
75
|
+
**Example form spacing:**
|
|
76
|
+
```tsx
|
|
77
|
+
<form className="flex flex-col gap-sui-16">
|
|
78
|
+
<InputField label="Name" />
|
|
79
|
+
<InputField label="Email" />
|
|
80
|
+
<div className="mt-sui-16">
|
|
81
|
+
<h3 className="text-sui-text-default">Additional Info</h3>
|
|
82
|
+
</div>
|
|
83
|
+
<TextAreaField label="Bio" />
|
|
84
|
+
<Button className="mt-sui-24">Submit</Button>
|
|
85
|
+
</form>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Layout Primitives
|
|
91
|
+
|
|
92
|
+
SortUI does not provide explicit layout components (Stack, Inline, Box). Use **Tailwind Flexbox and Grid utilities** for layout.
|
|
93
|
+
|
|
94
|
+
### Flexbox Patterns
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
{/* Vertical stack */}
|
|
98
|
+
<div className="flex flex-col gap-sui-16">…</div>
|
|
99
|
+
|
|
100
|
+
{/* Horizontal inline */}
|
|
101
|
+
<div className="flex flex-row gap-sui-8 items-center">…</div>
|
|
102
|
+
|
|
103
|
+
{/* Space between (navbar) */}
|
|
104
|
+
<div className="flex items-center justify-between">…</div>
|
|
105
|
+
|
|
106
|
+
{/* Centered content */}
|
|
107
|
+
<div className="flex items-center justify-center min-h-screen">…</div>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Grid Patterns
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
{/* Responsive cards grid */}
|
|
114
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-sui-24">
|
|
115
|
+
<Card>Item 1</Card>
|
|
116
|
+
<Card>Item 2</Card>
|
|
117
|
+
<Card>Item 3</Card>
|
|
118
|
+
</div>
|
|
119
|
+
|
|
120
|
+
{/* Form grid */}
|
|
121
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-sui-16">
|
|
122
|
+
<InputField label="First Name" />
|
|
123
|
+
<InputField label="Last Name" />
|
|
124
|
+
<InputField label="Email" className="md:col-span-2" />
|
|
125
|
+
</div>
|
|
126
|
+
|
|
127
|
+
{/* Dashboard grid */}
|
|
128
|
+
<div className="grid grid-cols-12 gap-sui-24">
|
|
129
|
+
<div className="col-span-12 lg:col-span-8">Main</div>
|
|
130
|
+
<div className="col-span-12 lg:col-span-4">Sidebar</div>
|
|
131
|
+
</div>
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Responsive Patterns
|
|
137
|
+
|
|
138
|
+
### Breakpoints (Tailwind v3)
|
|
139
|
+
|
|
140
|
+
SortUI uses the **default Tailwind v3 breakpoints**:
|
|
141
|
+
|
|
142
|
+
| Breakpoint | Min Width | Usage |
|
|
143
|
+
|------------|-----------|-------|
|
|
144
|
+
| `sm` | 640px | Small tablets |
|
|
145
|
+
| `md` | 768px | Tablets |
|
|
146
|
+
| `lg` | 1024px | Laptops |
|
|
147
|
+
| `xl` | 1280px | Desktops |
|
|
148
|
+
| `2xl` | 1536px | Large desktops |
|
|
149
|
+
|
|
150
|
+
**Mobile-first approach:**
|
|
151
|
+
```tsx
|
|
152
|
+
<div className="p-sui-16 md:p-sui-24 lg:p-sui-32">Content</div>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Responsive Spacing
|
|
156
|
+
|
|
157
|
+
| Pattern | Mobile | Tablet | Desktop |
|
|
158
|
+
|---------|--------|--------|---------|
|
|
159
|
+
| Page container padding | `px-sui-16` | `md:px-sui-24` | `lg:px-sui-32` |
|
|
160
|
+
| Section gap | `gap-sui-32` | `md:gap-sui-48` | `lg:gap-sui-64` |
|
|
161
|
+
| Grid columns | 1 | 2 | 3–4 |
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
<div className="px-sui-16 md:px-sui-24 lg:px-sui-32 py-sui-32 md:py-sui-48 lg:py-sui-64">
|
|
165
|
+
<div className="max-w-7xl mx-auto">
|
|
166
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-sui-24">
|
|
167
|
+
{/* Cards */}
|
|
168
|
+
</div>
|
|
169
|
+
</div>
|
|
170
|
+
</div>
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Radius & Shadow in Layouts (NO `sui-` prefix)
|
|
176
|
+
|
|
177
|
+
Always use the correct class names (see `tokens.md` for the full list):
|
|
178
|
+
|
|
179
|
+
```tsx
|
|
180
|
+
{/* ✅ Card with radius + shadow */}
|
|
181
|
+
<div className="bg-sui-bg-card border border-sui-border-default rounded-lg shadow-card p-sui-24">
|
|
182
|
+
Content
|
|
183
|
+
</div>
|
|
184
|
+
|
|
185
|
+
{/* ✅ Pill */}
|
|
186
|
+
<div className="rounded-full bg-sui-badge-blue px-sui-12 py-sui-4">Label</div>
|
|
187
|
+
|
|
188
|
+
{/* ❌ Wrong */}
|
|
189
|
+
<div className="rounded-sui-lg shadow-sui-card" />
|
|
190
|
+
<div className="rounded-lg shadow-md" />
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Styling Approach
|
|
196
|
+
|
|
197
|
+
**Use Tailwind utilities FIRST:**
|
|
198
|
+
```tsx
|
|
199
|
+
<div className="flex items-center gap-sui-12 p-sui-16 bg-sui-bg-default border border-sui-border-default rounded-lg">
|
|
200
|
+
Content
|
|
201
|
+
</div>
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
**Use CSS custom properties for dynamic values:**
|
|
205
|
+
```tsx
|
|
206
|
+
<div style={{
|
|
207
|
+
color: "var(--text-subtle)",
|
|
208
|
+
padding: "var(--spacing-16)",
|
|
209
|
+
}}>
|
|
210
|
+
Content
|
|
211
|
+
</div>
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**Override component styles via `className`:**
|
|
215
|
+
```tsx
|
|
216
|
+
<Button className="w-full md:w-auto">
|
|
217
|
+
Full width on mobile, auto on desktop
|
|
218
|
+
</Button>
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Custom CSS (when needed, token-based only)
|
|
222
|
+
|
|
223
|
+
```css
|
|
224
|
+
.custom-card {
|
|
225
|
+
background: var(--bg-card);
|
|
226
|
+
border: 1px solid var(--border-default);
|
|
227
|
+
border-radius: var(--radius-md);
|
|
228
|
+
padding: var(--spacing-24);
|
|
229
|
+
box-shadow: var(--shadow-card);
|
|
230
|
+
}
|
|
231
|
+
.custom-card:hover {
|
|
232
|
+
box-shadow: var(--shadow-modal-sm);
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Component Reuse Rule (CRITICAL)
|
|
239
|
+
|
|
240
|
+
**Reuse existing SortUI components** instead of inlining custom markup. This keeps styling consistent across themes.
|
|
241
|
+
|
|
242
|
+
```tsx
|
|
243
|
+
// ✅ DO — reuse components
|
|
244
|
+
<Badge color="green" shape="pill">Active</Badge>
|
|
245
|
+
<Avatar src="/u.jpg" fallback="MS" size="md" />
|
|
246
|
+
<ProgressBar value={75} label labelText="Upload" />
|
|
247
|
+
<Button variant="default" size="md">Save</Button>
|
|
248
|
+
|
|
249
|
+
// ❌ DON'T — inline markup
|
|
250
|
+
<span className="inline-flex bg-green-100 text-green-800 px-sui-8 py-sui-4 rounded-full text-xs">Active</span>
|
|
251
|
+
<img src="/u.jpg" className="w-10 h-10 rounded-full" />
|
|
252
|
+
<div className="h-2 bg-sui-bg-muted rounded-full overflow-hidden">
|
|
253
|
+
<div style={{ width: "75%" }} className="h-full bg-sui-state-primary" />
|
|
254
|
+
</div>
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## DO / DON'T
|
|
260
|
+
|
|
261
|
+
**DO:**
|
|
262
|
+
```tsx
|
|
263
|
+
<div className="gap-sui-16 p-sui-24" />
|
|
264
|
+
<div className="bg-sui-bg-default text-sui-text-default" />
|
|
265
|
+
<div className="p-sui-16 md:p-sui-24 lg:p-sui-32" />
|
|
266
|
+
<div className="flex flex-col gap-sui-16" />
|
|
267
|
+
<div className="rounded-md shadow-card" />
|
|
268
|
+
<Button className="w-full md:w-auto">Submit</Button>
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**DON'T:**
|
|
272
|
+
```tsx
|
|
273
|
+
<div className="gap-[16px] p-[24px]" /> {/* ❌ arbitrary */}
|
|
274
|
+
<div className="bg-[#ffffff] text-[#111115]" /> {/* ❌ hex */}
|
|
275
|
+
<div className="lg:p-sui-32 md:p-sui-24 p-sui-16" /> {/* ❌ desktop-first */}
|
|
276
|
+
<Button style={{ padding: "20px" }}>Submit</Button> {/* ❌ inline style */}
|
|
277
|
+
<div className="rounded-sui-md shadow-sui-default" /> {/* ❌ wrong prefix */}
|
|
278
|
+
<div className="rounded-md shadow-md shadow-lg" /> {/* ❌ generic shadow */}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## Layout Examples
|
|
284
|
+
|
|
285
|
+
### Dashboard Layout
|
|
286
|
+
```tsx
|
|
287
|
+
<div className="min-h-screen bg-sui-bg-subtle">
|
|
288
|
+
<header className="bg-sui-bg-default border-b border-sui-border-default px-sui-24 py-sui-16">
|
|
289
|
+
<div className="max-w-7xl mx-auto flex items-center justify-between">
|
|
290
|
+
<h1 className="text-sui-text-default font-semibold">Dashboard</h1>
|
|
291
|
+
<nav className="flex gap-sui-12">
|
|
292
|
+
<Button variant="ghost">Settings</Button>
|
|
293
|
+
</nav>
|
|
294
|
+
</div>
|
|
295
|
+
</header>
|
|
296
|
+
|
|
297
|
+
<main className="max-w-7xl mx-auto px-sui-24 py-sui-32">
|
|
298
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-sui-24">
|
|
299
|
+
<Card>…</Card>
|
|
300
|
+
<Card>…</Card>
|
|
301
|
+
<Card>…</Card>
|
|
302
|
+
</div>
|
|
303
|
+
</main>
|
|
304
|
+
</div>
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Form Layout
|
|
308
|
+
```tsx
|
|
309
|
+
<div className="max-w-md mx-auto p-sui-24">
|
|
310
|
+
<form className="flex flex-col gap-sui-16">
|
|
311
|
+
<h2 className="text-2xl font-semibold text-sui-text-default mb-sui-8">Sign Up</h2>
|
|
312
|
+
<InputField label="Name" required />
|
|
313
|
+
<InputField label="Email" type="email" required />
|
|
314
|
+
<InputField label="Password" type="password" required />
|
|
315
|
+
<CheckboxWithText label="I agree to the terms" />
|
|
316
|
+
<Button type="submit" className="mt-sui-16">Create Account</Button>
|
|
317
|
+
</form>
|
|
318
|
+
</div>
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Article Layout
|
|
322
|
+
```tsx
|
|
323
|
+
<div className="max-w-4xl mx-auto px-sui-24 py-sui-64">
|
|
324
|
+
<article className="space-y-sui-32">
|
|
325
|
+
<header className="space-y-sui-16">
|
|
326
|
+
<h1 className="text-4xl font-bold text-sui-text-default">Article Title</h1>
|
|
327
|
+
<p className="text-sui-text-muted">Published on Jan 1, 2026</p>
|
|
328
|
+
</header>
|
|
329
|
+
<div className="prose">
|
|
330
|
+
<p className="text-sui-text-default">Article content…</p>
|
|
331
|
+
</div>
|
|
332
|
+
<footer className="border-t border-sui-border-default pt-sui-24">
|
|
333
|
+
<div className="flex items-center gap-sui-12">
|
|
334
|
+
<Avatar src="/author.jpg" fallback="JD" size="md" />
|
|
335
|
+
<div>
|
|
336
|
+
<p className="font-semibold text-sui-text-default">John Doe</p>
|
|
337
|
+
<p className="text-sm text-sui-text-subtle">Author</p>
|
|
338
|
+
</div>
|
|
339
|
+
</div>
|
|
340
|
+
</footer>
|
|
341
|
+
</article>
|
|
342
|
+
</div>
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## Summary
|
|
348
|
+
|
|
349
|
+
- **Tailwind v3**, mobile-first, semantic tokens
|
|
350
|
+
- **Spacing with `sui-` prefix**: `gap-sui-16`, `p-sui-24`, `m-sui-8`
|
|
351
|
+
- **Radius & Shadow WITHOUT `sui-` prefix**: `rounded-md`, `shadow-card`
|
|
352
|
+
- **Use Flexbox and Grid utilities** for layout
|
|
353
|
+
- **Reuse SortUI components** (Badge, Avatar, Button, ProgressBar, etc.) instead of inlining markup
|
|
354
|
+
- **Responsive breakpoints**: `sm`, `md`, `lg`, `xl`, `2xl`
|
|
355
|
+
- **Semantic color tokens** over hard-coded hex/rgb
|
|
356
|
+
- **Common spacing**: 16px between form fields, 24px card padding, 32px section gaps
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
# Design Tokens and CSS Guidelines
|
|
2
|
+
|
|
3
|
+
Design tokens, CSS custom properties, and theming in SortUI. Uses **Tailwind v3** (`^3.4.1`) — never v4.
|
|
4
|
+
|
|
5
|
+
## Token Format
|
|
6
|
+
|
|
7
|
+
Tokens are consumed as **CSS custom properties** (variables) and **Tailwind v3 utility classes**.
|
|
8
|
+
|
|
9
|
+
```css
|
|
10
|
+
/* CSS custom properties */
|
|
11
|
+
color: var(--text-default);
|
|
12
|
+
background: var(--bg-subtle);
|
|
13
|
+
border-radius: var(--radius-md);
|
|
14
|
+
box-shadow: var(--shadow-card);
|
|
15
|
+
|
|
16
|
+
/* Tailwind v3 classes (via SortUI preset) */
|
|
17
|
+
<div className="bg-sui-bg-default text-sui-text-default rounded-md shadow-card p-sui-24" />
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### `sui-` prefix rules (CRITICAL)
|
|
21
|
+
|
|
22
|
+
The `sui-` prefix is applied **selectively**. Memorize this table.
|
|
23
|
+
|
|
24
|
+
| Category | Prefix? | Correct | Wrong |
|
|
25
|
+
|---|---|---|---|
|
|
26
|
+
| Color — text | yes | `text-sui-text-default`, `text-sui-text-muted` | `text-default` |
|
|
27
|
+
| Color — background | yes | `bg-sui-bg-default`, `bg-sui-bg-subtle` | `bg-default` |
|
|
28
|
+
| Color — border | yes | `border-sui-border-default` | `border-default` |
|
|
29
|
+
| Color — icon | yes | `text-sui-icon-default`, `text-sui-icon-destructive` | `text-icon-default` |
|
|
30
|
+
| Spacing | yes | `gap-sui-16`, `p-sui-24`, `mx-sui-32`, `space-y-sui-16` | `gap-16` |
|
|
31
|
+
| Badge background | yes | `bg-sui-badge-blue`, `bg-sui-badge-red` | `bg-badge-blue` |
|
|
32
|
+
| **Radius** | **no** | `rounded-md`, `rounded-lg`, `rounded-full`, `rounded-card-md` | ~~`rounded-sui-md`~~ |
|
|
33
|
+
| **Shadow** | **no** | `shadow-default`, `shadow-card`, `shadow-focus`, `shadow-modal-md` | ~~`shadow-sui-default`~~ ~~`shadow-md`~~ |
|
|
34
|
+
| **Border width** | **no** | `border` (1px), `border-md` (1.5px), `border-lg` (2px) | ~~`border-sui-md`~~ |
|
|
35
|
+
| **Font size** | **no** | `text-sm`, `text-base`, `text-2xl` | ~~`text-sui-md`~~ |
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Theming — 4 Themes
|
|
40
|
+
|
|
41
|
+
SortUI provides **4 theme variants**. All four must render correctly for any generated UI.
|
|
42
|
+
|
|
43
|
+
- `light` — zinc/blue, light mode (default)
|
|
44
|
+
- `dark` — zinc/blue, dark mode
|
|
45
|
+
- `theme-2` — neutral/orange, light mode
|
|
46
|
+
- `theme-2-dark` — neutral/orange, dark mode
|
|
47
|
+
|
|
48
|
+
**Apply theme class to `<html>` or `<body>`:**
|
|
49
|
+
```tsx
|
|
50
|
+
<html className="dark">
|
|
51
|
+
{/* App renders in dark theme */}
|
|
52
|
+
</html>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Color Tokens
|
|
58
|
+
|
|
59
|
+
### Text Tokens
|
|
60
|
+
|
|
61
|
+
| Token | Usage | Tailwind class |
|
|
62
|
+
|-------|-------|----------------|
|
|
63
|
+
| `--text-default` | Primary text | `text-sui-text-default` |
|
|
64
|
+
| `--text-subtle` | Secondary text | `text-sui-text-subtle` |
|
|
65
|
+
| `--text-muted` | Tertiary text | `text-sui-text-muted` |
|
|
66
|
+
| `--text-hint` | Placeholder text | `text-sui-text-hint` |
|
|
67
|
+
| `--text-inverted-default` | Text on dark backgrounds | `text-sui-text-inverted-default` |
|
|
68
|
+
| `--text-inverted-subtle` | Subtle text on dark | `text-sui-text-inverted-subtle` |
|
|
69
|
+
| `--text-destructive` | Error/danger text | `text-sui-text-destructive` |
|
|
70
|
+
| `--text-primary` | Primary brand text | `text-sui-text-primary` |
|
|
71
|
+
| `--text-success` | Success text | `text-sui-text-success` |
|
|
72
|
+
| `--text-warning` | Warning text | `text-sui-text-warning` |
|
|
73
|
+
| `--text-informative` | Info text | `text-sui-text-informative` |
|
|
74
|
+
|
|
75
|
+
### Background Tokens
|
|
76
|
+
|
|
77
|
+
| Token | Usage | Tailwind class |
|
|
78
|
+
|-------|-------|----------------|
|
|
79
|
+
| `--bg-default` | Page/card background | `bg-sui-bg-default` |
|
|
80
|
+
| `--bg-subtle` | Subtle background | `bg-sui-bg-subtle` |
|
|
81
|
+
| `--bg-muted` | Muted background | `bg-sui-bg-muted` |
|
|
82
|
+
| `--bg-card` | Card background | `bg-sui-bg-card` |
|
|
83
|
+
| `--bg-inverted` | Dark background | `bg-sui-bg-inverted` |
|
|
84
|
+
|
|
85
|
+
**State backgrounds:** `bg-sui-state-primary`, `bg-sui-state-primary-hover`, `bg-sui-state-destructive`, `bg-sui-state-soft`, `bg-sui-state-ghost`, `bg-sui-state-disabled`, etc.
|
|
86
|
+
|
|
87
|
+
**Badge backgrounds (semantic color scale):**
|
|
88
|
+
- `bg-sui-badge-red`, `bg-sui-badge-orange`, `bg-sui-badge-yellow`, `bg-sui-badge-lime`, `bg-sui-badge-green`, `bg-sui-badge-emerald`, `bg-sui-badge-teal`, `bg-sui-badge-cyan`, `bg-sui-badge-sky`, `bg-sui-badge-blue`, `bg-sui-badge-indigo`, `bg-sui-badge-violet`, `bg-sui-badge-purple`, `bg-sui-badge-fuchsia`, `bg-sui-badge-pink`, `bg-sui-badge-gray`, `bg-sui-badge-white`, `bg-sui-badge-inverted`
|
|
89
|
+
|
|
90
|
+
### Border Color Tokens
|
|
91
|
+
|
|
92
|
+
| Token | Usage | Tailwind class |
|
|
93
|
+
|-------|-------|----------------|
|
|
94
|
+
| `--border-default` | Default borders | `border-sui-border-default` |
|
|
95
|
+
| `--border-darker` | Stronger borders | `border-sui-border-darker` |
|
|
96
|
+
| `--border-strong` | Strong borders | `border-sui-border-strong` |
|
|
97
|
+
| `--border-accent` | Accent borders | `border-sui-border-accent` |
|
|
98
|
+
| `--border-destructive` | Error borders | `border-sui-border-destructive` |
|
|
99
|
+
| `--border-informative` | Info borders | `border-sui-border-informative` |
|
|
100
|
+
| `--border-success` | Success borders | `border-sui-border-success` |
|
|
101
|
+
| `--border-warning` | Warning borders | `border-sui-border-warning` |
|
|
102
|
+
|
|
103
|
+
### Icon Color Tokens
|
|
104
|
+
|
|
105
|
+
| Token | Usage | Tailwind class |
|
|
106
|
+
|-------|-------|----------------|
|
|
107
|
+
| `--icon-default` | Primary icons | `text-sui-icon-default` |
|
|
108
|
+
| `--icon-default-subtle` | Subtle icons | `text-sui-icon-subtle` |
|
|
109
|
+
| `--icon-default-muted` | Muted icons | `text-sui-icon-muted` |
|
|
110
|
+
| `--icon-default-disabled` | Disabled icons | `text-sui-icon-disabled` |
|
|
111
|
+
| `--icon-inverted-default` | Icons on dark backgrounds | `text-sui-icon-inverted-default` |
|
|
112
|
+
| `--icon-destructive` | Error icons | `text-sui-icon-destructive` |
|
|
113
|
+
| `--icon-informative` | Info icons | `text-sui-icon-informative` |
|
|
114
|
+
| `--icon-success` | Success icons | `text-sui-icon-success` |
|
|
115
|
+
| `--icon-warning` | Warning icons | `text-sui-icon-warning` |
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Typography Tokens
|
|
120
|
+
|
|
121
|
+
### Font Family
|
|
122
|
+
|
|
123
|
+
| Token | Tailwind | Default |
|
|
124
|
+
|-------|----------|---------|
|
|
125
|
+
| `--font-body` | `font-sans` | Geist Sans (bundled) |
|
|
126
|
+
| `--font-headline` | `font-headline` | Geist Sans |
|
|
127
|
+
| `--font-quote` | `font-quote` | Redaction (bundled) |
|
|
128
|
+
| `--font-quote-alt` | `font-quote-alt` | Redaction 35 |
|
|
129
|
+
| `--font-code` | `font-code` | Geist Mono (bundled) |
|
|
130
|
+
|
|
131
|
+
### Font Size (Tailwind v3 classes)
|
|
132
|
+
|
|
133
|
+
Use `text-xs` through `text-9xl` — these are native Tailwind classes wired to SortUI tokens. **Do NOT use `text-sui-*` font-size classes.**
|
|
134
|
+
|
|
135
|
+
| Class | Size | Usage |
|
|
136
|
+
|-------|------|-------|
|
|
137
|
+
| `text-xs` | 12px | Small labels, captions |
|
|
138
|
+
| `text-sm` | 14px | Body text (small) |
|
|
139
|
+
| `text-base` | 16px | Body text (default) — also `text-md` |
|
|
140
|
+
| `text-lg` | 18px | Large body text |
|
|
141
|
+
| `text-xl` | 20px | Small headings |
|
|
142
|
+
| `text-2xl` | 24px | Headings (H3) |
|
|
143
|
+
| `text-3xl` | 30px | Headings (H2) |
|
|
144
|
+
| `text-4xl` | 36px | Headings (H1) |
|
|
145
|
+
| `text-5xl` – `text-9xl` | 48–128px | Display / hero text |
|
|
146
|
+
|
|
147
|
+
### Font Weight
|
|
148
|
+
|
|
149
|
+
`font-light` (300), `font-normal` (400), `font-medium` (500), `font-semibold` (600), `font-bold` (700), `font-extrabold` (800), `font-black` (900).
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Shadow Tokens (NO `sui-` prefix)
|
|
154
|
+
|
|
155
|
+
Use ONLY these Figma-aligned shadow classes. **Never** use `shadow-sm`, `shadow-md`, `shadow-lg`, arbitrary `shadow-[…]`, or `shadow-sui-*`.
|
|
156
|
+
|
|
157
|
+
| Tailwind class | CSS var | Usage |
|
|
158
|
+
|----------------|---------|-------|
|
|
159
|
+
| `shadow-default` | `--shadow-default` | Default element shadow |
|
|
160
|
+
| `shadow-card` | `--shadow-card` | Card shadow |
|
|
161
|
+
| `shadow-card-base` | `--shadow-card-base` | Base card shadow |
|
|
162
|
+
| `shadow-focus` | `--shadow-focus` | Focus ring |
|
|
163
|
+
| `shadow-destructive-focus` | `--shadow-destructive-focus` | Destructive focus ring |
|
|
164
|
+
| `shadow-misc-focus` | `--shadow-misc-focus` | Misc focus |
|
|
165
|
+
| `shadow-input-focus` | `--shadow-input-focus` | Input focus |
|
|
166
|
+
| `shadow-modal-sm` | `--shadow-modal-sm` | Small modal |
|
|
167
|
+
| `shadow-modal-md` | `--shadow-modal-md` | Medium modal |
|
|
168
|
+
| `shadow-modal-lg` | `--shadow-modal-lg` | Large modal |
|
|
169
|
+
| `shadow-switch-handle` | `--shadow-switch-handle` | Switch handle |
|
|
170
|
+
| `shadow-checkbox` / `shadow-checkbox-active` | | Checkbox |
|
|
171
|
+
| `shadow-inset-bottom` / `-soft` / `-strong` | | Inset bottom |
|
|
172
|
+
| `shadow-tab-active` | `--shadow-tab-active` | Active tab |
|
|
173
|
+
| `shadow-button-default` / `-press` / `-secondary` / `-secondary-press` | | Button shadows |
|
|
174
|
+
|
|
175
|
+
```tsx
|
|
176
|
+
<div className="shadow-card" />
|
|
177
|
+
<div className="shadow-default" />
|
|
178
|
+
<button className="shadow-button-default active:shadow-button-press" />
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## Border & Radius Tokens
|
|
184
|
+
|
|
185
|
+
### Border Width (NO `sui-` prefix)
|
|
186
|
+
|
|
187
|
+
| Class | Width |
|
|
188
|
+
|-------|-------|
|
|
189
|
+
| `border-sm` | 0.5px |
|
|
190
|
+
| `border` | 1px (default) |
|
|
191
|
+
| `border-md` | 1.5px |
|
|
192
|
+
| `border-lg` | 2px |
|
|
193
|
+
| `border-xl` | 3px |
|
|
194
|
+
| `border-2xl` | 4px |
|
|
195
|
+
|
|
196
|
+
### Border Radius (NO `sui-` prefix)
|
|
197
|
+
|
|
198
|
+
| Class | Radius |
|
|
199
|
+
|-------|--------|
|
|
200
|
+
| `rounded-none` | 0px |
|
|
201
|
+
| `rounded-2xs` | 2px |
|
|
202
|
+
| `rounded-xs` | 4px |
|
|
203
|
+
| `rounded-sm` | 6px |
|
|
204
|
+
| `rounded-md` | 8px |
|
|
205
|
+
| `rounded-lg` | 12px |
|
|
206
|
+
| `rounded-xl` | 16px |
|
|
207
|
+
| `rounded-2xl` | 24px |
|
|
208
|
+
| `rounded-3xl` | 28px |
|
|
209
|
+
| `rounded-full` | 9999px (pill) |
|
|
210
|
+
| `rounded-card-none` / `-xs` / `-sm` / `-md` / `-lg` | Card-specific |
|
|
211
|
+
|
|
212
|
+
```tsx
|
|
213
|
+
<div className="rounded-md" /> {/* 8px */}
|
|
214
|
+
<div className="rounded-lg" /> {/* 12px */}
|
|
215
|
+
<div className="rounded-full" /> {/* pill */}
|
|
216
|
+
<div className="rounded-card-md" /> {/* card-aligned */}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Spacing Tokens (WITH `sui-` prefix)
|
|
222
|
+
|
|
223
|
+
Use spacing tokens from `--spacing-1` to `--spacing-384`, exposed as `p-sui-16`, `gap-sui-12`, etc.
|
|
224
|
+
|
|
225
|
+
| Class | Size | Common usage |
|
|
226
|
+
|-------|------|--------------|
|
|
227
|
+
| `gap-sui-none` | 0 | No spacing |
|
|
228
|
+
| `gap-sui-4` | 4px | Tight groups |
|
|
229
|
+
| `gap-sui-8` | 8px | Small |
|
|
230
|
+
| `gap-sui-12` | 12px | Inline items |
|
|
231
|
+
| `gap-sui-16` | 16px | Form fields |
|
|
232
|
+
| `gap-sui-20` | 20px | Medium+ |
|
|
233
|
+
| `gap-sui-24` | 24px | Card internal |
|
|
234
|
+
| `gap-sui-32` | 32px | Section break |
|
|
235
|
+
| `gap-sui-48` | 48px | Major section |
|
|
236
|
+
| `gap-sui-64` | 64px | Page section |
|
|
237
|
+
|
|
238
|
+
Works across all spacing utilities: `p-`, `m-`, `gap-`, `space-x-`, `space-y-`, etc.
|
|
239
|
+
|
|
240
|
+
```tsx
|
|
241
|
+
<div className="gap-sui-16 p-sui-24" />
|
|
242
|
+
<div className="space-y-sui-16" />
|
|
243
|
+
<div className="mx-sui-32 my-sui-24" />
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## DO / DON'T
|
|
249
|
+
|
|
250
|
+
**DO:**
|
|
251
|
+
```tsx
|
|
252
|
+
// Semantic color tokens
|
|
253
|
+
<div className="bg-sui-bg-subtle text-sui-text-default border border-sui-border-default" />
|
|
254
|
+
|
|
255
|
+
// Correct radius (NO sui- prefix)
|
|
256
|
+
<div className="rounded-md" />
|
|
257
|
+
<div className="rounded-lg" />
|
|
258
|
+
|
|
259
|
+
// Correct shadow (NO sui- prefix)
|
|
260
|
+
<div className="shadow-card" />
|
|
261
|
+
<div className="shadow-default" />
|
|
262
|
+
|
|
263
|
+
// Correct spacing (WITH sui- prefix)
|
|
264
|
+
<div className="p-sui-24 gap-sui-16" />
|
|
265
|
+
|
|
266
|
+
// CSS variable for dynamic values
|
|
267
|
+
<div style={{ color: "var(--text-subtle)" }} />
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
**DON'T:**
|
|
271
|
+
```tsx
|
|
272
|
+
// ❌ sui- prefix on radius/shadow
|
|
273
|
+
<div className="rounded-sui-md shadow-sui-default" />
|
|
274
|
+
|
|
275
|
+
// ❌ Generic Tailwind shadow primitives
|
|
276
|
+
<div className="shadow-md shadow-lg" />
|
|
277
|
+
|
|
278
|
+
// ❌ Hardcoded hex/arbitrary values
|
|
279
|
+
<div className="bg-[#fafafa] text-[#111115] gap-[16px]" />
|
|
280
|
+
|
|
281
|
+
// ❌ Missing sui- on colors/spacing
|
|
282
|
+
<div className="bg-bg-default text-text-default gap-16" />
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## Token Usage Examples
|
|
288
|
+
|
|
289
|
+
**Card:**
|
|
290
|
+
```tsx
|
|
291
|
+
<div className="bg-sui-bg-card border border-sui-border-default rounded-card-md shadow-card p-sui-24">
|
|
292
|
+
<h3 className="text-sui-text-default font-semibold">Card title</h3>
|
|
293
|
+
<p className="text-sui-text-subtle">Card body</p>
|
|
294
|
+
</div>
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
**Button (primary):**
|
|
298
|
+
```css
|
|
299
|
+
.custom-button {
|
|
300
|
+
background: var(--bg-state-primary);
|
|
301
|
+
color: var(--text-inverted-default);
|
|
302
|
+
border-radius: var(--radius-md);
|
|
303
|
+
padding: var(--spacing-12) var(--spacing-24);
|
|
304
|
+
box-shadow: var(--shadow-button-default);
|
|
305
|
+
}
|
|
306
|
+
.custom-button:hover { background: var(--bg-state-primary-hover); }
|
|
307
|
+
.custom-button:active { box-shadow: var(--shadow-button-press); }
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
**Input:**
|
|
311
|
+
```css
|
|
312
|
+
.custom-input {
|
|
313
|
+
background: var(--bg-default);
|
|
314
|
+
border: 1px solid var(--border-default);
|
|
315
|
+
border-radius: var(--radius-sm);
|
|
316
|
+
color: var(--text-default);
|
|
317
|
+
padding: var(--spacing-8) var(--spacing-12);
|
|
318
|
+
}
|
|
319
|
+
.custom-input:focus {
|
|
320
|
+
border-color: var(--border-informative);
|
|
321
|
+
box-shadow: var(--shadow-input-focus);
|
|
322
|
+
}
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## Chart Color Tokens
|
|
328
|
+
|
|
329
|
+
For data visualization (Recharts integration):
|
|
330
|
+
|
|
331
|
+
| Token | Default |
|
|
332
|
+
|-------|---------|
|
|
333
|
+
| `--chart-1` | blue |
|
|
334
|
+
| `--chart-2` | green |
|
|
335
|
+
| `--chart-3` | orange |
|
|
336
|
+
| `--chart-4` | red |
|
|
337
|
+
| `--chart-5` | purple |
|
|
338
|
+
|
|
339
|
+
**Usage in charts (note `isAnimationActive={false}` — required for React 19):**
|
|
340
|
+
```tsx
|
|
341
|
+
<Line dataKey="revenue" stroke="var(--chart-1)" isAnimationActive={false} />
|
|
342
|
+
<Bar dataKey="sales" fill="var(--chart-2)" isAnimationActive={false} />
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## Summary
|
|
348
|
+
|
|
349
|
+
- **Use semantic tokens** over raw values
|
|
350
|
+
- **Tokens are CSS custom properties** (`var(--token-name)`)
|
|
351
|
+
- **Tailwind v3** utility classes — never emit Tailwind v4 syntax
|
|
352
|
+
- **Selective `sui-` prefix** — colors + spacing yes; radius + shadow + border-width + font-size no
|
|
353
|
+
- **Theming** via class on root element (`light`, `dark`, `theme-2`, `theme-2-dark`)
|
|
354
|
+
- **All tokens** automatically adapt to theme changes
|