@tydavidson/design-system 1.1.16 → 1.1.18
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/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +77 -283
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +78 -281
- package/dist/index.mjs.map +1 -1
- package/dist/themes/index.d.mts +12 -53
- package/dist/themes/index.d.ts +12 -53
- package/dist/themes/index.js +73 -237
- package/dist/themes/index.js.map +1 -1
- package/dist/themes/index.mjs +74 -235
- package/dist/themes/index.mjs.map +1 -1
- package/docs/theme-usage.md +191 -542
- package/package.json +1 -1
package/docs/theme-usage.md
CHANGED
@@ -1,449 +1,156 @@
|
|
1
|
-
#
|
1
|
+
# Theme Usage Guide
|
2
2
|
|
3
|
-
|
3
|
+
This guide explains how to use the theme system in the Float Design System.
|
4
4
|
|
5
|
-
##
|
6
|
-
|
7
|
-
- [Installation](#installation)
|
8
|
-
- [Quick Start](#quick-start)
|
9
|
-
- [Core Components](#core-components)
|
10
|
-
- [Theme Variables](#theme-variables)
|
11
|
-
- [Advanced Usage](#advanced-usage)
|
12
|
-
- [Framework Integration](#framework-integration)
|
13
|
-
- [Troubleshooting](#troubleshooting)
|
5
|
+
## Quick Start
|
14
6
|
|
15
|
-
|
7
|
+
### 1. Install the Package
|
16
8
|
|
17
9
|
```bash
|
18
10
|
npm install @tydavidson/design-system
|
19
11
|
```
|
20
12
|
|
21
|
-
|
22
|
-
|
23
|
-
### 1. Import Theme CSS
|
24
|
-
|
25
|
-
Import the theme CSS to get access to all theme variables:
|
26
|
-
|
27
|
-
```css
|
28
|
-
/* In your main CSS file */
|
29
|
-
@import '@tydavidson/design-system/themes/theme.css';
|
30
|
-
```
|
31
|
-
|
32
|
-
Or in your JavaScript/TypeScript:
|
33
|
-
|
34
|
-
```typescript
|
35
|
-
import '@tydavidson/design-system/themes/theme.css';
|
36
|
-
```
|
37
|
-
|
38
|
-
### 2. Set up Theme Providers
|
39
|
-
|
40
|
-
Wrap your app with the theme providers:
|
13
|
+
### 2. Import CSS
|
41
14
|
|
42
15
|
```tsx
|
43
|
-
|
44
|
-
|
45
|
-
function App() {
|
46
|
-
return (
|
47
|
-
<ThemeProvider>
|
48
|
-
<ThemeContextProvider>
|
49
|
-
{/* Your app content */}
|
50
|
-
<Header />
|
51
|
-
<Main />
|
52
|
-
<Footer />
|
53
|
-
</ThemeContextProvider>
|
54
|
-
</ThemeProvider>
|
55
|
-
);
|
56
|
-
}
|
16
|
+
// In your main CSS file or layout
|
17
|
+
import '@tydavidson/design-system/src/themes/theme.css';
|
57
18
|
```
|
58
19
|
|
59
|
-
### 3.
|
60
|
-
|
61
|
-
Add the theme toggle component to your app:
|
20
|
+
### 3. Set Up Theme Provider
|
62
21
|
|
63
22
|
```tsx
|
64
|
-
|
23
|
+
// app/layout.tsx
|
24
|
+
import { ClientThemeProvider } from '@tydavidson/design-system/themes';
|
65
25
|
|
66
|
-
function
|
26
|
+
export default function RootLayout({ children }) {
|
67
27
|
return (
|
68
|
-
<
|
69
|
-
<
|
70
|
-
<
|
71
|
-
|
72
|
-
|
73
|
-
|
28
|
+
<html lang="en" suppressHydrationWarning>
|
29
|
+
<body>
|
30
|
+
<ClientThemeProvider>
|
31
|
+
{children}
|
32
|
+
</ClientThemeProvider>
|
33
|
+
</body>
|
34
|
+
</html>
|
74
35
|
);
|
75
36
|
}
|
76
37
|
```
|
77
38
|
|
78
|
-
|
79
|
-
|
80
|
-
### ThemeToggle
|
81
|
-
|
82
|
-
A flexible component for switching between light and dark themes with multiple variants.
|
83
|
-
|
84
|
-
```tsx
|
85
|
-
import { ThemeToggle } from '@tydavidson/design-system';
|
86
|
-
|
87
|
-
// Icon variant (default) - Compact toggle with sun/moon icons
|
88
|
-
<ThemeToggle variant="icon" size="md" />
|
89
|
-
|
90
|
-
// Button variant - Full button with text
|
91
|
-
<ThemeToggle variant="button" size="lg" />
|
92
|
-
|
93
|
-
// Switch variant - Toggle switch style
|
94
|
-
<ThemeToggle variant="switch" size="sm" />
|
95
|
-
```
|
96
|
-
|
97
|
-
**Props:**
|
98
|
-
- `variant`: `'icon' | 'switch' | 'button'` (default: `'icon'`)
|
99
|
-
- `size`: `'sm' | 'md' | 'lg'` (default: `'md'`)
|
100
|
-
- `className`: Additional CSS classes
|
101
|
-
|
102
|
-
**Examples:**
|
39
|
+
### 4. Use Theme Toggle
|
103
40
|
|
104
41
|
```tsx
|
105
|
-
// In
|
106
|
-
|
107
|
-
<ThemeToggle variant="icon" size="sm" />
|
108
|
-
<ThemeToggle variant="button" size="md" />
|
109
|
-
</div>
|
110
|
-
|
111
|
-
// In a sidebar
|
112
|
-
<nav className="flex flex-col gap-2">
|
113
|
-
<ThemeToggle variant="switch" size="lg" />
|
114
|
-
</nav>
|
115
|
-
```
|
116
|
-
|
117
|
-
### useTheme Hook
|
42
|
+
// In any component
|
43
|
+
import { ClientThemeToggle } from '@tydavidson/design-system/themes';
|
118
44
|
|
119
|
-
|
120
|
-
|
121
|
-
```tsx
|
122
|
-
import { useTheme } from '@tydavidson/design-system';
|
123
|
-
|
124
|
-
function ThemeAwareComponent() {
|
125
|
-
const {
|
126
|
-
theme, // Current theme setting ('light', 'dark', 'system')
|
127
|
-
setTheme, // Function to change theme
|
128
|
-
resolvedTheme, // Actual theme ('light' or 'dark')
|
129
|
-
isDark, // Boolean for dark mode
|
130
|
-
isClient // Boolean for client-side rendering
|
131
|
-
} = useTheme();
|
132
|
-
|
45
|
+
export default function MyPage() {
|
133
46
|
return (
|
134
|
-
<div
|
135
|
-
<
|
136
|
-
<
|
137
|
-
<p>Current setting: {theme}</p>
|
138
|
-
<p>Resolved theme: {resolvedTheme}</p>
|
139
|
-
<p>Is dark mode: {isDark ? 'Yes' : 'No'}</p>
|
140
|
-
</div>
|
141
|
-
|
142
|
-
<div className="flex gap-2 mt-4">
|
143
|
-
<button
|
144
|
-
onClick={() => setTheme('light')}
|
145
|
-
className="px-3 py-1 bg-bg-primary border border-border-primary rounded text-text-primary hover:bg-bg-tertiary"
|
146
|
-
>
|
147
|
-
Light
|
148
|
-
</button>
|
149
|
-
<button
|
150
|
-
onClick={() => setTheme('dark')}
|
151
|
-
className="px-3 py-1 bg-bg-primary border border-border-primary rounded text-text-primary hover:bg-bg-tertiary"
|
152
|
-
>
|
153
|
-
Dark
|
154
|
-
</button>
|
155
|
-
<button
|
156
|
-
onClick={() => setTheme('system')}
|
157
|
-
className="px-3 py-1 bg-bg-primary border border-border-primary rounded text-text-primary hover:bg-bg-tertiary"
|
158
|
-
>
|
159
|
-
System
|
160
|
-
</button>
|
161
|
-
</div>
|
47
|
+
<div>
|
48
|
+
<h1>My App</h1>
|
49
|
+
<ClientThemeToggle />
|
162
50
|
</div>
|
163
51
|
);
|
164
52
|
}
|
165
53
|
```
|
166
54
|
|
167
|
-
##
|
168
|
-
|
169
|
-
### CSS Variables
|
170
|
-
|
171
|
-
The theme system provides comprehensive CSS custom properties:
|
172
|
-
|
173
|
-
```css
|
174
|
-
/* Background colors */
|
175
|
-
.my-component {
|
176
|
-
background-color: var(--bg-primary);
|
177
|
-
color: var(--text-primary);
|
178
|
-
border: 1px solid var(--border-primary);
|
179
|
-
}
|
180
|
-
|
181
|
-
/* Semantic colors */
|
182
|
-
.success-message {
|
183
|
-
background-color: var(--bg-success-primary);
|
184
|
-
color: var(--text-success-primary);
|
185
|
-
border-color: var(--border-success);
|
186
|
-
}
|
187
|
-
|
188
|
-
.error-message {
|
189
|
-
background-color: var(--bg-error-primary);
|
190
|
-
color: var(--text-error-primary);
|
191
|
-
border-color: var(--border-error);
|
192
|
-
}
|
193
|
-
```
|
194
|
-
|
195
|
-
### Tailwind Classes
|
55
|
+
## Available Components
|
196
56
|
|
197
|
-
|
57
|
+
### Server Component Safe Components
|
198
58
|
|
199
|
-
|
200
|
-
// Basic layout
|
201
|
-
<div className="bg-bg-primary text-text-primary min-h-screen">
|
202
|
-
<header className="bg-bg-secondary border-b border-border-primary p-4">
|
203
|
-
<h1 className="text-text-primary font-bold">My App</h1>
|
204
|
-
</header>
|
205
|
-
|
206
|
-
<main className="p-6">
|
207
|
-
<div className="bg-bg-tertiary border border-border-secondary rounded-lg p-4">
|
208
|
-
<p className="text-text-secondary">Content goes here</p>
|
209
|
-
</div>
|
210
|
-
</main>
|
211
|
-
</div>
|
212
|
-
|
213
|
-
// Semantic components
|
214
|
-
<div className="space-y-4">
|
215
|
-
<div className="bg-bg-success-primary text-text-success-primary border border-border-success rounded p-3">
|
216
|
-
Success message
|
217
|
-
</div>
|
218
|
-
|
219
|
-
<div className="bg-bg-error-primary text-text-error-primary border border-border-error rounded p-3">
|
220
|
-
Error message
|
221
|
-
</div>
|
222
|
-
|
223
|
-
<div className="bg-bg-warning-primary text-text-warning-primary border border-border-warning rounded p-3">
|
224
|
-
Warning message
|
225
|
-
</div>
|
226
|
-
</div>
|
227
|
-
```
|
228
|
-
|
229
|
-
### Available Color Variables
|
230
|
-
|
231
|
-
#### Background Colors
|
232
|
-
- `--bg-primary` / `bg-bg-primary` - Main background
|
233
|
-
- `--bg-secondary` / `bg-bg-secondary` - Secondary background
|
234
|
-
- `--bg-tertiary` / `bg-bg-tertiary` - Tertiary background
|
235
|
-
- `--bg-quaternary` / `bg-bg-quaternary` - Quaternary background
|
236
|
-
- `--bg-disabled` / `bg-bg-disabled` - Disabled state background
|
237
|
-
- `--bg-overlay` / `bg-bg-overlay` - Overlay/modal background
|
59
|
+
These components can be used in Server Components without any issues:
|
238
60
|
|
239
|
-
|
240
|
-
-
|
241
|
-
-
|
242
|
-
- `--text-tertiary` / `text-text-tertiary` - Tertiary text
|
243
|
-
- `--text-disabled` / `text-text-disabled` - Disabled text
|
61
|
+
- **`ClientThemeProvider`** - Theme provider for Server Components
|
62
|
+
- **`ClientThemeToggle`** - Theme toggle for Server Components
|
63
|
+
- **`useThemeServer`** - Server-safe theme hook
|
244
64
|
|
245
|
-
|
246
|
-
- `--border-primary` / `border-border-primary` - Primary borders
|
247
|
-
- `--border-secondary` / `border-border-secondary` - Secondary borders
|
248
|
-
- `--border-tertiary` / `border-border-tertiary` - Tertiary borders
|
249
|
-
- `--border-disabled` / `border-border-disabled` - Disabled borders
|
65
|
+
### Client Component Only Components
|
250
66
|
|
251
|
-
|
252
|
-
- `--bg-brand-primary` / `bg-bg-brand-primary` - Brand background
|
253
|
-
- `--text-brand-primary` / `text-text-brand-primary` - Brand text
|
254
|
-
- `--border-brand` / `border-border-brand` - Brand borders
|
67
|
+
These components can only be used in Client Components:
|
255
68
|
|
256
|
-
|
257
|
-
-
|
258
|
-
- **Warning**: `--bg-warning-primary`, `--text-warning-primary`, `--border-warning`
|
259
|
-
- **Success**: `--bg-success-primary`, `--text-success-primary`, `--border-success`
|
69
|
+
- **`ThemeProvider`** - Standard theme provider (use `ClientThemeProvider` instead)
|
70
|
+
- **`ThemeProviderNoSSR`** - NoSSR theme provider (use `ClientThemeProvider` instead)
|
260
71
|
|
261
|
-
##
|
72
|
+
## Usage Examples
|
262
73
|
|
263
|
-
###
|
74
|
+
### Server Components
|
264
75
|
|
265
76
|
```tsx
|
266
|
-
import {
|
77
|
+
import { ClientThemeToggle, useThemeServer } from '@tydavidson/design-system/themes';
|
267
78
|
|
268
|
-
function
|
269
|
-
const { theme,
|
270
|
-
const isDark = isDarkTheme(theme, systemTheme);
|
79
|
+
export default function ServerComponent() {
|
80
|
+
const { theme, isDark } = useThemeServer();
|
271
81
|
|
272
82
|
return (
|
273
|
-
<div className={isDark ? 'dark
|
274
|
-
|
83
|
+
<div className={isDark ? 'dark' : 'light'}>
|
84
|
+
<h1>Current theme: {theme}</h1>
|
85
|
+
<ClientThemeToggle />
|
275
86
|
</div>
|
276
87
|
);
|
277
88
|
}
|
278
89
|
```
|
279
90
|
|
280
|
-
###
|
91
|
+
### Client Components
|
281
92
|
|
282
93
|
```tsx
|
283
|
-
|
284
|
-
|
285
|
-
mapVariantToShadcnVariant,
|
286
|
-
getColorVariantClasses
|
287
|
-
} from '@tydavidson/design-system';
|
288
|
-
|
289
|
-
// Map design system colors to shadcn variants
|
290
|
-
const variant = mapColorToShadcnVariant('brand'); // returns 'default'
|
291
|
-
const errorVariant = mapColorToShadcnVariant('error'); // returns 'destructive'
|
292
|
-
|
293
|
-
// Map design system variants to shadcn variants
|
294
|
-
const shadcnVariant = mapVariantToShadcnVariant('primary'); // returns 'default'
|
295
|
-
const outlineVariant = mapVariantToShadcnVariant('secondary'); // returns 'outline'
|
296
|
-
|
297
|
-
// Get Tailwind classes for color/variant combinations
|
298
|
-
const primaryClasses = getColorVariantClasses('brand', 'primary');
|
299
|
-
// returns: 'bg-brand-600 hover:bg-brand-700 text-white focus-visible:ring-brand-500'
|
300
|
-
|
301
|
-
const secondaryClasses = getColorVariantClasses('error', 'secondary');
|
302
|
-
// returns: 'border-error-300 text-error-700 hover:bg-error-50 focus-visible:ring-error-500'
|
303
|
-
```
|
304
|
-
|
305
|
-
### Dynamic Theme Switching
|
94
|
+
'use client';
|
95
|
+
import { ClientThemeToggle } from '@tydavidson/design-system/themes';
|
306
96
|
|
307
|
-
|
308
|
-
import { useTheme } from '@tydavidson/design-system';
|
309
|
-
|
310
|
-
function ThemeSwitcher() {
|
311
|
-
const { theme, setTheme, resolvedTheme } = useTheme();
|
312
|
-
|
313
|
-
const themes = [
|
314
|
-
{ value: 'light', label: 'Light', icon: '☀️' },
|
315
|
-
{ value: 'dark', label: 'Dark', icon: '🌙' },
|
316
|
-
{ value: 'system', label: 'System', icon: '💻' }
|
317
|
-
];
|
318
|
-
|
97
|
+
export default function ClientComponent() {
|
319
98
|
return (
|
320
|
-
<div
|
321
|
-
|
322
|
-
|
323
|
-
key={value}
|
324
|
-
onClick={() => setTheme(value)}
|
325
|
-
className={`px-3 py-2 rounded border transition-colors ${
|
326
|
-
theme === value
|
327
|
-
? 'bg-bg-brand-primary text-text-brand-primary border-border-brand'
|
328
|
-
: 'bg-bg-primary text-text-primary border-border-primary hover:bg-bg-secondary'
|
329
|
-
}`}
|
330
|
-
>
|
331
|
-
<span className="mr-2">{icon}</span>
|
332
|
-
{label}
|
333
|
-
</button>
|
334
|
-
))}
|
99
|
+
<div>
|
100
|
+
<h1>My Client Component</h1>
|
101
|
+
<ClientThemeToggle />
|
335
102
|
</div>
|
336
103
|
);
|
337
104
|
}
|
338
105
|
```
|
339
106
|
|
340
|
-
###
|
341
|
-
|
342
|
-
```tsx
|
343
|
-
import { useTheme } from '@tydavidson/design-system';
|
344
|
-
|
345
|
-
function ThemeAwareCard({ title, children, variant = 'default' }) {
|
346
|
-
const { isDark } = useTheme();
|
347
|
-
|
348
|
-
const variants = {
|
349
|
-
default: 'bg-bg-primary border-border-primary',
|
350
|
-
elevated: isDark ? 'bg-bg-secondary border-border-secondary shadow-lg' : 'bg-white border-border-primary shadow-md',
|
351
|
-
brand: 'bg-bg-brand-primary border-border-brand',
|
352
|
-
error: 'bg-bg-error-primary border-border-error',
|
353
|
-
success: 'bg-bg-success-primary border-border-success'
|
354
|
-
};
|
355
|
-
|
356
|
-
return (
|
357
|
-
<div className={`p-6 rounded-lg border ${variants[variant]}`}>
|
358
|
-
<h3 className="text-text-primary font-semibold mb-3">{title}</h3>
|
359
|
-
<div className="text-text-secondary">{children}</div>
|
360
|
-
</div>
|
361
|
-
);
|
362
|
-
}
|
363
|
-
|
364
|
-
// Usage
|
365
|
-
<ThemeAwareCard title="Default Card" variant="default">
|
366
|
-
This is a default card
|
367
|
-
</ThemeAwareCard>
|
368
|
-
|
369
|
-
<ThemeAwareCard title="Brand Card" variant="brand">
|
370
|
-
This is a brand-themed card
|
371
|
-
</ThemeAwareCard>
|
372
|
-
```
|
373
|
-
|
374
|
-
## Framework Integration
|
375
|
-
|
376
|
-
### Next.js App Router
|
107
|
+
### Layout Setup
|
377
108
|
|
378
109
|
```tsx
|
379
110
|
// app/layout.tsx
|
380
|
-
import {
|
381
|
-
|
382
|
-
|
383
|
-
export default function RootLayout({
|
384
|
-
children,
|
385
|
-
}: {
|
386
|
-
children: React.ReactNode
|
387
|
-
}) {
|
111
|
+
import { ClientThemeProvider } from '@tydavidson/design-system/themes';
|
112
|
+
|
113
|
+
export default function RootLayout({ children }) {
|
388
114
|
return (
|
389
115
|
<html lang="en" suppressHydrationWarning>
|
390
|
-
<body
|
391
|
-
<
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
116
|
+
<body>
|
117
|
+
<ClientThemeProvider
|
118
|
+
attribute="class"
|
119
|
+
defaultTheme="system"
|
120
|
+
enableSystem
|
121
|
+
disableTransitionOnChange
|
122
|
+
>
|
123
|
+
{children}
|
124
|
+
</ClientThemeProvider>
|
396
125
|
</body>
|
397
126
|
</html>
|
398
127
|
);
|
399
128
|
}
|
400
129
|
```
|
401
130
|
|
402
|
-
|
131
|
+
## Theme Configuration
|
403
132
|
|
404
|
-
|
405
|
-
// pages/_app.tsx
|
406
|
-
import { ThemeProvider, ThemeContextProvider } from '@tydavidson/design-system';
|
407
|
-
import '@tydavidson/design-system/themes/theme.css';
|
408
|
-
|
409
|
-
function MyApp({ Component, pageProps }) {
|
410
|
-
return (
|
411
|
-
<ThemeProvider>
|
412
|
-
<ThemeContextProvider>
|
413
|
-
<Component {...pageProps} />
|
414
|
-
</ThemeContextProvider>
|
415
|
-
</ThemeProvider>
|
416
|
-
);
|
417
|
-
}
|
418
|
-
|
419
|
-
export default MyApp;
|
420
|
-
```
|
421
|
-
|
422
|
-
### Create React App
|
133
|
+
### CSS Variables
|
423
134
|
|
424
|
-
|
425
|
-
// src/App.tsx
|
426
|
-
import { ThemeProvider, ThemeContextProvider } from '@tydavidson/design-system';
|
427
|
-
import '@tydavidson/design-system/themes/theme.css';
|
135
|
+
The theme system uses CSS custom properties for colors:
|
428
136
|
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
{/* Your app content */}
|
435
|
-
</div>
|
436
|
-
</ThemeContextProvider>
|
437
|
-
</ThemeProvider>
|
438
|
-
);
|
137
|
+
```css
|
138
|
+
:root {
|
139
|
+
--bg-primary: #ffffff;
|
140
|
+
--text-primary: #000000;
|
141
|
+
--accent-primary: #3b82f6;
|
439
142
|
}
|
440
143
|
|
441
|
-
|
144
|
+
.dark {
|
145
|
+
--bg-primary: #000000;
|
146
|
+
--text-primary: #ffffff;
|
147
|
+
--accent-primary: #60a5fa;
|
148
|
+
}
|
442
149
|
```
|
443
150
|
|
444
151
|
### Tailwind Configuration
|
445
152
|
|
446
|
-
|
153
|
+
Configure Tailwind to use the CSS variables:
|
447
154
|
|
448
155
|
```js
|
449
156
|
// tailwind.config.js
|
@@ -451,218 +158,160 @@ module.exports = {
|
|
451
158
|
darkMode: ["class"],
|
452
159
|
content: [
|
453
160
|
"./src/**/*.{js,ts,jsx,tsx}",
|
161
|
+
"./node_modules/@tydavidson/design-system/dist/**/*.{js,mjs}",
|
454
162
|
],
|
455
163
|
theme: {
|
456
164
|
extend: {
|
457
165
|
colors: {
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
quaternary: 'var(--bg-quaternary)',
|
464
|
-
disabled: 'var(--bg-disabled)',
|
465
|
-
overlay: 'var(--bg-overlay)',
|
466
|
-
'brand-primary': 'var(--bg-brand-primary)',
|
467
|
-
'error-primary': 'var(--bg-error-primary)',
|
468
|
-
'warning-primary': 'var(--bg-warning-primary)',
|
469
|
-
'success-primary': 'var(--bg-success-primary)',
|
470
|
-
},
|
471
|
-
// Text colors
|
472
|
-
text: {
|
473
|
-
primary: 'var(--text-primary)',
|
474
|
-
secondary: 'var(--text-secondary)',
|
475
|
-
tertiary: 'var(--text-tertiary)',
|
476
|
-
disabled: 'var(--text-disabled)',
|
477
|
-
'brand-primary': 'var(--text-brand-primary)',
|
478
|
-
'error-primary': 'var(--text-error-primary)',
|
479
|
-
'warning-primary': 'var(--text-warning-primary)',
|
480
|
-
'success-primary': 'var(--text-success-primary)',
|
166
|
+
background: "var(--bg-primary)",
|
167
|
+
foreground: "var(--text-primary)",
|
168
|
+
primary: {
|
169
|
+
DEFAULT: "var(--accent-primary)",
|
170
|
+
foreground: "var(--text-primary)",
|
481
171
|
},
|
482
|
-
|
483
|
-
|
484
|
-
primary: 'var(--border-primary)',
|
485
|
-
secondary: 'var(--border-secondary)',
|
486
|
-
tertiary: 'var(--border-tertiary)',
|
487
|
-
disabled: 'var(--border-disabled)',
|
488
|
-
brand: 'var(--border-brand)',
|
489
|
-
error: 'var(--border-error)',
|
490
|
-
warning: 'var(--border-warning)',
|
491
|
-
success: 'var(--border-success)',
|
492
|
-
}
|
493
|
-
}
|
494
|
-
}
|
172
|
+
},
|
173
|
+
},
|
495
174
|
},
|
496
|
-
|
497
|
-
}
|
175
|
+
};
|
498
176
|
```
|
499
177
|
|
500
|
-
##
|
501
|
-
|
502
|
-
### Hydration Mismatch
|
178
|
+
## Theme Utilities
|
503
179
|
|
504
|
-
|
505
|
-
|
506
|
-
**Solutions**:
|
507
|
-
1. Add `suppressHydrationWarning` to the HTML element
|
508
|
-
2. Check `isClient` before rendering theme-dependent content
|
509
|
-
3. Use the `useTheme` hook properly
|
180
|
+
### Server-Safe Theme Detection
|
510
181
|
|
511
182
|
```tsx
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
if (!isClient) return null;
|
183
|
+
import { useThemeServer } from '@tydavidson/design-system/themes';
|
184
|
+
|
185
|
+
export default function ServerComponent() {
|
186
|
+
const { theme, isDark } = useThemeServer();
|
517
187
|
|
518
188
|
return (
|
519
|
-
<div className={isDark ? 'dark-
|
520
|
-
|
189
|
+
<div className={isDark ? 'dark-theme' : 'light-theme'}>
|
190
|
+
Current theme: {theme}
|
521
191
|
</div>
|
522
192
|
);
|
523
193
|
}
|
524
194
|
```
|
525
195
|
|
526
|
-
### Theme
|
196
|
+
### Theme Utilities
|
527
197
|
|
528
|
-
|
198
|
+
```tsx
|
199
|
+
import {
|
200
|
+
isDarkTheme,
|
201
|
+
mapColorToShadcnVariant,
|
202
|
+
mapVariantToShadcnVariant,
|
203
|
+
getColorVariantClasses
|
204
|
+
} from '@tydavidson/design-system/themes';
|
529
205
|
|
530
|
-
|
531
|
-
|
532
|
-
2. Check theme providers are wrapping your app
|
533
|
-
3. Ensure `next-themes` is properly configured
|
534
|
-
4. Confirm Tailwind config includes theme variables
|
206
|
+
// Check if theme is dark
|
207
|
+
const isDark = isDarkTheme('dark', 'dark');
|
535
208
|
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
<div className="text-sm text-text-secondary space-y-1">
|
545
|
-
<p>Client: {isClient ? 'Yes' : 'No'}</p>
|
546
|
-
<p>Theme: {theme}</p>
|
547
|
-
<p>Resolved: {resolvedTheme}</p>
|
548
|
-
<p>Is Dark: {isDark ? 'Yes' : 'No'}</p>
|
549
|
-
</div>
|
550
|
-
</div>
|
551
|
-
);
|
552
|
-
}
|
209
|
+
// Map design system colors to shadcn variants
|
210
|
+
const variant = mapColorToShadcnVariant('brand'); // 'default'
|
211
|
+
|
212
|
+
// Map design system variants to shadcn variants
|
213
|
+
const shadcnVariant = mapVariantToShadcnVariant('primary'); // 'default'
|
214
|
+
|
215
|
+
// Get Tailwind classes for color/variant combinations
|
216
|
+
const classes = getColorVariantClasses('brand', 'primary');
|
553
217
|
```
|
554
218
|
|
555
|
-
|
219
|
+
## Migration Guide
|
556
220
|
|
557
|
-
|
221
|
+
### From Previous Versions
|
558
222
|
|
559
|
-
|
560
|
-
1. Verify CSS variables are imported
|
561
|
-
2. Check Tailwind configuration includes theme colors
|
562
|
-
3. Ensure correct class names are used
|
563
|
-
4. Confirm theme providers are in correct order
|
223
|
+
If you were using the old theme system:
|
564
224
|
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
225
|
+
**Before:**
|
226
|
+
```tsx
|
227
|
+
import { ThemeToggle, useTheme } from '@tydavidson/design-system/themes';
|
228
|
+
|
229
|
+
export default function MyComponent() {
|
230
|
+
const { theme, setTheme } = useTheme();
|
231
|
+
return <ThemeToggle />;
|
232
|
+
}
|
233
|
+
```
|
234
|
+
|
235
|
+
**After:**
|
236
|
+
```tsx
|
237
|
+
import { ClientThemeToggle, useThemeServer } from '@tydavidson/design-system/themes';
|
238
|
+
|
239
|
+
export default function MyComponent() {
|
240
|
+
const { theme } = useThemeServer();
|
241
|
+
return <ClientThemeToggle />;
|
571
242
|
}
|
572
243
|
```
|
573
244
|
|
574
|
-
###
|
245
|
+
### Key Changes
|
246
|
+
|
247
|
+
1. **`ThemeToggle`** → **`ClientThemeToggle`** (Server Component safe)
|
248
|
+
2. **`useTheme`** → **`useThemeServer`** (Server Component safe)
|
249
|
+
3. **`ThemeProvider`** → **`ClientThemeProvider`** (Server Component safe)
|
250
|
+
|
251
|
+
## Troubleshooting
|
252
|
+
|
253
|
+
### Common Issues
|
254
|
+
|
255
|
+
1. **Theme not switching**: Ensure `ClientThemeProvider` is wrapping your app
|
256
|
+
2. **Hydration errors**: Add `suppressHydrationWarning` to your `<html>` element
|
257
|
+
3. **CSS not loading**: Import the theme CSS file
|
258
|
+
4. **TypeScript errors**: The package includes types, no additional @types needed
|
259
|
+
|
260
|
+
### Server Component Compatibility
|
575
261
|
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
262
|
+
All exported components are now Server Component safe. If you encounter any issues:
|
263
|
+
|
264
|
+
1. Use `ClientThemeToggle` instead of `ThemeToggle`
|
265
|
+
2. Use `ClientThemeProvider` instead of `ThemeProvider`
|
266
|
+
3. Use `useThemeServer` instead of `useTheme`
|
267
|
+
|
268
|
+
## API Reference
|
269
|
+
|
270
|
+
### ClientThemeProvider
|
271
|
+
|
272
|
+
Theme provider component for Server Component compatibility.
|
581
273
|
|
582
274
|
```tsx
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
Content
|
594
|
-
</div>
|
275
|
+
import { ClientThemeProvider } from '@tydavidson/design-system/themes';
|
276
|
+
|
277
|
+
<ClientThemeProvider
|
278
|
+
attribute="class"
|
279
|
+
defaultTheme="system"
|
280
|
+
enableSystem
|
281
|
+
disableTransitionOnChange
|
282
|
+
>
|
283
|
+
{children}
|
284
|
+
</ClientThemeProvider>
|
595
285
|
```
|
596
286
|
|
597
|
-
|
287
|
+
### ClientThemeToggle
|
598
288
|
|
599
|
-
|
289
|
+
Theme toggle component for Server Component compatibility.
|
600
290
|
|
601
291
|
```tsx
|
602
|
-
import {
|
603
|
-
import '@tydavidson/design-system/themes/theme.css';
|
292
|
+
import { ClientThemeToggle } from '@tydavidson/design-system/themes';
|
604
293
|
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
<Main />
|
612
|
-
<Footer />
|
613
|
-
</div>
|
614
|
-
</ThemeContextProvider>
|
615
|
-
</ThemeProvider>
|
616
|
-
);
|
617
|
-
}
|
294
|
+
<ClientThemeToggle
|
295
|
+
variant="icon"
|
296
|
+
size="md"
|
297
|
+
className="custom-class"
|
298
|
+
/>
|
299
|
+
```
|
618
300
|
|
619
|
-
|
620
|
-
return (
|
621
|
-
<header className="bg-bg-secondary border-b border-border-primary p-4">
|
622
|
-
<div className="max-w-6xl mx-auto flex items-center justify-between">
|
623
|
-
<h1 className="text-xl font-bold text-text-primary">My App</h1>
|
624
|
-
<ThemeToggle variant="icon" size="md" />
|
625
|
-
</div>
|
626
|
-
</header>
|
627
|
-
);
|
628
|
-
}
|
301
|
+
### useThemeServer
|
629
302
|
|
630
|
-
|
631
|
-
return (
|
632
|
-
<main className="max-w-6xl mx-auto p-6">
|
633
|
-
<div className="grid gap-6">
|
634
|
-
<section className="bg-bg-secondary border border-border-primary rounded-lg p-6">
|
635
|
-
<h2 className="text-lg font-semibold text-text-primary mb-4">Welcome</h2>
|
636
|
-
<p className="text-text-secondary">
|
637
|
-
This app uses the Float Design System theme system.
|
638
|
-
</p>
|
639
|
-
</section>
|
640
|
-
|
641
|
-
<section className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
642
|
-
<div className="bg-bg-success-primary text-text-success-primary border border-border-success rounded-lg p-4">
|
643
|
-
Success Card
|
644
|
-
</div>
|
645
|
-
<div className="bg-bg-error-primary text-text-error-primary border border-border-error rounded-lg p-4">
|
646
|
-
Error Card
|
647
|
-
</div>
|
648
|
-
<div className="bg-bg-warning-primary text-text-warning-primary border border-border-warning rounded-lg p-4">
|
649
|
-
Warning Card
|
650
|
-
</div>
|
651
|
-
</section>
|
652
|
-
</div>
|
653
|
-
</main>
|
654
|
-
);
|
655
|
-
}
|
303
|
+
Server-safe theme hook that returns default theme values.
|
656
304
|
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
© 2024 My App. Built with Float Design System.
|
662
|
-
</div>
|
663
|
-
</footer>
|
664
|
-
);
|
665
|
-
}
|
305
|
+
```tsx
|
306
|
+
import { useThemeServer } from '@tydavidson/design-system/themes';
|
307
|
+
|
308
|
+
const { theme, setTheme, resolvedTheme, isDark } = useThemeServer();
|
666
309
|
```
|
667
310
|
|
668
|
-
|
311
|
+
## Version Compatibility
|
312
|
+
|
313
|
+
| Next.js Version | Design System Version | Notes |
|
314
|
+
|----------------|----------------------|-------|
|
315
|
+
| 13+ (App Router) | 1.1.17+ | Full Server Component support |
|
316
|
+
| 12+ (Pages Router) | 1.1.0+ | Basic compatibility |
|
317
|
+
| < 12 | Not supported | Use newer Next.js version |
|