@tydavidson/design-system 1.1.5 → 1.1.7
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 +59 -1
- package/docs/component-colors.ts +94 -0
- package/docs/component-specific-colors.md +253 -0
- package/docs/setup-guide.md +276 -0
- package/docs/theme-usage.md +668 -0
- package/docs/troubleshooting.md +130 -0
- package/package.json +5 -5
@@ -0,0 +1,668 @@
|
|
1
|
+
# Float Design System - Theme System Guide
|
2
|
+
|
3
|
+
A comprehensive guide for implementing and using the Float Design System's theme system in your React applications.
|
4
|
+
|
5
|
+
## Table of Contents
|
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)
|
14
|
+
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
```bash
|
18
|
+
npm install @tydavidson/design-system
|
19
|
+
```
|
20
|
+
|
21
|
+
## Quick Start
|
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:
|
41
|
+
|
42
|
+
```tsx
|
43
|
+
import { ThemeProvider, ThemeContextProvider } from '@tydavidson/design-system';
|
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
|
+
}
|
57
|
+
```
|
58
|
+
|
59
|
+
### 3. Add Theme Toggle
|
60
|
+
|
61
|
+
Add the theme toggle component to your app:
|
62
|
+
|
63
|
+
```tsx
|
64
|
+
import { ThemeToggle } from '@tydavidson/design-system';
|
65
|
+
|
66
|
+
function Header() {
|
67
|
+
return (
|
68
|
+
<header className="bg-bg-primary border-b border-border-primary p-4">
|
69
|
+
<div className="flex items-center justify-between">
|
70
|
+
<h1 className="text-text-primary text-xl font-bold">My App</h1>
|
71
|
+
<ThemeToggle variant="icon" size="md" />
|
72
|
+
</div>
|
73
|
+
</header>
|
74
|
+
);
|
75
|
+
}
|
76
|
+
```
|
77
|
+
|
78
|
+
## Core Components
|
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:**
|
103
|
+
|
104
|
+
```tsx
|
105
|
+
// In a header
|
106
|
+
<div className="flex items-center gap-4">
|
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
|
118
|
+
|
119
|
+
Access theme state and functions in your components:
|
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
|
+
|
133
|
+
return (
|
134
|
+
<div className="p-4 bg-bg-secondary border border-border-primary rounded-lg">
|
135
|
+
<h3 className="text-text-primary font-semibold mb-2">Theme Information</h3>
|
136
|
+
<div className="space-y-1 text-sm text-text-secondary">
|
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>
|
162
|
+
</div>
|
163
|
+
);
|
164
|
+
}
|
165
|
+
```
|
166
|
+
|
167
|
+
## Theme Variables
|
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
|
196
|
+
|
197
|
+
Use semantic color classes with Tailwind CSS:
|
198
|
+
|
199
|
+
```tsx
|
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
|
238
|
+
|
239
|
+
#### Text Colors
|
240
|
+
- `--text-primary` / `text-text-primary` - Primary text
|
241
|
+
- `--text-secondary` / `text-text-secondary` - Secondary text
|
242
|
+
- `--text-tertiary` / `text-text-tertiary` - Tertiary text
|
243
|
+
- `--text-disabled` / `text-text-disabled` - Disabled text
|
244
|
+
|
245
|
+
#### Border Colors
|
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
|
250
|
+
|
251
|
+
#### Brand Colors
|
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
|
255
|
+
|
256
|
+
#### Semantic Colors
|
257
|
+
- **Error**: `--bg-error-primary`, `--text-error-primary`, `--border-error`
|
258
|
+
- **Warning**: `--bg-warning-primary`, `--text-warning-primary`, `--border-warning`
|
259
|
+
- **Success**: `--bg-success-primary`, `--text-success-primary`, `--border-success`
|
260
|
+
|
261
|
+
## Advanced Usage
|
262
|
+
|
263
|
+
### Custom Theme Detection
|
264
|
+
|
265
|
+
```tsx
|
266
|
+
import { isDarkTheme } from '@tydavidson/design-system';
|
267
|
+
|
268
|
+
function ConditionalComponent() {
|
269
|
+
const { theme, systemTheme } = useTheme();
|
270
|
+
const isDark = isDarkTheme(theme, systemTheme);
|
271
|
+
|
272
|
+
return (
|
273
|
+
<div className={isDark ? 'dark-mode-styles' : 'light-mode-styles'}>
|
274
|
+
{isDark ? 'Dark mode content' : 'Light mode content'}
|
275
|
+
</div>
|
276
|
+
);
|
277
|
+
}
|
278
|
+
```
|
279
|
+
|
280
|
+
### Color Mapping Utilities
|
281
|
+
|
282
|
+
```tsx
|
283
|
+
import {
|
284
|
+
mapColorToShadcnVariant,
|
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
|
306
|
+
|
307
|
+
```tsx
|
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
|
+
|
319
|
+
return (
|
320
|
+
<div className="flex gap-2">
|
321
|
+
{themes.map(({ value, label, icon }) => (
|
322
|
+
<button
|
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
|
+
))}
|
335
|
+
</div>
|
336
|
+
);
|
337
|
+
}
|
338
|
+
```
|
339
|
+
|
340
|
+
### Theme-Aware Components
|
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
|
377
|
+
|
378
|
+
```tsx
|
379
|
+
// app/layout.tsx
|
380
|
+
import { ThemeProvider, ThemeContextProvider } from '@tydavidson/design-system';
|
381
|
+
import '@tydavidson/design-system/themes/theme.css';
|
382
|
+
|
383
|
+
export default function RootLayout({
|
384
|
+
children,
|
385
|
+
}: {
|
386
|
+
children: React.ReactNode
|
387
|
+
}) {
|
388
|
+
return (
|
389
|
+
<html lang="en" suppressHydrationWarning>
|
390
|
+
<body className="bg-bg-primary text-text-primary">
|
391
|
+
<ThemeProvider>
|
392
|
+
<ThemeContextProvider>
|
393
|
+
{children}
|
394
|
+
</ThemeContextProvider>
|
395
|
+
</ThemeProvider>
|
396
|
+
</body>
|
397
|
+
</html>
|
398
|
+
);
|
399
|
+
}
|
400
|
+
```
|
401
|
+
|
402
|
+
### Next.js Pages Router
|
403
|
+
|
404
|
+
```tsx
|
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
|
423
|
+
|
424
|
+
```tsx
|
425
|
+
// src/App.tsx
|
426
|
+
import { ThemeProvider, ThemeContextProvider } from '@tydavidson/design-system';
|
427
|
+
import '@tydavidson/design-system/themes/theme.css';
|
428
|
+
|
429
|
+
function App() {
|
430
|
+
return (
|
431
|
+
<ThemeProvider>
|
432
|
+
<ThemeContextProvider>
|
433
|
+
<div className="bg-bg-primary text-text-primary min-h-screen">
|
434
|
+
{/* Your app content */}
|
435
|
+
</div>
|
436
|
+
</ThemeContextProvider>
|
437
|
+
</ThemeProvider>
|
438
|
+
);
|
439
|
+
}
|
440
|
+
|
441
|
+
export default App;
|
442
|
+
```
|
443
|
+
|
444
|
+
### Tailwind Configuration
|
445
|
+
|
446
|
+
Extend your Tailwind config to use theme variables:
|
447
|
+
|
448
|
+
```js
|
449
|
+
// tailwind.config.js
|
450
|
+
module.exports = {
|
451
|
+
darkMode: ["class"],
|
452
|
+
content: [
|
453
|
+
"./src/**/*.{js,ts,jsx,tsx}",
|
454
|
+
],
|
455
|
+
theme: {
|
456
|
+
extend: {
|
457
|
+
colors: {
|
458
|
+
// Background colors
|
459
|
+
bg: {
|
460
|
+
primary: 'var(--bg-primary)',
|
461
|
+
secondary: 'var(--bg-secondary)',
|
462
|
+
tertiary: 'var(--bg-tertiary)',
|
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)',
|
481
|
+
},
|
482
|
+
// Border colors
|
483
|
+
border: {
|
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
|
+
}
|
495
|
+
},
|
496
|
+
plugins: [],
|
497
|
+
}
|
498
|
+
```
|
499
|
+
|
500
|
+
## Troubleshooting
|
501
|
+
|
502
|
+
### Hydration Mismatch
|
503
|
+
|
504
|
+
**Problem**: Server-side rendering doesn't match client-side rendering.
|
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
|
510
|
+
|
511
|
+
```tsx
|
512
|
+
function ThemeDependentComponent() {
|
513
|
+
const { isClient, isDark } = useTheme();
|
514
|
+
|
515
|
+
// Don't render until client-side
|
516
|
+
if (!isClient) return null;
|
517
|
+
|
518
|
+
return (
|
519
|
+
<div className={isDark ? 'dark-styles' : 'light-styles'}>
|
520
|
+
Theme-dependent content
|
521
|
+
</div>
|
522
|
+
);
|
523
|
+
}
|
524
|
+
```
|
525
|
+
|
526
|
+
### Theme Not Switching
|
527
|
+
|
528
|
+
**Problem**: Theme toggle doesn't change the appearance.
|
529
|
+
|
530
|
+
**Solutions**:
|
531
|
+
1. Verify theme CSS is imported
|
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
|
535
|
+
|
536
|
+
```tsx
|
537
|
+
// Debug theme state
|
538
|
+
function ThemeDebugger() {
|
539
|
+
const { theme, setTheme, resolvedTheme, isDark, isClient } = useTheme();
|
540
|
+
|
541
|
+
return (
|
542
|
+
<div className="p-4 bg-bg-secondary border border-border-primary rounded">
|
543
|
+
<h3 className="text-text-primary font-semibold mb-2">Theme Debug</h3>
|
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
|
+
}
|
553
|
+
```
|
554
|
+
|
555
|
+
### Styling Issues
|
556
|
+
|
557
|
+
**Problem**: Theme styles aren't applying correctly.
|
558
|
+
|
559
|
+
**Solutions**:
|
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
|
564
|
+
|
565
|
+
```css
|
566
|
+
/* Test CSS variables are working */
|
567
|
+
.theme-test {
|
568
|
+
background-color: var(--bg-primary);
|
569
|
+
color: var(--text-primary);
|
570
|
+
border: 1px solid var(--border-primary);
|
571
|
+
}
|
572
|
+
```
|
573
|
+
|
574
|
+
### Performance Optimization
|
575
|
+
|
576
|
+
**Best Practices**:
|
577
|
+
1. Use CSS variables for dynamic theming
|
578
|
+
2. Avoid inline styles for theme-dependent styles
|
579
|
+
3. Use Tailwind classes when possible
|
580
|
+
4. Minimize theme-dependent JavaScript
|
581
|
+
|
582
|
+
```tsx
|
583
|
+
// Good: Use CSS variables and Tailwind
|
584
|
+
<div className="bg-bg-primary text-text-primary border border-border-primary">
|
585
|
+
Content
|
586
|
+
</div>
|
587
|
+
|
588
|
+
// Avoid: Inline styles for theme
|
589
|
+
<div style={{
|
590
|
+
backgroundColor: isDark ? '#000' : '#fff',
|
591
|
+
color: isDark ? '#fff' : '#000'
|
592
|
+
}}>
|
593
|
+
Content
|
594
|
+
</div>
|
595
|
+
```
|
596
|
+
|
597
|
+
## Examples
|
598
|
+
|
599
|
+
### Complete App Example
|
600
|
+
|
601
|
+
```tsx
|
602
|
+
import { ThemeProvider, ThemeContextProvider, ThemeToggle } from '@tydavidson/design-system';
|
603
|
+
import '@tydavidson/design-system/themes/theme.css';
|
604
|
+
|
605
|
+
function App() {
|
606
|
+
return (
|
607
|
+
<ThemeProvider>
|
608
|
+
<ThemeContextProvider>
|
609
|
+
<div className="min-h-screen bg-bg-primary text-text-primary">
|
610
|
+
<Header />
|
611
|
+
<Main />
|
612
|
+
<Footer />
|
613
|
+
</div>
|
614
|
+
</ThemeContextProvider>
|
615
|
+
</ThemeProvider>
|
616
|
+
);
|
617
|
+
}
|
618
|
+
|
619
|
+
function Header() {
|
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
|
+
}
|
629
|
+
|
630
|
+
function Main() {
|
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
|
+
}
|
656
|
+
|
657
|
+
function Footer() {
|
658
|
+
return (
|
659
|
+
<footer className="bg-bg-secondary border-t border-border-primary p-4 mt-auto">
|
660
|
+
<div className="max-w-6xl mx-auto text-center text-text-secondary">
|
661
|
+
© 2024 My App. Built with Float Design System.
|
662
|
+
</div>
|
663
|
+
</footer>
|
664
|
+
);
|
665
|
+
}
|
666
|
+
```
|
667
|
+
|
668
|
+
This comprehensive guide should help you implement and use the Float Design System theme system effectively in your projects!
|