shadcn-theme-menu 1.1.32 → 1.1.47

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 CHANGED
@@ -39,6 +39,7 @@ Beautiful theme components for shadcn/ui with 24+ color themes, dark/light mode,
39
39
  - **Fully type-safe** – complete TypeScript support with exported types
40
40
  - **Customizable** – pass your own Button/DropdownMenu components or set themes programmatically
41
41
  - **Persistent** – automatic `localStorage` support for color theme preferences
42
+ - **Themed typography** – each theme brings its own font, previewed live on hover
42
43
 
43
44
  ---
44
45
 
@@ -124,6 +125,57 @@ Animated toggle with particle effects.
124
125
 
125
126
  24 themes: `modern-minimal`, `elegant-luxury`, `cyberpunk`, `twitter`, `mocha-mousse`, `bubblegum`, `amethyst-haze`, `pink-lemonade`, `notebook`, `doom-64`, `catppuccin`, `graphite`, `perpetuity`, `kodama-grove`, `cosmic-night`, `tangerine`, `quantum-rose`, `nature`, `bold-tech`, `amber-minimal`, `supabase`, `neo-brutalism`, `solar-dusk`, `claymorphism`, `pastel-dreams`
126
127
 
128
+ ## Theme Fonts
129
+
130
+ A theme is a typeface as much as a palette. Each `theme-*` class defines
131
+ `--font-sans`, `--font-serif` and `--font-mono` alongside its colors, and
132
+ `themes.css` both loads those families from Google Fonts and applies the sans
133
+ face to the document:
134
+
135
+ ```css
136
+ html[class*="theme-"],
137
+ html[class*="theme-"] body {
138
+ font-family: var(--font-sans, ui-sans-serif, system-ui, sans-serif);
139
+ }
140
+ ```
141
+
142
+ Because the color theme is a class on `<html>`, the font follows every theme
143
+ change — including the hover preview in `ThemeDropdown` and `SidebarUserMenu`,
144
+ where the page re-typesets under the cursor and reverts on mouse-out. Nothing
145
+ to wire up: importing `themes.css` is enough.
146
+
147
+ The serif and mono faces are not applied globally; reach them with the
148
+ `.font-theme-serif` / `.font-theme-mono` utilities (and `.font-theme-sans` for
149
+ a subtree that opted out).
150
+
151
+ ```tsx
152
+ <blockquote className="font-theme-serif">Set in the theme's serif face.</blockquote>
153
+ <pre className="font-theme-mono">$ npm install</pre>
154
+ ```
155
+
156
+ **Overriding.** To keep a self-hosted face (`next/font`, Fontsource) while the
157
+ theme colors still switch, restate the same selector pair after the import —
158
+ equal specificity, later source order, so yours wins:
159
+
160
+ ```css
161
+ @import "shadcn-theme-menu/themes.css";
162
+
163
+ html[class*="theme-"],
164
+ html[class*="theme-"] body {
165
+ font-family: var(--font-geist-sans), sans-serif;
166
+ }
167
+ ```
168
+
169
+ Redefining `--font-sans` on `:root` will *not* do it: each theme block declares
170
+ that variable at two-class specificity and outranks `:root`. A bare
171
+ `body { font-family }` loses too. For a user-facing font preference, set
172
+ `style.fontFamily` inline on **both** `<html>` and `<body>` — inline beats the
173
+ rule, but setting it on `<html>` alone is overridden again at `<body>`, since
174
+ the rule targets both. Clearing it back to `""` restores the theme's font.
175
+
176
+ A handful of themes (`claude`, `caffeine`, `lemonade`) deliberately declare no
177
+ font of their own and inherit whatever your app already uses.
178
+
127
179
  ## Custom Components
128
180
 
129
181
  Pass your own Button or DropdownMenu components:
@@ -188,3 +240,9 @@ cd demo
188
240
  pnpm install
189
241
  pnpm dev
