From 5e23a984e12d1aeb8617ab92f46de65e790117c6 Mon Sep 17 00:00:00 2001 From: Brian Fertig Date: Fri, 28 Aug 2026 09:00:31 -0600 Subject: [PATCH] Added more themes --- app/globals.css | 436 +++++++++++++++++++++++++++- app/layout.tsx | 13 +- components/theme/theme-provider.tsx | 47 ++- components/theme/theme-toggle.tsx | 131 ++++++--- components/theme/use-dark-theme.ts | 22 +- components/ui/sonner.tsx | 11 +- 6 files changed, 591 insertions(+), 69 deletions(-) diff --git a/app/globals.css b/app/globals.css index 1b5af8f..62ed730 100644 --- a/app/globals.css +++ b/app/globals.css @@ -5,8 +5,9 @@ @import "@uiw/react-markdown-preview/markdown.css"; /* "dark:" must be true for every dark-surfaced theme, not just .dark -- - Ocean is a second dark look, so both classes turn on dark utilities. */ -@custom-variant dark (&:is(.dark *, .ocean *)); + the dark looks (Dark, Ocean, Pine, Plum, Midnight, Ember, Rosewood) all + turn on dark utilities. */ +@custom-variant dark (&:is(.dark *, .ocean *, .theme-pine *, .theme-plum *, .theme-midnight *, .theme-ember *, .theme-rosewood *)); @theme inline { --color-background: var(--background); @@ -58,13 +59,25 @@ /* --------------------------------------------------------------------------- Themes - The app ships four looks, chosen via the theme picker (next-themes): - default -- calm, cool neutral light theme (the safe, focused one) - sunset -- warm paper + persimmon accent, a cozier light theme - dark -- deep charcoal with an indigo accent - ocean -- deep blue-green night theme with a seafoam accent + The app ships fourteen looks, chosen via the theme picker: + Light: + default -- calm, cool neutral light theme (the safe, focused one) + sunset -- warm paper + persimmon accent, a cozier light theme + meadow -- fresh green paper with an emerald accent + honey -- buttercream paper with a honey-amber accent + rose -- soft pink paper with a raspberry accent ("Ros\xe9") + lavender -- lilac paper with a violet accent + slate -- cool grey-blue paper with a steel-blue accent + Dark: + dark -- deep charcoal with an indigo accent + ocean -- deep blue-green night theme with a seafoam accent + pine -- deep forest green with a mint accent + plum -- deep plum night with an orchid accent + midnight -- near-black navy with an ice-periwinkle accent + ember -- warm hearth charcoal with a glowing amber accent + rosewood -- deep wine with a rose accent Each is a complete token set; components only ever use tokens, so adding - a fifth theme later is just another block like these. + another theme later is just another block like these. --------------------------------------------------------------------------- */ :root, @@ -225,6 +238,413 @@ --sidebar-ring: oklch(0.72 0.11 192); } +/* Meadow -- fresh green paper + emerald accent: a spring morning on the desk. + Light-surfaced; pairs with the neutral group palette as well as anything. +*/ +.theme-meadow { + color-scheme: light; + --background: oklch(0.975 0.012 145); + --foreground: oklch(0.26 0.03 150); + --card: oklch(0.99 0.006 145); + --card-foreground: oklch(0.26 0.03 150); + --popover: oklch(0.992 0.005 145); + --popover-foreground: oklch(0.26 0.03 150); + /* Emerald -- leafy enough to feel grown, saturated enough to lead. */ + --primary: oklch(0.55 0.16 155); + --primary-foreground: oklch(0.98 0.01 145); + --secondary: oklch(0.945 0.018 145); + --secondary-foreground: oklch(0.31 0.05 150); + --muted: oklch(0.938 0.016 145); + --muted-foreground: oklch(0.53 0.04 150); + --accent: oklch(0.925 0.03 150); + --accent-foreground: oklch(0.35 0.1 155); + --destructive: oklch(0.57 0.21 25); + --border: oklch(0.89 0.018 145); + --input: oklch(0.86 0.02 145); + --ring: oklch(0.57 0.14 155); + --lane: oklch(0.94 0.015 145); + --chart-1: oklch(0.8 0.08 145); + --chart-2: oklch(0.68 0.11 152); + --chart-3: oklch(0.55 0.12 158); + --chart-4: oklch(0.44 0.1 152); + --chart-5: oklch(0.33 0.08 148); + --radius: 0.8rem; + --sidebar: oklch(0.965 0.01 145); + --sidebar-foreground: oklch(0.26 0.03 150); + --sidebar-primary: oklch(0.55 0.16 155); + --sidebar-primary-foreground: oklch(0.98 0.01 145); + --sidebar-accent: oklch(0.925 0.03 150); + --sidebar-accent-foreground: oklch(0.35 0.1 155); + --sidebar-border: oklch(0.89 0.018 145); + --sidebar-ring: oklch(0.57 0.14 155); +} + +/* Honey -- buttercream paper + honey-amber accent: golden hour, mellowed. + Light-surfaced; warmer than Sunset's terracotta, softer and yellower. */ +.theme-honey { + color-scheme: light; + --background: oklch(0.972 0.024 95); + --foreground: oklch(0.28 0.04 80); + --card: oklch(0.988 0.015 95); + --card-foreground: oklch(0.28 0.04 80); + --popover: oklch(0.99 0.014 95); + --popover-foreground: oklch(0.28 0.04 80); + /* Honey-amber -- glowing but gentle, like light through glass. */ + --primary: oklch(0.6 0.16 70); + --primary-foreground: oklch(0.98 0.015 90); + --secondary: oklch(0.948 0.03 92); + --secondary-foreground: oklch(0.33 0.06 78); + --muted: oklch(0.94 0.028 92); + --muted-foreground: oklch(0.55 0.05 82); + --accent: oklch(0.93 0.04 88); + --accent-foreground: oklch(0.37 0.11 75); + --destructive: oklch(0.57 0.21 25); + --border: oklch(0.885 0.03 90); + --input: oklch(0.855 0.032 90); + --ring: oklch(0.62 0.14 78); + --lane: oklch(0.942 0.026 92); + --chart-1: oklch(0.82 0.1 85); + --chart-2: oklch(0.7 0.13 78); + --chart-3: oklch(0.58 0.14 72); + --chart-4: oklch(0.47 0.12 75); + --chart-5: oklch(0.36 0.09 80); + /* A touch softer than default -- honey is meant to feel mellow. */ + --radius: 0.85rem; + --sidebar: oklch(0.962 0.02 95); + --sidebar-foreground: oklch(0.28 0.04 80); + --sidebar-primary: oklch(0.6 0.16 70); + --sidebar-primary-foreground: oklch(0.98 0.015 90); + --sidebar-accent: oklch(0.93 0.04 88); + --sidebar-accent-foreground: oklch(0.37 0.11 75); + --sidebar-border: oklch(0.885 0.03 90); + --sidebar-ring: oklch(0.62 0.14 78); +} + +/* Ros\xe9 -- soft pink paper + raspberry accent: a blush, not a ballroom. + Light-surfaced. */ +.theme-rose { + color-scheme: light; + --background: oklch(0.972 0.014 15); + --foreground: oklch(0.27 0.035 15); + --card: oklch(0.988 0.008 18); + --card-foreground: oklch(0.27 0.035 15); + --popover: oklch(0.99 0.008 18); + --popover-foreground: oklch(0.27 0.035 15); + /* Raspberry -- enough punch to be the accent, sweet enough to sit + comfortably inside the pink paper. */ + --primary: oklch(0.55 0.19 12); + --primary-foreground: oklch(0.98 0.01 20); + --secondary: oklch(0.948 0.02 15); + --secondary-foreground: oklch(0.32 0.06 12); + --muted: oklch(0.94 0.018 15); + --muted-foreground: oklch(0.54 0.045 12); + --accent: oklch(0.93 0.032 14); + --accent-foreground: oklch(0.36 0.11 12); + /* A deeper red than the rest of the pink, so errors still read as errors. */ + --destructive: oklch(0.55 0.22 20); + --border: oklch(0.888 0.022 15); + --input: oklch(0.86 0.024 15); + --ring: oklch(0.58 0.16 14); + --lane: oklch(0.942 0.02 15); + --chart-1: oklch(0.8 0.07 20); + --chart-2: oklch(0.68 0.11 15); + --chart-3: oklch(0.56 0.13 12); + --chart-4: oklch(0.45 0.12 10); + --chart-5: oklch(0.34 0.09 15); + /* Softer corners -- the most romantic look in the set. */ + --radius: 0.9rem; + --sidebar: oklch(0.962 0.012 15); + --sidebar-foreground: oklch(0.27 0.035 15); + --sidebar-primary: oklch(0.55 0.19 12); + --sidebar-primary-foreground: oklch(0.98 0.01 20); + --sidebar-accent: oklch(0.93 0.032 14); + --sidebar-accent-foreground: oklch(0.36 0.11 12); + --sidebar-border: oklch(0.888 0.022 15); + --sidebar-ring: oklch(0.58 0.16 14); +} + +/* Lavender -- lilac paper + violet accent: dusk without the dark. + Light-surfaced. */ +.theme-lavender { + color-scheme: light; + --background: oklch(0.972 0.012 300); + --foreground: oklch(0.27 0.035 305); + --card: oklch(0.988 0.008 300); + --card-foreground: oklch(0.27 0.035 305); + --popover: oklch(0.99 0.008 300); + --popover-foreground: oklch(0.27 0.035 305); + /* Violet -- a little more saturated than the paper's tint so it leads. */ + --primary: oklch(0.53 0.19 300); + --primary-foreground: oklch(0.98 0.01 300); + --secondary: oklch(0.948 0.018 300); + --secondary-foreground: oklch(0.32 0.06 305); + --muted: oklch(0.94 0.016 300); + --muted-foreground: oklch(0.54 0.045 305); + --accent: oklch(0.93 0.03 302); + --accent-foreground: oklch(0.36 0.11 305); + --destructive: oklch(0.57 0.21 25); + --border: oklch(0.888 0.018 300); + --input: oklch(0.86 0.02 300); + --ring: oklch(0.56 0.16 300); + --lane: oklch(0.942 0.015 300); + --chart-1: oklch(0.8 0.07 300); + --chart-2: oklch(0.68 0.11 302); + --chart-3: oklch(0.56 0.13 305); + --chart-4: oklch(0.45 0.12 308); + --chart-5: oklch(0.34 0.09 305); + --radius: 0.85rem; + --sidebar: oklch(0.962 0.012 300); + --sidebar-foreground: oklch(0.27 0.035 305); + --sidebar-primary: oklch(0.53 0.19 300); + --sidebar-primary-foreground: oklch(0.98 0.01 300); + --sidebar-accent: oklch(0.93 0.03 302); + --sidebar-accent-foreground: oklch(0.36 0.11 305); + --sidebar-border: oklch(0.888 0.018 300); + --sidebar-ring: oklch(0.56 0.16 300); +} + +/* Slate -- cool grey-blue paper + steel-blue accent: the "work mode" look. + Light-surfaced; the crispest corners in the set. */ +.theme-slate { + color-scheme: light; + --background: oklch(0.968 0.006 240); + --foreground: oklch(0.25 0.02 245); + --card: oklch(0.985 0.004 240); + --card-foreground: oklch(0.25 0.02 245); + --popover: oklch(0.988 0.004 240); + --popover-foreground: oklch(0.25 0.02 245); + /* Steel blue -- calmer than Default's indigo, quieter by design. */ + --primary: oklch(0.52 0.11 240); + --primary-foreground: oklch(0.98 0.005 240); + --secondary: oklch(0.945 0.008 240); + --secondary-foreground: oklch(0.31 0.03 245); + --muted: oklch(0.938 0.008 240); + --muted-foreground: oklch(0.52 0.02 245); + --accent: oklch(0.925 0.014 242); + --accent-foreground: oklch(0.35 0.08 245); + --destructive: oklch(0.57 0.2 25); + --border: oklch(0.895 0.006 240); + --input: oklch(0.875 0.006 240); + --ring: oklch(0.55 0.09 240); + --lane: oklch(0.94 0.007 240); + --chart-1: oklch(0.82 0.04 240); + --chart-2: oklch(0.7 0.06 242); + --chart-3: oklch(0.58 0.08 244); + --chart-4: oklch(0.47 0.07 246); + --chart-5: oklch(0.36 0.05 248); + /* Crisper corners -- the most "engineered" look in the set. */ + --radius: 0.7rem; + --sidebar: oklch(0.958 0.005 240); + --sidebar-foreground: oklch(0.25 0.02 245); + --sidebar-primary: oklch(0.52 0.11 240); + --sidebar-primary-foreground: oklch(0.98 0.005 240); + --sidebar-accent: oklch(0.925 0.014 242); + --sidebar-accent-foreground: oklch(0.35 0.08 245); + --sidebar-border: oklch(0.895 0.006 240); + --sidebar-ring: oklch(0.55 0.09 240); +} + +/* Pine -- deep forest green night + mint accent: the woods after rain. + Dark-surfaced (see the `dark` custom-variant above). */ +.theme-pine { + color-scheme: dark; + --background: oklch(0.2 0.035 160); + --foreground: oklch(0.92 0.02 150); + --card: oklch(0.245 0.04 158); + --card-foreground: oklch(0.92 0.02 150); + --popover: oklch(0.255 0.042 156); + --popover-foreground: oklch(0.92 0.02 150); + /* Mint -- luminous against the deep green, without Ocean's cool cast. */ + --primary: oklch(0.76 0.12 165); + --primary-foreground: oklch(0.2 0.05 160); + --secondary: oklch(0.295 0.042 158); + --secondary-foreground: oklch(0.92 0.02 150); + --muted: oklch(0.285 0.04 158); + --muted-foreground: oklch(0.7 0.03 150); + --accent: oklch(0.33 0.05 160); + --accent-foreground: oklch(0.9 0.03 165); + --destructive: oklch(0.7 0.17 25); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 14%); + --ring: oklch(0.72 0.1 165); + --lane: oklch(1 0 0 / 6%); + --chart-1: oklch(0.76 0.1 165); + --chart-2: oklch(0.63 0.11 160); + --chart-3: oklch(0.5 0.11 155); + --chart-4: oklch(0.4 0.09 150); + --chart-5: oklch(0.3 0.07 150); + --radius: 0.8rem; + --sidebar: oklch(0.225 0.04 158); + --sidebar-foreground: oklch(0.92 0.02 150); + --sidebar-primary: oklch(0.76 0.12 165); + --sidebar-primary-foreground: oklch(0.2 0.05 160); + --sidebar-accent: oklch(0.33 0.05 160); + --sidebar-accent-foreground: oklch(0.9 0.03 165); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.72 0.1 165); +} + +/* Plum -- deep plum night + orchid accent: the richest dark in the set. + Dark-surfaced. */ +.theme-plum { + color-scheme: dark; + --background: oklch(0.2 0.03 315); + --foreground: oklch(0.92 0.02 320); + --card: oklch(0.245 0.035 315); + --card-foreground: oklch(0.92 0.02 320); + --popover: oklch(0.255 0.038 315); + --popover-foreground: oklch(0.92 0.02 320); + /* Orchid -- bright enough to lead the eye, deep enough to stay nocturnal. */ + --primary: oklch(0.74 0.13 320); + --primary-foreground: oklch(0.2 0.05 315); + --secondary: oklch(0.295 0.04 315); + --secondary-foreground: oklch(0.92 0.02 320); + --muted: oklch(0.285 0.04 315); + --muted-foreground: oklch(0.7 0.03 320); + --accent: oklch(0.33 0.05 318); + --accent-foreground: oklch(0.9 0.03 322); + --destructive: oklch(0.7 0.17 25); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 14%); + --ring: oklch(0.7 0.12 320); + --lane: oklch(1 0 0 / 6%); + --chart-1: oklch(0.76 0.1 320); + --chart-2: oklch(0.63 0.11 318); + --chart-3: oklch(0.5 0.11 315); + --chart-4: oklch(0.4 0.1 312); + --chart-5: oklch(0.3 0.08 315); + --radius: 0.8rem; + --sidebar: oklch(0.225 0.035 315); + --sidebar-foreground: oklch(0.92 0.02 320); + --sidebar-primary: oklch(0.74 0.13 320); + --sidebar-primary-foreground: oklch(0.2 0.05 315); + --sidebar-accent: oklch(0.33 0.05 318); + --sidebar-accent-foreground: oklch(0.9 0.03 322); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.7 0.12 320); +} + +/* Midnight -- the darkest surface in the set, near-black navy, with an + ice-periwinkle accent: a clear winter night. + Dark-surfaced. */ +.theme-midnight { + color-scheme: dark; + --background: oklch(0.16 0.02 262); + --foreground: oklch(0.93 0.01 258); + --card: oklch(0.2 0.022 260); + --card-foreground: oklch(0.93 0.01 258); + --popover: oklch(0.21 0.024 260); + --popover-foreground: oklch(0.93 0.01 258); + /* Ice periwinkle -- pale and cool, a thin light against the black. */ + --primary: oklch(0.76 0.09 255); + --primary-foreground: oklch(0.17 0.03 260); + --secondary: oklch(0.255 0.024 262); + --secondary-foreground: oklch(0.93 0.01 258); + --muted: oklch(0.245 0.024 262); + --muted-foreground: oklch(0.7 0.015 258); + --accent: oklch(0.29 0.035 260); + --accent-foreground: oklch(0.9 0.02 255); + --destructive: oklch(0.7 0.17 25); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 14%); + --ring: oklch(0.74 0.08 255); + --lane: oklch(1 0 0 / 6%); + --chart-1: oklch(0.78 0.07 255); + --chart-2: oklch(0.66 0.08 258); + --chart-3: oklch(0.54 0.09 260); + --chart-4: oklch(0.44 0.08 262); + --chart-5: oklch(0.34 0.06 265); + --radius: 0.75rem; + --sidebar: oklch(0.185 0.022 262); + --sidebar-foreground: oklch(0.93 0.01 258); + --sidebar-primary: oklch(0.76 0.09 255); + --sidebar-primary-foreground: oklch(0.17 0.03 260); + --sidebar-accent: oklch(0.29 0.035 260); + --sidebar-accent-foreground: oklch(0.9 0.02 255); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.74 0.08 255); +} + +/* Ember -- warm hearth charcoal + glowing amber accent: Sunset's dark twin. + Dark-surfaced. */ +.theme-ember { + color-scheme: dark; + --background: oklch(0.2 0.025 45); + --foreground: oklch(0.92 0.015 60); + --card: oklch(0.245 0.028 48); + --card-foreground: oklch(0.92 0.015 60); + --popover: oklch(0.255 0.03 48); + --popover-foreground: oklch(0.92 0.015 60); + /* Ember amber -- warm glow, like coals catching the evening. */ + --primary: oklch(0.72 0.14 62); + --primary-foreground: oklch(0.2 0.04 50); + --secondary: oklch(0.295 0.03 50); + --secondary-foreground: oklch(0.92 0.015 60); + --muted: oklch(0.285 0.03 50); + --muted-foreground: oklch(0.7 0.025 55); + --accent: oklch(0.33 0.04 52); + --accent-foreground: oklch(0.9 0.03 62); + --destructive: oklch(0.7 0.17 25); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 14%); + --ring: oklch(0.7 0.12 62); + --lane: oklch(1 0 0 / 6%); + --chart-1: oklch(0.78 0.1 58); + --chart-2: oklch(0.66 0.12 55); + --chart-3: oklch(0.54 0.12 52); + --chart-4: oklch(0.44 0.1 50); + --chart-5: oklch(0.34 0.08 52); + --radius: 0.85rem; + --sidebar: oklch(0.225 0.028 48); + --sidebar-foreground: oklch(0.92 0.015 60); + --sidebar-primary: oklch(0.72 0.14 62); + --sidebar-primary-foreground: oklch(0.2 0.04 50); + --sidebar-accent: oklch(0.33 0.04 52); + --sidebar-accent-foreground: oklch(0.9 0.03 62); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.7 0.12 62); +} + +/* Rosewood -- deep wine + rose accent: Ros\xe9's dark twin. + Dark-surfaced. */ +.theme-rosewood { + color-scheme: dark; + --background: oklch(0.2 0.04 18); + --foreground: oklch(0.92 0.02 20); + --card: oklch(0.245 0.045 18); + --card-foreground: oklch(0.92 0.02 20); + --popover: oklch(0.255 0.048 18); + --popover-foreground: oklch(0.92 0.02 20); + /* Rose -- bright enough to lead, warm enough to stay in the wine. */ + --primary: oklch(0.74 0.13 20); + --primary-foreground: oklch(0.2 0.05 15); + --secondary: oklch(0.295 0.045 18); + --secondary-foreground: oklch(0.92 0.02 20); + --muted: oklch(0.285 0.045 18); + --muted-foreground: oklch(0.7 0.03 20); + --accent: oklch(0.33 0.055 18); + --accent-foreground: oklch(0.9 0.03 22); + --destructive: oklch(0.7 0.17 25); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 14%); + --ring: oklch(0.72 0.11 20); + --lane: oklch(1 0 0 / 6%); + --chart-1: oklch(0.78 0.09 20); + --chart-2: oklch(0.66 0.11 18); + --chart-3: oklch(0.54 0.12 16); + --chart-4: oklch(0.44 0.1 15); + --chart-5: oklch(0.34 0.08 18); + --radius: 0.85rem; + --sidebar: oklch(0.225 0.045 18); + --sidebar-foreground: oklch(0.92 0.02 20); + --sidebar-primary: oklch(0.74 0.13 20); + --sidebar-primary-foreground: oklch(0.2 0.05 15); + --sidebar-accent: oklch(0.33 0.055 18); + --sidebar-accent-foreground: oklch(0.9 0.03 22); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.72 0.11 20); +} + @layer base { * { @apply border-border outline-ring/50; diff --git a/app/layout.tsx b/app/layout.tsx index 1e41757..f324fe6 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -57,14 +57,15 @@ export default function RootLayout({ children }: LayoutProps<"/">) { suppressHydrationWarning > - {/* Four looks: Default (calm light), Sunset (warm light), Dark, Ocean - (deep blue-green) -- complete token sets in app/globals.css. - "system" resolves to Default/Dark by OS preference. - No-FOUC theme restore: runs before first paint, applies the - stored preference to (class + color-scheme). */} + {/* Fourteen looks: seven light (Default, Sunset, Meadow, Honey, + Rosé, Lavender, Slate) and seven dark (Dark, Ocean, Pine, Plum, + Midnight, Ember, Rosewood) -- complete token sets in + app/globals.css. "system" resolves to Default/Dark by OS + preference. No-FOUC theme restore: runs before first paint, + applies the stored preference to (class + color-scheme). */}