Files
Calbook/lib/ui-appearance.ts

814 lines
28 KiB
TypeScript

export type UiThemePalette = {
background: string;
foreground: string;
card: string;
cardForeground: string;
popover: string;
popoverForeground: string;
primary: string;
primaryForeground: string;
secondary: string;
secondaryForeground: string;
muted: string;
mutedForeground: string;
accent: string;
accentForeground: string;
destructive: string;
destructiveForeground: string;
border: string;
input: string;
ring: string;
glow1: string;
glow2: string;
backgroundImage: string;
surfaceShadow: string;
};
export type UiThemePreset = {
id: string;
name: string;
description: string;
radius: string;
recommendedFonts: {
body: string;
heading: string;
};
light: UiThemePalette;
dark: UiThemePalette;
};
export type UiFontOption = {
id: string;
name: string;
cssStack: string;
};
export const UI_FONT_OPTIONS: UiFontOption[] = [
{
id: "font:manrope",
name: "Manrope",
cssStack: 'var(--font-manrope), "Segoe UI", "Helvetica Neue", Arial, sans-serif'
},
{
id: "font:sora",
name: "Sora",
cssStack: 'var(--font-sora), "Segoe UI", "Helvetica Neue", Arial, sans-serif'
},
{
id: "font:inter",
name: "Inter",
cssStack: 'var(--font-inter), "Segoe UI", "Helvetica Neue", Arial, sans-serif'
},
{
id: "font:outfit",
name: "Outfit",
cssStack: 'var(--font-outfit), "Segoe UI", "Helvetica Neue", Arial, sans-serif'
},
{
id: "font:space-grotesk",
name: "Space Grotesk",
cssStack:
'var(--font-space-grotesk), "Segoe UI", "Helvetica Neue", Arial, sans-serif'
},
{
id: "font:system-sans",
name: "System Sans",
cssStack:
'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif'
},
{
id: "font:ui-rounded",
name: "UI Rounded",
cssStack:
'"Arial Rounded MT Bold", "Trebuchet MS", "Segoe UI", "Helvetica Neue", Arial, sans-serif'
},
{
id: "font:georgia",
name: "Georgia Serif",
cssStack: 'Georgia, "Times New Roman", serif'
},
{
id: "font:cambria",
name: "Cambria Serif",
cssStack: 'Cambria, "Times New Roman", serif'
},
{
id: "font:mono",
name: "Modern Mono",
cssStack:
'"SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", monospace'
}
];
const BASE_LIGHT: UiThemePalette = {
background: "230 33% 99%",
foreground: "229 40% 15%",
card: "0 0% 100%",
cardForeground: "229 40% 15%",
popover: "0 0% 100%",
popoverForeground: "229 40% 15%",
primary: "248 85% 60%",
primaryForeground: "0 0% 100%",
secondary: "230 30% 96%",
secondaryForeground: "229 40% 20%",
muted: "228 25% 94%",
mutedForeground: "227 12% 40%",
accent: "248 80% 96%",
accentForeground: "248 55% 35%",
destructive: "0 84% 60%",
destructiveForeground: "0 0% 100%",
border: "230 20% 88%",
input: "230 20% 88%",
ring: "248 85% 60%",
glow1: "248 85% 60%",
glow2: "234 80% 72%",
backgroundImage:
"radial-gradient(circle at 15% -20%, hsl(248 85% 60% / 0.16) 0%, transparent 40%), radial-gradient(circle at 85% -15%, hsl(234 80% 72% / 0.12) 0%, transparent 35%), linear-gradient(180deg, hsl(230 33% 99%) 0%, hsl(228 29% 97%) 100%)",
surfaceShadow: "0 12px 34px rgba(30, 41, 59, 0.08)"
};
const BASE_DARK: UiThemePalette = {
background: "224 28% 10%",
foreground: "220 17% 97%",
card: "223 25% 14%",
cardForeground: "220 17% 97%",
popover: "223 25% 14%",
popoverForeground: "220 17% 97%",
primary: "247 78% 69%",
primaryForeground: "230 35% 11%",
secondary: "225 18% 18%",
secondaryForeground: "220 17% 95%",
muted: "225 12% 20%",
mutedForeground: "225 10% 70%",
accent: "245 45% 25%",
accentForeground: "220 17% 97%",
destructive: "0 62% 48%",
destructiveForeground: "220 17% 95%",
border: "225 15% 24%",
input: "225 15% 24%",
ring: "247 78% 69%",
glow1: "247 78% 69%",
glow2: "265 78% 66%",
backgroundImage:
"radial-gradient(circle at 20% -10%, hsl(247 78% 69% / 0.22) 0%, transparent 42%), radial-gradient(circle at 80% -20%, hsl(265 78% 66% / 0.2) 0%, transparent 36%), linear-gradient(180deg, hsl(224 28% 10%) 0%, hsl(228 22% 8%) 100%)",
surfaceShadow: "0 22px 44px rgba(2, 6, 23, 0.42)"
};
function mode(
base: UiThemePalette,
overrides: Partial<UiThemePalette>
): UiThemePalette {
return {
...base,
...overrides
};
}
export const UI_THEME_PRESETS: UiThemePreset[] = [
{
id: "theme:calbook-classic",
name: "CalBook Classic",
description: "Sauber, hell und ausgewogen mit Indigo-Akzenten.",
radius: "1rem",
recommendedFonts: {
body: "font:manrope",
heading: "font:sora"
},
light: mode(BASE_LIGHT, {}),
dark: mode(BASE_DARK, {})
},
{
id: "theme:aurora-glass",
name: "Aurora Glass",
description: "Transluzente Farbflächen mit Aurora-Stimmung.",
radius: "1.25rem",
recommendedFonts: {
body: "font:outfit",
heading: "font:space-grotesk"
},
light: mode(BASE_LIGHT, {
background: "198 85% 98%",
foreground: "218 42% 16%",
card: "0 0% 100%",
cardForeground: "218 42% 16%",
primary: "271 82% 57%",
primaryForeground: "0 0% 100%",
secondary: "203 64% 94%",
secondaryForeground: "218 35% 22%",
muted: "205 46% 91%",
mutedForeground: "218 14% 40%",
accent: "280 92% 90%",
accentForeground: "271 56% 29%",
border: "207 34% 86%",
input: "207 34% 86%",
ring: "271 82% 57%",
glow1: "271 82% 57%",
glow2: "188 88% 58%",
backgroundImage:
"radial-gradient(circle at 8% -15%, hsl(271 82% 57% / 0.33) 0%, transparent 40%), radial-gradient(circle at 86% -18%, hsl(188 88% 58% / 0.32) 0%, transparent 38%), linear-gradient(165deg, hsl(198 85% 98%) 0%, hsl(210 75% 96%) 52%, hsl(280 76% 96%) 100%)",
surfaceShadow: "0 18px 42px rgba(76, 29, 149, 0.16)"
}),
dark: mode(BASE_DARK, {
background: "228 30% 9%",
foreground: "217 32% 95%",
card: "229 32% 13%",
cardForeground: "217 32% 95%",
primary: "279 90% 70%",
primaryForeground: "227 32% 12%",
secondary: "224 20% 19%",
secondaryForeground: "217 24% 90%",
muted: "225 16% 22%",
mutedForeground: "217 12% 70%",
accent: "227 44% 28%",
accentForeground: "217 32% 95%",
border: "224 14% 28%",
input: "224 14% 28%",
ring: "279 90% 70%",
glow1: "279 90% 70%",
glow2: "188 82% 58%",
backgroundImage:
"radial-gradient(circle at 12% -10%, hsl(279 90% 70% / 0.34) 0%, transparent 42%), radial-gradient(circle at 90% -15%, hsl(188 82% 58% / 0.28) 0%, transparent 38%), linear-gradient(160deg, hsl(228 30% 9%) 0%, hsl(225 26% 10%) 46%, hsl(249 24% 12%) 100%)",
surfaceShadow: "0 24px 52px rgba(7, 12, 30, 0.5)"
})
},
{
id: "theme:neo-brutal",
name: "Neo Brutal",
description: "Knallige Kontraste, feste Kanten und plakative Farben.",
radius: "0.4rem",
recommendedFonts: {
body: "font:mono",
heading: "font:space-grotesk"
},
light: mode(BASE_LIGHT, {
background: "54 100% 95%",
foreground: "247 56% 13%",
card: "0 0% 100%",
cardForeground: "247 56% 13%",
primary: "247 100% 52%",
primaryForeground: "60 100% 96%",
secondary: "334 100% 88%",
secondaryForeground: "247 56% 13%",
muted: "192 100% 85%",
mutedForeground: "247 32% 28%",
accent: "115 100% 72%",
accentForeground: "247 56% 13%",
border: "247 100% 24%",
input: "247 100% 24%",
ring: "247 100% 52%",
glow1: "247 100% 52%",
glow2: "334 100% 57%",
backgroundImage:
"linear-gradient(135deg, hsl(54 100% 95%) 0%, hsl(54 100% 95%) 40%, hsl(334 100% 90%) 40%, hsl(334 100% 90%) 55%, hsl(192 100% 88%) 55%, hsl(192 100% 88%) 100%)",
surfaceShadow: "8px 8px 0 rgba(37, 18, 152, 0.24)"
}),
dark: mode(BASE_DARK, {
background: "248 30% 8%",
foreground: "60 85% 96%",
card: "247 36% 14%",
cardForeground: "60 85% 96%",
primary: "60 100% 62%",
primaryForeground: "247 36% 12%",
secondary: "334 92% 40%",
secondaryForeground: "60 85% 96%",
muted: "204 84% 32%",
mutedForeground: "60 50% 78%",
accent: "114 74% 38%",
accentForeground: "60 85% 96%",
border: "60 100% 62%",
input: "60 100% 62%",
ring: "60 100% 62%",
glow1: "60 100% 62%",
glow2: "334 95% 56%",
backgroundImage:
"linear-gradient(135deg, hsl(248 30% 8%) 0%, hsl(248 30% 8%) 44%, hsl(334 92% 30%) 44%, hsl(334 92% 30%) 58%, hsl(204 84% 24%) 58%, hsl(204 84% 24%) 100%)",
surfaceShadow: "10px 10px 0 rgba(251, 255, 95, 0.28)"
})
},
{
id: "theme:midnight-cinema",
name: "Midnight Cinema",
description: "Dunkler Editorial-Look mit Gold und sattem Schwarz.",
radius: "0.85rem",
recommendedFonts: {
body: "font:georgia",
heading: "font:cambria"
},
light: mode(BASE_LIGHT, {
background: "36 35% 97%",
foreground: "226 22% 14%",
card: "0 0% 100%",
cardForeground: "226 22% 14%",
primary: "41 86% 48%",
primaryForeground: "226 22% 13%",
secondary: "32 40% 93%",
secondaryForeground: "226 18% 22%",
muted: "33 28% 91%",
mutedForeground: "226 10% 42%",
accent: "42 84% 84%",
accentForeground: "226 30% 26%",
border: "33 20% 82%",
input: "33 20% 82%",
ring: "41 86% 48%",
glow1: "41 86% 48%",
glow2: "221 44% 36%",
backgroundImage:
"radial-gradient(circle at 50% -35%, hsl(41 86% 48% / 0.32) 0%, transparent 45%), linear-gradient(180deg, hsl(36 35% 97%) 0%, hsl(29 28% 92%) 100%)",
surfaceShadow: "0 18px 42px rgba(28, 25, 23, 0.16)"
}),
dark: mode(BASE_DARK, {
background: "231 24% 8%",
foreground: "40 45% 92%",
card: "230 22% 12%",
cardForeground: "40 45% 92%",
primary: "41 90% 60%",
primaryForeground: "230 24% 13%",
secondary: "230 14% 18%",
secondaryForeground: "40 30% 88%",
muted: "231 10% 22%",
mutedForeground: "39 14% 68%",
accent: "229 24% 27%",
accentForeground: "40 45% 92%",
border: "230 10% 26%",
input: "230 10% 26%",
ring: "41 90% 60%",
glow1: "41 90% 60%",
glow2: "224 64% 58%",
backgroundImage:
"radial-gradient(circle at 50% -30%, hsl(41 90% 60% / 0.28) 0%, transparent 42%), linear-gradient(180deg, hsl(231 24% 8%) 0%, hsl(231 22% 7%) 48%, hsl(225 30% 10%) 100%)",
surfaceShadow: "0 30px 58px rgba(0, 0, 0, 0.55)"
})
},
{
id: "theme:citrus-pop",
name: "Citrus Pop",
description: "Frisches Orange/Lime-Theme mit viel Energie.",
radius: "1.3rem",
recommendedFonts: {
body: "font:ui-rounded",
heading: "font:outfit"
},
light: mode(BASE_LIGHT, {
background: "56 100% 96%",
foreground: "148 56% 16%",
card: "0 0% 100%",
cardForeground: "148 56% 16%",
primary: "25 96% 54%",
primaryForeground: "0 0% 100%",
secondary: "94 86% 90%",
secondaryForeground: "148 50% 21%",
muted: "71 66% 90%",
mutedForeground: "148 16% 38%",
accent: "36 98% 84%",
accentForeground: "148 56% 20%",
border: "74 32% 80%",
input: "74 32% 80%",
ring: "25 96% 54%",
glow1: "25 96% 54%",
glow2: "98 84% 48%",
backgroundImage:
"radial-gradient(circle at 14% -20%, hsl(25 96% 54% / 0.34) 0%, transparent 42%), radial-gradient(circle at 90% -10%, hsl(98 84% 48% / 0.3) 0%, transparent 38%), linear-gradient(180deg, hsl(56 100% 96%) 0%, hsl(73 84% 92%) 100%)",
surfaceShadow: "0 16px 40px rgba(82, 126, 32, 0.2)"
}),
dark: mode(BASE_DARK, {
background: "136 25% 10%",
foreground: "58 70% 94%",
card: "136 20% 14%",
cardForeground: "58 70% 94%",
primary: "27 100% 62%",
primaryForeground: "137 32% 12%",
secondary: "92 48% 22%",
secondaryForeground: "58 70% 90%",
muted: "102 24% 20%",
mutedForeground: "70 20% 70%",
accent: "33 56% 30%",
accentForeground: "58 70% 94%",
border: "108 16% 28%",
input: "108 16% 28%",
ring: "27 100% 62%",
glow1: "27 100% 62%",
glow2: "96 86% 56%",
backgroundImage:
"radial-gradient(circle at 12% -18%, hsl(27 100% 62% / 0.34) 0%, transparent 42%), radial-gradient(circle at 85% -15%, hsl(96 86% 56% / 0.22) 0%, transparent 36%), linear-gradient(180deg, hsl(136 25% 10%) 0%, hsl(128 28% 9%) 100%)",
surfaceShadow: "0 24px 50px rgba(12, 32, 11, 0.58)"
})
},
{
id: "theme:rose-paper",
name: "Rose Paper",
description: "Softes Editorial-Theme mit Papier-Charakter.",
radius: "1.45rem",
recommendedFonts: {
body: "font:cambria",
heading: "font:georgia"
},
light: mode(BASE_LIGHT, {
background: "15 72% 97%",
foreground: "341 34% 20%",
card: "20 45% 99%",
cardForeground: "341 34% 20%",
popover: "20 45% 99%",
popoverForeground: "341 34% 20%",
primary: "343 74% 56%",
primaryForeground: "0 0% 100%",
secondary: "17 55% 93%",
secondaryForeground: "341 30% 26%",
muted: "16 38% 90%",
mutedForeground: "339 15% 42%",
accent: "334 82% 88%",
accentForeground: "339 50% 30%",
border: "13 24% 84%",
input: "13 24% 84%",
ring: "343 74% 56%",
glow1: "343 74% 56%",
glow2: "24 90% 70%",
backgroundImage:
"radial-gradient(circle at 12% -18%, hsl(343 74% 56% / 0.26) 0%, transparent 38%), radial-gradient(circle at 94% -18%, hsl(24 90% 70% / 0.24) 0%, transparent 36%), linear-gradient(180deg, hsl(15 72% 97%) 0%, hsl(20 60% 94%) 100%)",
surfaceShadow: "0 14px 38px rgba(138, 63, 87, 0.18)"
}),
dark: mode(BASE_DARK, {
background: "336 24% 11%",
foreground: "21 40% 94%",
card: "336 21% 14%",
cardForeground: "21 40% 94%",
primary: "343 78% 66%",
primaryForeground: "337 28% 13%",
secondary: "338 14% 20%",
secondaryForeground: "21 28% 89%",
muted: "337 12% 23%",
mutedForeground: "21 12% 69%",
accent: "341 27% 30%",
accentForeground: "21 40% 94%",
border: "338 11% 27%",
input: "338 11% 27%",
ring: "343 78% 66%",
glow1: "343 78% 66%",
glow2: "24 82% 65%",
backgroundImage:
"radial-gradient(circle at 12% -15%, hsl(343 78% 66% / 0.32) 0%, transparent 40%), radial-gradient(circle at 88% -18%, hsl(24 82% 65% / 0.22) 0%, transparent 35%), linear-gradient(180deg, hsl(336 24% 11%) 0%, hsl(334 20% 10%) 100%)",
surfaceShadow: "0 26px 52px rgba(38, 14, 25, 0.58)"
})
},
{
id: "theme:cyber-lime",
name: "Cyber Lime",
description: "Techno-Look mit Neon-Lime und dunklem Untergrund.",
radius: "0.7rem",
recommendedFonts: {
body: "font:mono",
heading: "font:space-grotesk"
},
light: mode(BASE_LIGHT, {
background: "80 90% 96%",
foreground: "216 26% 12%",
card: "0 0% 100%",
cardForeground: "216 26% 12%",
primary: "128 82% 40%",
primaryForeground: "0 0% 100%",
secondary: "203 84% 90%",
secondaryForeground: "214 35% 22%",
muted: "82 60% 90%",
mutedForeground: "214 12% 38%",
accent: "190 88% 85%",
accentForeground: "214 48% 28%",
border: "121 32% 78%",
input: "121 32% 78%",
ring: "128 82% 40%",
glow1: "128 82% 40%",
glow2: "191 90% 48%",
backgroundImage:
"linear-gradient(120deg, hsl(80 90% 96%) 0%, hsl(80 90% 96%) 44%, hsl(190 88% 88%) 44%, hsl(190 88% 88%) 58%, hsl(123 74% 85%) 58%, hsl(123 74% 85%) 100%)",
surfaceShadow: "0 16px 34px rgba(22, 101, 52, 0.22)"
}),
dark: mode(BASE_DARK, {
background: "214 35% 8%",
foreground: "111 42% 92%",
card: "214 30% 12%",
cardForeground: "111 42% 92%",
primary: "95 94% 56%",
primaryForeground: "214 38% 11%",
secondary: "190 58% 20%",
secondaryForeground: "111 42% 88%",
muted: "212 22% 19%",
mutedForeground: "111 14% 68%",
accent: "206 42% 28%",
accentForeground: "111 42% 92%",
border: "204 16% 24%",
input: "204 16% 24%",
ring: "95 94% 56%",
glow1: "95 94% 56%",
glow2: "190 88% 52%",
backgroundImage:
"linear-gradient(135deg, hsl(214 35% 8%) 0%, hsl(214 35% 8%) 46%, hsl(200 70% 18%) 46%, hsl(200 70% 18%) 58%, hsl(96 56% 20%) 58%, hsl(96 56% 20%) 100%)",
surfaceShadow: "0 22px 50px rgba(2, 15, 21, 0.62)"
})
},
{
id: "theme:desert-editorial",
name: "Desert Editorial",
description: "Sandige Töne, elegante Serif-Kombination, ruhiger Look.",
radius: "1.1rem",
recommendedFonts: {
body: "font:georgia",
heading: "font:cambria"
},
light: mode(BASE_LIGHT, {
background: "39 52% 95%",
foreground: "22 35% 22%",
card: "33 45% 98%",
cardForeground: "22 35% 22%",
popover: "33 45% 98%",
popoverForeground: "22 35% 22%",
primary: "22 75% 52%",
primaryForeground: "0 0% 100%",
secondary: "32 42% 90%",
secondaryForeground: "24 33% 28%",
muted: "36 30% 88%",
mutedForeground: "26 14% 42%",
accent: "46 72% 82%",
accentForeground: "26 40% 28%",
border: "31 23% 80%",
input: "31 23% 80%",
ring: "22 75% 52%",
glow1: "22 75% 52%",
glow2: "46 80% 58%",
backgroundImage:
"radial-gradient(circle at 12% -16%, hsl(22 75% 52% / 0.24) 0%, transparent 38%), radial-gradient(circle at 84% -20%, hsl(46 80% 58% / 0.2) 0%, transparent 35%), linear-gradient(180deg, hsl(39 52% 95%) 0%, hsl(35 36% 90%) 100%)",
surfaceShadow: "0 14px 36px rgba(93, 63, 33, 0.19)"
}),
dark: mode(BASE_DARK, {
background: "25 28% 11%",
foreground: "36 36% 92%",
card: "25 24% 14%",
cardForeground: "36 36% 92%",
primary: "29 86% 62%",
primaryForeground: "24 34% 14%",
secondary: "27 18% 20%",
secondaryForeground: "36 24% 88%",
muted: "26 14% 23%",
mutedForeground: "34 10% 69%",
accent: "29 30% 30%",
accentForeground: "36 36% 92%",
border: "27 12% 27%",
input: "27 12% 27%",
ring: "29 86% 62%",
glow1: "29 86% 62%",
glow2: "47 75% 56%",
backgroundImage:
"radial-gradient(circle at 16% -16%, hsl(29 86% 62% / 0.3) 0%, transparent 40%), radial-gradient(circle at 88% -18%, hsl(47 75% 56% / 0.2) 0%, transparent 34%), linear-gradient(180deg, hsl(25 28% 11%) 0%, hsl(28 24% 9%) 100%)",
surfaceShadow: "0 24px 50px rgba(23, 15, 8, 0.62)"
})
},
{
id: "theme:oceanic-neon",
name: "Oceanic Neon",
description: "Aquatischer Neon-Kontrast mit leuchtenden Akzenten.",
radius: "1.2rem",
recommendedFonts: {
body: "font:inter",
heading: "font:space-grotesk"
},
light: mode(BASE_LIGHT, {
background: "191 100% 97%",
foreground: "214 45% 16%",
card: "0 0% 100%",
cardForeground: "214 45% 16%",
primary: "196 92% 46%",
primaryForeground: "0 0% 100%",
secondary: "176 72% 90%",
secondaryForeground: "210 44% 23%",
muted: "189 48% 90%",
mutedForeground: "214 14% 40%",
accent: "236 94% 88%",
accentForeground: "225 50% 32%",
border: "190 26% 82%",
input: "190 26% 82%",
ring: "196 92% 46%",
glow1: "196 92% 46%",
glow2: "236 94% 64%",
backgroundImage:
"radial-gradient(circle at 10% -22%, hsl(196 92% 46% / 0.3) 0%, transparent 40%), radial-gradient(circle at 92% -10%, hsl(236 94% 64% / 0.22) 0%, transparent 35%), linear-gradient(170deg, hsl(191 100% 97%) 0%, hsl(202 82% 93%) 100%)",
surfaceShadow: "0 18px 42px rgba(24, 70, 132, 0.2)"
}),
dark: mode(BASE_DARK, {
background: "215 36% 9%",
foreground: "186 50% 94%",
card: "214 30% 13%",
cardForeground: "186 50% 94%",
primary: "186 94% 58%",
primaryForeground: "215 38% 12%",
secondary: "214 18% 20%",
secondaryForeground: "186 36% 89%",
muted: "214 14% 23%",
mutedForeground: "186 12% 70%",
accent: "231 34% 30%",
accentForeground: "186 50% 94%",
border: "214 13% 27%",
input: "214 13% 27%",
ring: "186 94% 58%",
glow1: "186 94% 58%",
glow2: "236 95% 64%",
backgroundImage:
"radial-gradient(circle at 8% -15%, hsl(186 94% 58% / 0.3) 0%, transparent 40%), radial-gradient(circle at 94% -20%, hsl(236 95% 64% / 0.24) 0%, transparent 35%), linear-gradient(180deg, hsl(215 36% 9%) 0%, hsl(222 32% 9%) 100%)",
surfaceShadow: "0 26px 56px rgba(3, 10, 25, 0.62)"
})
},
{
id: "theme:monochrome-ink",
name: "Monochrome Ink",
description: "Schwarz/Weiß mit redaktioneller Klarheit und hoher Ruhe.",
radius: "0.65rem",
recommendedFonts: {
body: "font:system-sans",
heading: "font:mono"
},
light: mode(BASE_LIGHT, {
background: "0 0% 97%",
foreground: "0 0% 11%",
card: "0 0% 100%",
cardForeground: "0 0% 11%",
primary: "0 0% 12%",
primaryForeground: "0 0% 100%",
secondary: "0 0% 92%",
secondaryForeground: "0 0% 18%",
muted: "0 0% 90%",
mutedForeground: "0 0% 38%",
accent: "0 0% 86%",
accentForeground: "0 0% 18%",
destructive: "2 80% 54%",
border: "0 0% 80%",
input: "0 0% 80%",
ring: "0 0% 12%",
glow1: "0 0% 28%",
glow2: "0 0% 52%",
backgroundImage:
"linear-gradient(180deg, hsl(0 0% 97%) 0%, hsl(0 0% 92%) 100%)",
surfaceShadow: "0 10px 22px rgba(0, 0, 0, 0.12)"
}),
dark: mode(BASE_DARK, {
background: "0 0% 7%",
foreground: "0 0% 94%",
card: "0 0% 11%",
cardForeground: "0 0% 94%",
primary: "0 0% 94%",
primaryForeground: "0 0% 10%",
secondary: "0 0% 17%",
secondaryForeground: "0 0% 90%",
muted: "0 0% 20%",
mutedForeground: "0 0% 68%",
accent: "0 0% 28%",
accentForeground: "0 0% 94%",
destructive: "2 68% 50%",
border: "0 0% 24%",
input: "0 0% 24%",
ring: "0 0% 94%",
glow1: "0 0% 80%",
glow2: "0 0% 40%",
backgroundImage:
"linear-gradient(180deg, hsl(0 0% 7%) 0%, hsl(0 0% 5%) 100%)",
surfaceShadow: "0 20px 44px rgba(0, 0, 0, 0.66)"
})
},
{
id: "theme:monochrome-ink-glass",
name: "Monochrome Ink Liquid Glass",
description:
"Monochrome-Variante mit sanftem Gradient und Liquid-Glass-Flächen.",
radius: "1rem",
recommendedFonts: {
body: "font:system-sans",
heading: "font:mono"
},
light: mode(BASE_LIGHT, {
background: "210 18% 96%",
foreground: "215 18% 14%",
card: "0 0% 100% / 0.62",
cardForeground: "215 18% 14%",
popover: "0 0% 100% / 0.72",
popoverForeground: "215 18% 14%",
primary: "0 0% 14%",
primaryForeground: "0 0% 100%",
secondary: "0 0% 100% / 0.46",
secondaryForeground: "216 18% 20%",
muted: "212 14% 88% / 0.58",
mutedForeground: "216 8% 38%",
accent: "218 30% 86% / 0.65",
accentForeground: "216 22% 22%",
destructive: "2 78% 54%",
border: "0 0% 100% / 0.56",
input: "0 0% 100% / 0.64",
ring: "215 18% 24%",
glow1: "217 36% 72%",
glow2: "204 60% 86%",
backgroundImage:
"radial-gradient(circle at 14% -22%, hsl(217 36% 72% / 0.42) 0%, transparent 42%), radial-gradient(circle at 88% -18%, hsl(204 60% 86% / 0.46) 0%, transparent 38%), linear-gradient(165deg, hsl(210 18% 96%) 0%, hsl(211 20% 92%) 52%, hsl(218 20% 94%) 100%)",
surfaceShadow:
"0 18px 46px rgba(15, 23, 42, 0.16), inset 0 1px 0 rgba(255, 255, 255, 0.52)"
}),
dark: mode(BASE_DARK, {
background: "222 24% 10%",
foreground: "215 24% 94%",
card: "220 20% 18% / 0.56",
cardForeground: "215 24% 94%",
popover: "220 20% 16% / 0.72",
popoverForeground: "215 24% 94%",
primary: "0 0% 96%",
primaryForeground: "220 24% 12%",
secondary: "220 18% 24% / 0.5",
secondaryForeground: "215 20% 90%",
muted: "220 14% 20% / 0.58",
mutedForeground: "215 10% 70%",
accent: "220 26% 30% / 0.62",
accentForeground: "215 24% 94%",
destructive: "2 68% 50%",
border: "0 0% 100% / 0.2",
input: "0 0% 100% / 0.26",
ring: "0 0% 96%",
glow1: "217 18% 58%",
glow2: "205 26% 38%",
backgroundImage:
"radial-gradient(circle at 16% -18%, hsl(217 18% 58% / 0.34) 0%, transparent 42%), radial-gradient(circle at 86% -20%, hsl(205 26% 38% / 0.3) 0%, transparent 38%), linear-gradient(170deg, hsl(222 24% 10%) 0%, hsl(220 24% 9%) 52%, hsl(224 22% 8%) 100%)",
surfaceShadow:
"0 28px 58px rgba(2, 6, 23, 0.62), inset 0 1px 0 rgba(255, 255, 255, 0.12)"
})
}
];
export function getUiThemePresetById(themeId?: string) {
return (
UI_THEME_PRESETS.find((theme) => theme.id === themeId) ??
UI_THEME_PRESETS[0]!
);
}
export function getUiFontOptionById(fontId?: string) {
return (
UI_FONT_OPTIONS.find((font) => font.id === fontId) ??
UI_FONT_OPTIONS[0]!
);
}
export function buildUiAppearanceStyle(input?: {
themeId?: string;
bodyFontId?: string;
headingFontId?: string;
}) {
const theme = getUiThemePresetById(input?.themeId);
const bodyFont = getUiFontOptionById(input?.bodyFontId);
const headingFont = getUiFontOptionById(input?.headingFontId);
return {
"--font-body": bodyFont.cssStack,
"--font-heading": headingFont.cssStack,
"--radius": theme.radius,
"--theme-light-background": theme.light.background,
"--theme-light-foreground": theme.light.foreground,
"--theme-light-card": theme.light.card,
"--theme-light-card-foreground": theme.light.cardForeground,
"--theme-light-popover": theme.light.popover,
"--theme-light-popover-foreground": theme.light.popoverForeground,
"--theme-light-primary": theme.light.primary,
"--theme-light-primary-foreground": theme.light.primaryForeground,
"--theme-light-secondary": theme.light.secondary,
"--theme-light-secondary-foreground": theme.light.secondaryForeground,
"--theme-light-muted": theme.light.muted,
"--theme-light-muted-foreground": theme.light.mutedForeground,
"--theme-light-accent": theme.light.accent,
"--theme-light-accent-foreground": theme.light.accentForeground,
"--theme-light-destructive": theme.light.destructive,
"--theme-light-destructive-foreground": theme.light.destructiveForeground,
"--theme-light-border": theme.light.border,
"--theme-light-input": theme.light.input,
"--theme-light-ring": theme.light.ring,
"--theme-light-glow-1": theme.light.glow1,
"--theme-light-glow-2": theme.light.glow2,
"--theme-light-bg-image": theme.light.backgroundImage,
"--theme-light-surface-shadow": theme.light.surfaceShadow,
"--theme-dark-background": theme.dark.background,
"--theme-dark-foreground": theme.dark.foreground,
"--theme-dark-card": theme.dark.card,
"--theme-dark-card-foreground": theme.dark.cardForeground,
"--theme-dark-popover": theme.dark.popover,
"--theme-dark-popover-foreground": theme.dark.popoverForeground,
"--theme-dark-primary": theme.dark.primary,
"--theme-dark-primary-foreground": theme.dark.primaryForeground,
"--theme-dark-secondary": theme.dark.secondary,
"--theme-dark-secondary-foreground": theme.dark.secondaryForeground,
"--theme-dark-muted": theme.dark.muted,
"--theme-dark-muted-foreground": theme.dark.mutedForeground,
"--theme-dark-accent": theme.dark.accent,
"--theme-dark-accent-foreground": theme.dark.accentForeground,
"--theme-dark-destructive": theme.dark.destructive,
"--theme-dark-destructive-foreground": theme.dark.destructiveForeground,
"--theme-dark-border": theme.dark.border,
"--theme-dark-input": theme.dark.input,
"--theme-dark-ring": theme.dark.ring,
"--theme-dark-glow-1": theme.dark.glow1,
"--theme-dark-glow-2": theme.dark.glow2,
"--theme-dark-bg-image": theme.dark.backgroundImage,
"--theme-dark-surface-shadow": theme.dark.surfaceShadow
} as Record<string, string>;
}