190
242
  ```
243
+
244
+ ---
245
+
246
+ [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request)
247
+
248
+ Please star this repo for updates! 🌟
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shadcn-theme-menu",
3
- "version": "1.1.32",
3
+ "version": "1.1.47",
4
4
  "description": "A collection of beautiful shadcn/ui theme components with dynamic theme switching and animations",
5
5
  "author": "vtempest",
6
6
  "type": "module",
@@ -25,7 +25,10 @@
25
25
  "scripts": {
26
26
  "build": "vite build",
27
27
  "ship": "npm run build; npx standard-version --release-as patch; rm CHANGELOG.md; npm publish",
28
- "demo": "cd demo && pnpm dev"
28
+ "demo": "cd demo && pnpm dev",
29
+ "test": "vitest run",
30
+ "test:watch": "vitest",
31
+ "coverage": "vitest run --coverage"
29
32
  },
30
33
  "sideEffects": [
31
34
  "*.css"
@@ -75,8 +78,11 @@
75
78
  "@types/react-dom": "^19.2.3",
76
79
  "@types/react-window": "^2.0.0",
77
80
  "@vitejs/plugin-react": "^6.0.1",
81
+ "@vitest/coverage-v8": "^4.1.0",
82
+ "jsdom": "^28.0.1",
78
83
  "react": "^19.2.4",
79
84
  "react-dom": "^19.2.4",
80
- "vite": "^8.0.0"
85
+ "vite": "^8.0.0",
86
+ "vitest": "^4.1.0"
81
87
  }
82
88
  }
@@ -1,3 +1,51 @@
1
+ /* ---------------------------------------------------------------------------
2
+ * Theme typography
3
+ *
4
+ * Every `theme-*` block in this file carries `--font-sans` / `--font-serif` /
5
+ * `--font-mono` next to its colors, so a theme is a typeface as much as a
6
+ * palette. Two things have to be true for that to reach the screen:
7
+ *
8
+ * 1. the families have to be loaded — the Google Fonts import below covers
9
+ * every non-system family the themes reference; and
10
+ * 2. something has to actually read `--font-sans` — the rule under it.
11
+ *
12
+ * The rule is scoped to `theme-*` so it only takes over once a color theme is
13
+ * active. Because the color theme is a class on `<html>`, the font then follows
14
+ * every theme change — including the hover preview in `ThemeDropdown`, where
15
+ * the page re-typesets under the cursor and reverts on mouse-out.
16
+ *
17
+ * Overriding it: the selector is (0,1,1), so a bare `body { font-family }` in
18
+ * an app stylesheet loses to it — restate this same selector pair after the
19
+ * import (equal specificity, later source order), or set `style.fontFamily`
20
+ * inline on `<html>` *and* `<body>`: the rule targets both, so an inline style
21
+ * on `<html>` alone is overridden again at `<body>`. Redefining `--font-sans`
22
+ * on `:root` is *not* enough: each theme block declares it at (0,2,0) and
23
+ * outranks `:root`.
24
+ *
25
+ * Themes with no `--font-*` of their own — `claude`, `caffeine`, `lemonade` —
26
+ * deliberately inherit whatever the app already uses.
27
+ * ------------------------------------------------------------------------- */
28
+ @import url("https://fonts.googleapis.com/css2?family=Architects+Daughter&family=DM+Sans:wght@400;500;700&family=Fira+Code:wght@400;500;700&family=Geist+Mono:wght@400;500;700&family=Geist:wght@400;500;700&family=IBM+Plex+Mono:wght@400;500;700&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;700&family=Libre+Baskerville:wght@400;700&family=Lora:wght@400;500;600;700&family=Merriweather:wght@400;700&family=Montserrat:wght@400;500;600;700&family=Open+Sans:wght@400;500;600;700&family=Outfit:wght@400;500;600;700&family=Oxanium:wght@400;500;600;700&family=Playfair+Display:wght@400;500;600;700&family=Plus+Jakarta+Sans:wght@400;500;600;700&family=Poppins:wght@400;500;600;700&family=Quicksand:wght@400;500;600;700&family=Roboto+Mono:wght@400;500;700&family=Roboto:wght@400;500;700&family=Source+Code+Pro:wght@400;500;700&family=Source+Serif+4:wght@400;500;600;700&family=Space+Mono:wght@400;700&family=Ubuntu+Mono:wght@400;700&display=swap");
29
+
30
+ html[class*="theme-"],
31
+ html[class*="theme-"] body {
32
+ font-family: var(--font-sans, ui-sans-serif, system-ui, sans-serif);
33
+ }
34
+
35
+ /* Opt-in escape hatches for the other two faces a theme defines — there is no
36
+ other way to reach them, since only the sans face is applied globally. */
37
+ .font-theme-sans {
38
+ font-family: var(--font-sans, ui-sans-serif, system-ui, sans-serif);
39
+ }
40
+
41
+ .font-theme-serif {
42
+ font-family: var(--font-serif, ui-serif, Georgia, serif);
43
+ }
44
+
45
+ .font-theme-mono {
46
+ font-family: var(--font-mono, ui-monospace, monospace);
47
+ }
48
+
1
49
  .theme-minimal.light {
2
50
  --background: #ffffff;
3
51
  --foreground: #333333;
@@ -71,6 +119,9 @@
71
119
  --sidebar-accent-foreground: #bfdbfe;
72
120
  --sidebar-border: #404040;
73
121
  --sidebar-ring: #3b82f6;
122
+ --font-sans: Inter, sans-serif;
123
+ --font-serif: Source Serif 4, serif;
124
+ --font-mono: JetBrains Mono, monospace;
74
125
  }
75
126
 
76
127
  .theme-lemonade.light {
@@ -223,6 +274,9 @@
223
274
  --sidebar-border: #38444d;
224
275
  --sidebar-ring: #1da1f2;
225
276
  --shadow-color: rgba(29, 161, 242, 0.25);
277
+ --font-sans: Open Sans, sans-serif;
278
+ --font-serif: Georgia, serif;
279
+ --font-mono: Menlo, monospace;
226
280
  }
227
281
 
228
282
  .theme-mocha.light {
@@ -304,6 +358,9 @@
304
358
  --sidebar-border: #56453f;
305
359
  --sidebar-ring: #c39e88;
306
360
  --shadow-color: hsl(20 18% 30% / 0.5);
361
+ --font-sans: DM Sans, sans-serif;
362
+ --font-serif: Georgia, serif;
363
+ --font-mono: Menlo, monospace;
307
364
  }
308
365
 
309
366
  .theme-bubblegum.light {
@@ -470,6 +527,9 @@
470
527
  --sidebar-accent-foreground: #f2b8c6;
471
528
  --sidebar-border: #2a273a;
472
529
  --sidebar-ring: #a995c9;
530
+ --font-sans: Geist, sans-serif;
531
+ --font-serif: "Lora", Georgia, serif;
532
+ --font-mono: "Fira Code", "Courier New", monospace;
473
533
  }
474
534
 
475
535
  .theme-notebook.light {
@@ -738,6 +798,9 @@
738
798
  --sidebar-accent-foreground: #1e1e2e;
739
799
  --sidebar-border: #45475a;
740
800
  --sidebar-ring: #cba6f7;
801
+ --font-sans: Montserrat, sans-serif;
802
+ --font-serif: Georgia, serif;
803
+ --font-mono: Fira Code, monospace;
741
804
  }
742
805
 
743
806
  .theme-graphite.light {
@@ -991,6 +1054,9 @@
991
1054
  --sidebar-accent-foreground: #2a2521;
992
1055
  --sidebar-border: #5a5345;
993
1056
  --sidebar-ring: #8a9f7b;
1057
+ --font-sans: Merriweather, serif;
1058
+ --font-serif: Source Serif 4, serif;
1059
+ --font-mono: JetBrains Mono, monospace;
994
1060
  }
995
1061
 
996
1062
  .theme-cosmic.light {
@@ -1072,6 +1138,9 @@
1072
1138
  --sidebar-accent-foreground: #e2e2f5;
1073
1139
  --sidebar-border: #303052;
1074
1140
  --sidebar-ring: #a48fff;
1141
+ --font-sans: Inter, sans-serif;
1142
+ --font-serif: Georgia, serif;
1143
+ --font-mono: JetBrains Mono, monospace;
1075
1144
  }
1076
1145
 
1077
1146
  .theme-tangerine.light {
@@ -1152,6 +1221,9 @@
1152
1221
  --sidebar-accent-foreground: #bfdbfe;
1153
1222
  --sidebar-border: #3d4354;
1154
1223
  --sidebar-ring: #e05d38;
1224
+ --font-sans: Inter, sans-serif;
1225
+ --font-serif: Source Serif 4, serif;
1226
+ --font-mono: JetBrains Mono, monospace;
1155
1227
  }
1156
1228
 
1157
1229
  .theme-quantum.light {
@@ -1311,6 +1383,9 @@
1311
1383
  --sidebar-accent-foreground: #f0ebe5;
1312
1384
  --sidebar-border: #3e4a3d;
1313
1385
  --sidebar-ring: #4caf50;
1386
+ --font-sans: Montserrat, sans-serif;
1387
+ --font-serif: Merriweather, serif;
1388
+ --font-mono: Source Code Pro, monospace;
1314
1389
  }
1315
1390
 
1316
1391
  .theme-boldtech.light {
@@ -1392,6 +1467,9 @@
1392
1467
  --sidebar-accent-foreground: #e0e7ff;
1393
1468
  --sidebar-border: #2e1065;
1394
1469
  --sidebar-ring: #8b5cf6;
1470
+ --font-sans: Roboto, sans-serif;
1471
+ --font-serif: Playfair Display, serif;
1472
+ --font-mono: Fira Code, monospace;
1395
1473
  }
1396
1474
 
1397
1475
  .theme-luxury.light {
@@ -1473,6 +1551,9 @@
1473
1551
  --sidebar-accent-foreground: #fef3c7;
1474
1552
  --sidebar-border: #44403c;
1475
1553
  --sidebar-ring: #b91c1c;
1554
+ --font-sans: Poppins, sans-serif;
1555
+ --font-serif: Libre Baskerville, serif;
1556
+ --font-mono: IBM Plex Mono, monospace;
1476
1557
  }
1477
1558
 
1478
1559
  .theme-ambermin.light {
@@ -1555,6 +1636,9 @@
1555
1636
  --sidebar-accent-foreground: #fde68a;
1556
1637
  --sidebar-border: #404040;
1557
1638
  --sidebar-ring: #f59e0b;
1639
+ --font-sans: Inter, sans-serif;
1640
+ --font-serif: Source Serif 4, serif;
1641
+ --font-mono: JetBrains Mono, monospace;
1558
1642
  }
1559
1643
 
1560
1644
  .theme-supabase.light {
@@ -1636,6 +1720,9 @@
1636
1720
  --sidebar-accent-foreground: #fafafa;
1637
1721
  --sidebar-border: #292929;
1638
1722
  --sidebar-ring: #4ade80;
1723
+ --font-sans: Outfit, sans-serif;
1724
+ --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
1725
+ --font-mono: monospace;
1639
1726
  }
1640
1727
 
1641
1728
  .theme-brutalism.light {
@@ -1716,6 +1803,8 @@
1716
1803
  --sidebar-accent-foreground: #000000;
1717
1804
  --sidebar-border: #ffffff;
1718
1805
  --sidebar-ring: #ff6666;
1806
+ --font-sans: DM Sans, sans-serif;
1807
+ --font-mono: Space Mono, monospace;
1719
1808
  }
1720
1809
 
1721
1810
  .theme-solardusk.light {
@@ -1798,6 +1887,9 @@
1798
1887
  --sidebar-border: #44403c;
1799
1888
  --sidebar-ring: #f97316;
1800
1889
  --shadow-color: hsl(0 0% 5%);
1890
+ --font-sans: Oxanium, sans-serif;
1891
+ --font-serif: Merriweather, serif;
1892
+ --font-mono: Fira Code, monospace;
1801
1893
  }
1802
1894
 
1803
1895
  .theme-claymorphism.light {
@@ -1880,6 +1972,9 @@
1880
1972
  --sidebar-border: #3a3633;
1881
1973
  --sidebar-ring: #818cf8;
1882
1974
  --shadow-color: hsl(0 0% 0%);
1975
+ --font-sans: Plus Jakarta Sans, sans-serif;
1976
+ --font-serif: Lora, serif;
1977
+ --font-mono: Roboto Mono, monospace;
1883
1978
  }
1884
1979
 
1885
1980
  .theme-cyberpunk.light {
@@ -1960,6 +2055,8 @@
1960
2055
  --sidebar-accent-foreground: #0c0c1d;
1961
2056
  --sidebar-border: #2e2e5e;
1962
2057
  --sidebar-ring: #ff00c8;
2058
+ --font-sans: Outfit, sans-serif;
2059
+ --font-mono: Fira Code, monospace;
1963
2060
  }
1964
2061
 
1965
2062
  .theme-pastel.light {
@@ -2041,6 +2138,9 @@
2041
2138
  --sidebar-accent-foreground: #d1d5db;
2042
2139
  --sidebar-border: #3f324a;
2043
2140
  --sidebar-ring: #c0aafd;
2141
+ --font-sans: Open Sans, sans-serif;
2142
+ --font-serif: Source Serif 4, serif;
2143
+ --font-mono: IBM Plex Mono, monospace;
2044
2144
  }
2045
2145
 
2046
2146
  .theme-cleanslate.light {
@@ -2122,6 +2222,9 @@
2122
2222
  --sidebar-accent-foreground: #d1d5db;
2123
2223
  --sidebar-border: #4b5563;
2124
2224
  --sidebar-ring: #818cf8;
2225
+ --font-sans: Inter, sans-serif;
2226
+ --font-serif: Merriweather, serif;
2227
+ --font-mono: JetBrains Mono, monospace;
2125
2228
  }
2126
2229
 
2127
2230
  .theme-caffeine.light {
@@ -2275,6 +2378,9 @@
2275
2378
  --sidebar-accent-foreground: #a1a1aa;
2276
2379
  --sidebar-border: #4b5563;
2277
2380
  --sidebar-ring: #34d399;
2381
+ --font-sans: DM Sans, sans-serif;
2382
+ --font-serif: Lora, serif;
2383
+ --font-mono: IBM Plex Mono, monospace;
2278
2384
  }
2279
2385
 
2280
2386
  .theme-retro.light {
@@ -2355,6 +2461,8 @@
2355
2461
  --sidebar-accent-foreground: #ffffff;
2356
2462
  --sidebar-border: #586e75;
2357
2463
  --sidebar-ring: #d33682;
2464
+ --font-sans: Outfit, sans-serif;
2465
+ --font-mono: Space Mono, monospace;
2358
2466
  }
2359
2467
 
2360
2468
  .theme-bloom.light {
@@ -2436,6 +2544,9 @@
2436
2544
  --sidebar-accent-foreground: #e5e5e5;
2437
2545
  --sidebar-border: #444444;
2438
2546
  --sidebar-ring: #6c5ce7;
2547
+ --font-sans: Montserrat, sans-serif;
2548
+ --font-serif: Playfair Display, serif;
2549
+ --font-mono: Source Code Pro, monospace;
2439
2550
  }
2440
2551
 
2441
2552
  .theme-candyland.light {
@@ -2510,6 +2621,8 @@
2510
2621
  --sidebar-accent-foreground: #000000;
2511
2622
  --sidebar-border: #444444;
2512
2623
  --sidebar-ring: #ff99cc;
2624
+ --font-sans: Poppins, sans-serif;
2625
+ --font-mono: Roboto Mono, monospace;
2513
2626
  }
2514
2627
 
2515
2628
  .theme-aurora.light {
@@ -2585,6 +2698,9 @@
2585
2698
  --sidebar-accent-foreground: #e5e5e5;
2586
2699
  --sidebar-border: #444444;
2587
2700
  --sidebar-ring: #34a85a;
2701
+ --font-sans: Plus Jakarta Sans, sans-serif;
2702
+ --font-serif: Source Serif 4, serif;
2703
+ --font-mono: JetBrains Mono, monospace;
2588
2704
  }
2589
2705
 
2590
2706
  .theme-vintage.light {
@@ -2666,6 +2782,9 @@
2666
2782
  --sidebar-accent-foreground: #ece5d8;
2667
2783
  --sidebar-border: #4a4039;
2668
2784
  --sidebar-ring: #c0a080;
2785
+ --font-sans: Libre Baskerville, serif;
2786
+ --font-serif: Lora, serif;
2787
+ --font-mono: IBM Plex Mono, monospace;
2669
2788
  }
2670
2789
 
2671
2790
  .theme-horizon.light {
@@ -2747,6 +2866,9 @@
2747
2866
  --sidebar-accent-foreground: #2a2024;
2748
2867
  --sidebar-border: #463a41;
2749
2868
  --sidebar-ring: #ff7e5f;
2869
+ --font-sans: Montserrat, sans-serif;
2870
+ --font-serif: Merriweather, serif;
2871
+ --font-mono: Ubuntu Mono, monospace;
2750
2872
  }
2751
2873
 
2752
2874
  .theme-starry.light {
@@ -2820,6 +2942,7 @@
2820
2942
  --sidebar-border: #2d2e3e;
2821
2943
  --sidebar-ring: #ffe066;
2822
2944
  --radius: 0.5rem;
2945
+ --font-sans: Libre Baskerville, serif;
2823
2946
  }
2824
2947
 
2825
2948
  .theme-claude.light {
@@ -3054,4 +3177,7 @@
3054
3177
  --sidebar-accent-foreground: #fafafa;
3055
3178
  --sidebar-border: #ffffff;
3056
3179
  --sidebar-ring: #525252;
3180
+ --font-sans: Geist Mono, monospace;
3181
+ --font-serif: Geist Mono, monospace;
3182
+ --font-mono: Geist Mono, monospace;
3057
3183
  }