@soybeanjs/shadcn-theme 0.0.11 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en_US.md +329 -94
- package/README.md +375 -93
- package/dist/index.d.ts +111 -77
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.en_US.md
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
# @soybeanjs/shadcn-theme
|
|
2
2
|
|
|
3
|
-
A powerful and flexible shadcn/ui theme generator with
|
|
3
|
+
A powerful and flexible shadcn/ui theme CSS variables generator with preset color schemes, light/dark output, and optional custom preset extension.
|
|
4
4
|
|
|
5
5
|
[中文 README](README.md)
|
|
6
6
|
|
|
7
7
|
## ✨ Features
|
|
8
8
|
|
|
9
|
-
- 🎨 **Rich Preset Themes** -
|
|
10
|
-
- 🌗 **Light/Dark
|
|
11
|
-
- 🎯 **Flexible Color
|
|
12
|
-
- 🔧 **
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
- 🌈 **Color Palette Generation** - Automatically generates gradient palettes (50-950) for primary colors
|
|
9
|
+
- 🎨 **Rich Preset Themes** - Built-in base / primary / feedback preset combinations
|
|
10
|
+
- 🌗 **Light/Dark Output** - Supports `.dark` / `@media (prefers-color-scheme: dark)` / custom selector
|
|
11
|
+
- 🎯 **Flexible Color Formats** - Supports `hsl` and `oklch` output
|
|
12
|
+
- 🔧 **Extensible** - Add custom colors via `preset` (including sidebar / chart fields)
|
|
13
|
+
- 🌈 **Palette Variables** - Generates 50-950 palette vars for primary/destructive/success/warning/info/carbon
|
|
14
|
+
- 📦 **Lightweight Dependency** - Only depends on `@soybeanjs/colord`
|
|
15
|
+
- 🧩 **Pure Generator** - Returns CSS strings only; does not automatically mutate the DOM
|
|
17
16
|
|
|
18
17
|
## 📦 Installation
|
|
19
18
|
|
|
@@ -28,39 +27,225 @@ pnpm add @soybeanjs/shadcn-theme
|
|
|
28
27
|
```typescript
|
|
29
28
|
import { createShadcnTheme } from '@soybeanjs/shadcn-theme';
|
|
30
29
|
|
|
31
|
-
// Use default presets (
|
|
32
|
-
createShadcnTheme();
|
|
30
|
+
// Use default presets (gray + indigo + classic + extended)
|
|
31
|
+
const theme = createShadcnTheme();
|
|
32
|
+
const css = theme.getCss();
|
|
33
33
|
|
|
34
34
|
// Custom preset combination
|
|
35
|
-
createShadcnTheme({
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
35
|
+
const custom = createShadcnTheme({
|
|
36
|
+
base: 'zinc',
|
|
37
|
+
primary: 'blue',
|
|
38
|
+
feedback: 'vivid',
|
|
39
|
+
sidebar: 'extended',
|
|
40
|
+
radius: '0.5rem',
|
|
41
|
+
darkSelector: 'class',
|
|
42
|
+
format: 'hsl'
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const customCss = custom.getCss();
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### (Optional) Inject into the DOM
|
|
49
|
+
|
|
50
|
+
This library generates CSS strings. If you want runtime theme switching, you can inject the result yourself:
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
import { createShadcnTheme } from '@soybeanjs/shadcn-theme';
|
|
54
|
+
|
|
55
|
+
const theme = createShadcnTheme({ primary: 'indigo' });
|
|
56
|
+
|
|
57
|
+
function applyTheme(cssText: string, styleId = 'SHADCN_THEME_STYLE') {
|
|
58
|
+
const el = document.getElementById(styleId) ?? document.createElement('style');
|
|
59
|
+
el.id = styleId;
|
|
60
|
+
el.textContent = cssText;
|
|
61
|
+
document.head.appendChild(el);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
applyTheme(theme.getCss());
|
|
65
|
+
applyTheme(theme.getCss({ primary: 'emerald' }));
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Custom Preset
|
|
69
|
+
|
|
70
|
+
`preset` lets you add or override named preset entries on top of the built-in presets. You can extend only one group (e.g. add a custom `primary` preset), or extend `base / primary / feedback / sidebar` together.
|
|
71
|
+
|
|
72
|
+
#### 1) Structure and how to reference a preset
|
|
73
|
+
|
|
74
|
+
- `preset` is an object that may contain `base / primary / feedback / sidebar`. Each group is `{ [key: string]: PresetItem }`.
|
|
75
|
+
- To use your custom preset, set the corresponding `base` / `primary` / `feedback` / `sidebar` option to the key you defined.
|
|
76
|
+
- Example: if you define `preset.primary.brandPrimary`, then pass `primary: 'brandPrimary'`.
|
|
77
|
+
|
|
78
|
+
#### 2) Merge/override rules
|
|
79
|
+
|
|
80
|
+
The library shallow-merges your `preset` into the built-ins:
|
|
81
|
+
|
|
82
|
+
- Same key is overridden by your `preset` (e.g. defining `primary.indigo` overrides built-in `indigo`).
|
|
83
|
+
- New keys are added as extra presets (e.g. `primary.brandPrimary`).
|
|
84
|
+
|
|
85
|
+
#### 3) Two sidebar modes
|
|
86
|
+
|
|
87
|
+
- `sidebar: 'extended'` (default): ignores `preset.sidebar` and derives sidebar colors from base/primary.
|
|
88
|
+
- `sidebar: '<yourKey>'`: uses `preset.sidebar[<yourKey>]` as the sidebar colors.
|
|
89
|
+
|
|
90
|
+
#### 4) Color values and `format`
|
|
91
|
+
|
|
92
|
+
- Each color value supports: Tailwind palette reference (e.g. `slate.500`), `hsl(...)`, or `oklch(...)`.
|
|
93
|
+
- `format: 'hsl'`: outputs `h s l [/ alpha]` (no outer `hsl(...)`); `oklch(...)` inputs are converted to HSL.
|
|
94
|
+
- `format: 'oklch'`: outputs values with the outer `oklch(...)`; `hsl(...)` inputs are converted to OKLCH.
|
|
95
|
+
|
|
96
|
+
#### Quick example: add a custom primary preset (good starting point)
|
|
97
|
+
|
|
98
|
+
`primary` presets only need `primary / ring / chart1~chart5`:
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
const theme = createShadcnTheme({
|
|
102
|
+
primary: 'brandPrimary',
|
|
103
|
+
preset: {
|
|
104
|
+
primary: {
|
|
105
|
+
brandPrimary: {
|
|
106
|
+
light: {
|
|
107
|
+
primary: 'blue.600',
|
|
108
|
+
ring: 'blue.400',
|
|
109
|
+
chart1: 'orange.600',
|
|
110
|
+
chart2: 'teal.600',
|
|
111
|
+
chart3: 'cyan.900',
|
|
112
|
+
chart4: 'amber.400',
|
|
113
|
+
chart5: 'amber.500'
|
|
114
|
+
},
|
|
115
|
+
dark: {
|
|
116
|
+
primary: 'blue.400',
|
|
117
|
+
ring: 'blue.500',
|
|
118
|
+
chart1: 'orange.500',
|
|
119
|
+
chart2: 'teal.500',
|
|
120
|
+
chart3: 'cyan.400',
|
|
121
|
+
chart4: 'amber.500',
|
|
122
|
+
chart5: 'amber.600'
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
const css = theme.getCss();
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
#### Quick example: add a custom feedback preset
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
const theme = createShadcnTheme({
|
|
136
|
+
feedback: 'brandFeedback',
|
|
137
|
+
preset: {
|
|
138
|
+
feedback: {
|
|
139
|
+
brandFeedback: {
|
|
140
|
+
light: {
|
|
141
|
+
destructive: 'red.500',
|
|
142
|
+
success: 'emerald.500',
|
|
143
|
+
warning: 'amber.500',
|
|
144
|
+
info: 'sky.500'
|
|
145
|
+
},
|
|
146
|
+
dark: {
|
|
147
|
+
destructive: 'red.400',
|
|
148
|
+
success: 'emerald.400',
|
|
149
|
+
warning: 'amber.400',
|
|
150
|
+
info: 'sky.400'
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
#### Quick example: custom sidebar (non-extended)
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
const theme = createShadcnTheme({
|
|
162
|
+
sidebar: 'brandSidebar',
|
|
163
|
+
preset: {
|
|
164
|
+
sidebar: {
|
|
165
|
+
brandSidebar: {
|
|
166
|
+
light: {
|
|
167
|
+
sidebar: 'slate.50',
|
|
168
|
+
sidebarForeground: 'slate.900',
|
|
169
|
+
sidebarPrimary: 'blue.600',
|
|
170
|
+
sidebarPrimaryForeground: 'slate.50',
|
|
171
|
+
sidebarAccent: 'slate.100',
|
|
172
|
+
sidebarAccentForeground: 'slate.900',
|
|
173
|
+
sidebarBorder: 'slate.200',
|
|
174
|
+
sidebarRing: 'blue.400'
|
|
175
|
+
},
|
|
176
|
+
dark: {
|
|
177
|
+
sidebar: 'slate.950',
|
|
178
|
+
sidebarForeground: 'slate.50',
|
|
179
|
+
sidebarPrimary: 'blue.400',
|
|
180
|
+
sidebarPrimaryForeground: 'slate.950',
|
|
181
|
+
sidebarAccent: 'slate.900',
|
|
182
|
+
sidebarAccentForeground: 'slate.50',
|
|
183
|
+
sidebarBorder: 'slate.800',
|
|
184
|
+
sidebarRing: 'blue.500'
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
44
189
|
});
|
|
45
190
|
```
|
|
46
191
|
|
|
47
|
-
|
|
192
|
+
#### Full example (custom base + primary + feedback)
|
|
48
193
|
|
|
49
194
|
```typescript
|
|
50
195
|
createShadcnTheme({
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
196
|
+
base: 'demoBase',
|
|
197
|
+
primary: 'demoPrimary',
|
|
198
|
+
feedback: 'demoFeedback',
|
|
199
|
+
preset: {
|
|
200
|
+
base: {
|
|
201
|
+
demoBase: {
|
|
202
|
+
light: {
|
|
203
|
+
background: 'oklch(100% 0 0)',
|
|
204
|
+
foreground: 'stone.950',
|
|
205
|
+
card: 'oklch(100% 0 0)',
|
|
206
|
+
cardForeground: 'stone.950',
|
|
207
|
+
popover: 'oklch(100% 0 0)',
|
|
208
|
+
popoverForeground: 'stone.950',
|
|
209
|
+
primaryForeground: 'stone.50',
|
|
210
|
+
secondary: 'stone.100',
|
|
211
|
+
secondaryForeground: 'stone.900',
|
|
212
|
+
muted: 'stone.100',
|
|
213
|
+
mutedForeground: 'stone.500',
|
|
214
|
+
accent: 'stone.100',
|
|
215
|
+
accentForeground: 'stone.900',
|
|
216
|
+
destructiveForeground: 'stone.50',
|
|
217
|
+
successForeground: 'stone.50',
|
|
218
|
+
warningForeground: 'stone.50',
|
|
219
|
+
infoForeground: 'stone.50',
|
|
220
|
+
carbon: 'stone.800',
|
|
221
|
+
carbonForeground: 'stone.50',
|
|
222
|
+
border: 'stone.200',
|
|
223
|
+
input: 'stone.200'
|
|
224
|
+
},
|
|
225
|
+
dark: {
|
|
226
|
+
background: 'stone.950',
|
|
227
|
+
foreground: 'stone.50',
|
|
228
|
+
card: 'stone.900',
|
|
229
|
+
cardForeground: 'stone.50',
|
|
230
|
+
popover: 'stone.900',
|
|
231
|
+
popoverForeground: 'stone.50',
|
|
232
|
+
primaryForeground: 'stone.900',
|
|
233
|
+
secondary: 'stone.800',
|
|
234
|
+
secondaryForeground: 'stone.50',
|
|
235
|
+
muted: 'stone.800',
|
|
236
|
+
mutedForeground: 'stone.400',
|
|
237
|
+
accent: 'stone.800',
|
|
238
|
+
accentForeground: 'stone.50',
|
|
239
|
+
destructiveForeground: 'stone.900',
|
|
240
|
+
successForeground: 'stone.900',
|
|
241
|
+
warningForeground: 'stone.900',
|
|
242
|
+
infoForeground: 'stone.900',
|
|
243
|
+
carbon: 'stone.100',
|
|
244
|
+
carbonForeground: 'stone.900',
|
|
245
|
+
border: 'oklch(100% 0 0 / 0.1)',
|
|
246
|
+
input: 'oklch(100% 0 0 / 0.15)'
|
|
247
|
+
}
|
|
248
|
+
}
|
|
64
249
|
}
|
|
65
250
|
}
|
|
66
251
|
});
|
|
@@ -70,27 +255,40 @@ createShadcnTheme({
|
|
|
70
255
|
|
|
71
256
|
### `createShadcnTheme(options?: ThemeOptions)`
|
|
72
257
|
|
|
73
|
-
Main function to create
|
|
258
|
+
Main function to create a theme CSS generator.
|
|
259
|
+
|
|
260
|
+
Return value:
|
|
261
|
+
|
|
262
|
+
```ts
|
|
263
|
+
const theme = createShadcnTheme();
|
|
264
|
+
|
|
265
|
+
theme.getCss(config?: PresetConfig, radius?: string): string
|
|
266
|
+
theme.getColorCss(config: PresetConfig): string
|
|
267
|
+
theme.getRadiusCss(radius?: string): string
|
|
268
|
+
```
|
|
74
269
|
|
|
75
270
|
#### ThemeOptions
|
|
76
271
|
|
|
77
272
|
| Parameter | Type | Default | Description |
|
|
78
273
|
|------|------|--------|------|
|
|
79
|
-
| `
|
|
80
|
-
| `
|
|
81
|
-
| `
|
|
82
|
-
| `
|
|
83
|
-
| `
|
|
84
|
-
| `
|
|
85
|
-
| `
|
|
274
|
+
| `base` | `BuiltinBasePresetKey \| string` | `'gray'` | Base preset key |
|
|
275
|
+
| `primary` | `BuiltinPrimaryPresetKey \| string` | `'indigo'` | Primary preset key |
|
|
276
|
+
| `feedback` | `BuiltinFeedbackPresetKey \| string` | `'classic'` | Feedback preset key |
|
|
277
|
+
| `sidebar` | `'extended' \| string` | `'extended'` | Sidebar mode; `extended` derives from base/primary |
|
|
278
|
+
| `preset` | `CustomPreset` | - | Custom preset collection (extends base/primary/feedback/sidebar) |
|
|
279
|
+
| `radius` | `string` | `'0.625rem'` | Global border radius |
|
|
280
|
+
| `styleTarget` | `'html' \| ':root'` | `':root'` | CSS variables mount selector |
|
|
281
|
+
| `darkSelector` | `'class' \| 'media' \| string` | `'class'` | Dark mode selector (custom string supported) |
|
|
282
|
+
| `format` | `'hsl' \| 'oklch'` | `'hsl'` | Output color format |
|
|
86
283
|
|
|
87
284
|
### Preset Configuration (PresetConfig)
|
|
88
285
|
|
|
89
286
|
```typescript
|
|
90
287
|
interface PresetConfig {
|
|
91
|
-
base?:
|
|
92
|
-
|
|
93
|
-
feedback?:
|
|
288
|
+
base?: string;
|
|
289
|
+
primary?: string;
|
|
290
|
+
feedback?: string;
|
|
291
|
+
sidebar?: 'extended' | string;
|
|
94
292
|
}
|
|
95
293
|
```
|
|
96
294
|
|
|
@@ -186,78 +384,75 @@ Supports three color value formats:
|
|
|
186
384
|
### Example 1: Classic Blue Theme
|
|
187
385
|
|
|
188
386
|
```typescript
|
|
189
|
-
createShadcnTheme({
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
feedback: 'classic'
|
|
194
|
-
},
|
|
387
|
+
const theme = createShadcnTheme({
|
|
388
|
+
base: 'slate',
|
|
389
|
+
primary: 'blue',
|
|
390
|
+
feedback: 'classic',
|
|
195
391
|
radius: '0.5rem',
|
|
196
392
|
darkSelector: 'class'
|
|
197
393
|
});
|
|
394
|
+
|
|
395
|
+
const css = theme.getCss();
|
|
198
396
|
```
|
|
199
397
|
|
|
200
398
|
### Example 2: Modern Purple Theme
|
|
201
399
|
|
|
202
400
|
```typescript
|
|
203
|
-
createShadcnTheme({
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
feedback: 'modern'
|
|
208
|
-
},
|
|
401
|
+
const theme = createShadcnTheme({
|
|
402
|
+
base: 'zinc',
|
|
403
|
+
primary: 'violet',
|
|
404
|
+
feedback: 'modern',
|
|
209
405
|
radius: '0.75rem',
|
|
210
406
|
darkSelector: 'class',
|
|
211
407
|
format: 'oklch'
|
|
212
408
|
});
|
|
409
|
+
|
|
410
|
+
const css = theme.getCss();
|
|
213
411
|
```
|
|
214
412
|
|
|
215
|
-
### Example 3:
|
|
413
|
+
### Example 3: Override Per Generation
|
|
216
414
|
|
|
217
415
|
```typescript
|
|
218
|
-
createShadcnTheme({
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
foreground: 'oklch(20% 0 0)',
|
|
223
|
-
primary: 'oklch(50% 0.25 280)', // Custom brand purple
|
|
224
|
-
primaryForeground: 'oklch(100% 0 0)',
|
|
225
|
-
secondary: 'oklch(95% 0.01 280)',
|
|
226
|
-
secondaryForeground: 'oklch(30% 0 0)',
|
|
227
|
-
// ... other colors
|
|
228
|
-
}
|
|
229
|
-
// dark is optional, will be auto-generated if not provided
|
|
230
|
-
}
|
|
231
|
-
});
|
|
416
|
+
const theme = createShadcnTheme({ base: 'slate', primary: 'indigo', feedback: 'classic' });
|
|
417
|
+
|
|
418
|
+
const css1 = theme.getCss();
|
|
419
|
+
const css2 = theme.getCss({ primary: 'emerald', feedback: 'vivid' });
|
|
232
420
|
```
|
|
233
421
|
|
|
234
422
|
### Example 4: Media Query Dark Mode
|
|
235
423
|
|
|
236
424
|
```typescript
|
|
237
|
-
createShadcnTheme({
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
theme: 'indigo'
|
|
241
|
-
},
|
|
425
|
+
const theme = createShadcnTheme({
|
|
426
|
+
base: 'slate',
|
|
427
|
+
primary: 'indigo',
|
|
242
428
|
darkSelector: 'media' // Use system preference
|
|
243
429
|
});
|
|
430
|
+
|
|
431
|
+
const css = theme.getCss();
|
|
244
432
|
```
|
|
245
433
|
|
|
246
434
|
### Example 5: Custom Dark Mode Selector
|
|
247
435
|
|
|
248
436
|
```typescript
|
|
249
|
-
createShadcnTheme({
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
theme: 'emerald'
|
|
253
|
-
},
|
|
437
|
+
const theme = createShadcnTheme({
|
|
438
|
+
base: 'slate',
|
|
439
|
+
primary: 'emerald',
|
|
254
440
|
darkSelector: '[data-theme="dark"]' // Custom selector
|
|
255
441
|
});
|
|
442
|
+
|
|
443
|
+
const css = theme.getCss();
|
|
256
444
|
```
|
|
257
445
|
|
|
258
446
|
## 🎯 Generated CSS Variables
|
|
259
447
|
|
|
260
|
-
|
|
448
|
+
`getCss()` returns a CSS string containing variables like the following.
|
|
449
|
+
|
|
450
|
+
When `format: 'hsl'`, variable values are `h s l [/ alpha]` (without the outer `hsl(...)` wrapper):
|
|
451
|
+
|
|
452
|
+
Notes:
|
|
453
|
+
|
|
454
|
+
- When `format: 'hsl'` and the color key is `border`, `input`, or `sidebarBorder`, if the value includes opacity (e.g. `hsl(... / 0.1)` or `oklch(... / 0.1)`), the library also emits alpha variables: `--border-alpha`, `--input-alpha`, `--sidebar-border-alpha`. Meanwhile `--border` / `--input` / `--sidebar-border` keep only the `h s l` part (without the `/ alpha`).
|
|
455
|
+
- It generates 11 palette variables (50-950) for `primary`, `destructive`, `success`, `warning`, `info`, and `carbon`: `50/100/200/300/400/500/600/700/800/900/950`.
|
|
261
456
|
|
|
262
457
|
```css
|
|
263
458
|
:root {
|
|
@@ -265,9 +460,13 @@ After calling `createShadcnTheme()`, a `<style>` tag containing the following va
|
|
|
265
460
|
--background: 0 0% 100%;
|
|
266
461
|
--foreground: 222.2 84% 4.9%;
|
|
267
462
|
--primary: 221.2 83.2% 53.3%;
|
|
463
|
+
|
|
464
|
+
/* In hsl mode: border/input/sidebarBorder also output alpha vars */
|
|
465
|
+
--border: 214.3 31.8% 91.4%;
|
|
466
|
+
--border-alpha: 0.1;
|
|
268
467
|
/* ... more variables */
|
|
269
468
|
|
|
270
|
-
/* Auto-generated palettes */
|
|
469
|
+
/* Auto-generated palettes (11 levels: 50-950) */
|
|
271
470
|
--primary-50: 239 84% 97%;
|
|
272
471
|
--primary-100: 237 84% 94%;
|
|
273
472
|
/* ... primary-200 to primary-950 */
|
|
@@ -287,23 +486,36 @@ After calling `createShadcnTheme()`, a `<style>` tag containing the following va
|
|
|
287
486
|
}
|
|
288
487
|
```
|
|
289
488
|
|
|
489
|
+
When `format: 'oklch'`, variable values include the outer `oklch(...)` wrapper:
|
|
490
|
+
|
|
491
|
+
```css
|
|
492
|
+
:root {
|
|
493
|
+
--background: oklch(100% 0 0);
|
|
494
|
+
--foreground: oklch(20% 0 0);
|
|
495
|
+
--border: oklch(100% 0 0 / 0.1);
|
|
496
|
+
}
|
|
497
|
+
```
|
|
498
|
+
|
|
290
499
|
## 💡 Advanced Usage
|
|
291
500
|
|
|
292
501
|
### Dynamic Theme Switching
|
|
293
502
|
|
|
294
503
|
```typescript
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
504
|
+
const theme = createShadcnTheme();
|
|
505
|
+
|
|
506
|
+
function apply(cssText: string) {
|
|
507
|
+
const id = 'SHADCN_THEME_STYLE';
|
|
508
|
+
const el = document.getElementById(id) ?? document.createElement('style');
|
|
509
|
+
el.id = id;
|
|
510
|
+
el.textContent = cssText;
|
|
511
|
+
document.head.appendChild(el);
|
|
512
|
+
}
|
|
299
513
|
|
|
300
|
-
|
|
301
|
-
|
|
514
|
+
apply(theme.getCss());
|
|
515
|
+
apply(theme.getCss({ base: 'zinc', primary: 'purple' }));
|
|
302
516
|
|
|
303
|
-
//
|
|
304
|
-
|
|
305
|
-
presets: { base: 'zinc', theme: 'purple' }
|
|
306
|
-
});
|
|
517
|
+
// Dark mode switching is controlled by your darkSelector (e.g. default is adding .dark)
|
|
518
|
+
document.documentElement.classList.add('dark');
|
|
307
519
|
```
|
|
308
520
|
|
|
309
521
|
### Using with Tailwind CSS
|
|
@@ -336,6 +548,29 @@ module.exports = {
|
|
|
336
548
|
}
|
|
337
549
|
```
|
|
338
550
|
|
|
551
|
+
When you use `format: 'hsl'`, opacity must be handled separately, especially for `border` / `input` / `sidebarBorder`:
|
|
552
|
+
|
|
553
|
+
- These variables output `h s l` (without `/ alpha`). If opacity is present, the library also emits `--border-alpha` / `--input-alpha` / `--sidebar-border-alpha`.
|
|
554
|
+
- In Tailwind, you can compose them using the slash syntax:
|
|
555
|
+
|
|
556
|
+
```js
|
|
557
|
+
// Use the generated alpha value
|
|
558
|
+
border: 'hsl(var(--border) / var(--border-alpha))'
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
If you want Tailwind opacity modifiers to work (e.g. `border-border/50`), use the `<alpha-value>` placeholder (in this case you typically don't use `--border-alpha`):
|
|
562
|
+
|
|
563
|
+
```js
|
|
564
|
+
// Let Tailwind inject opacity
|
|
565
|
+
border: 'hsl(var(--border) / <alpha-value>)'
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
If you use `format: 'oklch'`, since the variable value already contains `oklch(...)`, use `var(--xxx)` directly in Tailwind (no extra `oklch(...)` wrapper needed):
|
|
569
|
+
|
|
570
|
+
```js
|
|
571
|
+
background: 'var(--background)'
|
|
572
|
+
```
|
|
573
|
+
|
|
339
574
|
### Using in CSS
|
|
340
575
|
|
|
341
576
|
```css
|