feat: full palette themes for DaisyUI and HeroUI marketing scaffolds

DaisyUI scaffold now has 12 named themes (Dark, Light, Cupcake, Bee,
Synthwave, Cyberpunk, Retro, Dracula, Night, Forest, Coffee, Winter).
Each theme changes the page background, card bg, text, borders, and
primary color — swatch shows a split circle of bg+primary so you can
preview the full palette at a glance.

HeroUI marketing scaffold has 6 prebuilt themes (Purple, Blue, Teal,
Rose, Dark, Modern) matching heroui.com/themes.

ThemeColor type now supports optional bg/cardBg/textColor/borderColor/
mutedText fields for full-page dark/light palette overrides.

Made-with: Cursor
This commit is contained in:
2026-03-02 13:58:02 -08:00
parent 817fe3a1a4
commit 16766f587d

View File

@@ -35,6 +35,12 @@ export interface ThemeColor {
activeBg: string; // sidebar active item bg
activeFg: string; // sidebar active item text
ring: string; // focus ring / subtle tint
// optional full-page palette (used by DaisyUI & dark themes)
bg?: string;
cardBg?: string;
textColor?: string;
borderColor?: string;
mutedText?: string;
}
export const SHADCN_THEMES: ThemeColor[] = [
@@ -65,6 +71,22 @@ export const HEROUI_THEMES: ThemeColor[] = [
{ id: "orange", label: "Orange", primary: "#ea580c", primaryFg: "#fff", activeBg: "rgba(234,88,12,0.3)", activeFg: "#fdba74", ring: "rgba(249,115,22,0.3)" },
];
// DaisyUI named themes — each has a full page palette
export const DAISY_THEMES: ThemeColor[] = [
{ id: "dark", label: "Dark", primary: "#793ef9", primaryFg: "#fff", activeBg: "rgba(121,62,249,0.2)", activeFg: "#a78bfa", ring: "#4c1d95", bg: "#1d232a", cardBg: "#191e24", textColor: "#a6adba", borderColor: "#2a323c", mutedText: "#6b7280" },
{ id: "light", label: "Light", primary: "#570df8", primaryFg: "#fff", activeBg: "#f3f0ff", activeFg: "#4c1d95", ring: "#ddd6fe", bg: "#fff", cardBg: "#fff", textColor: "#1f2937", borderColor: "#e5e7eb", mutedText: "#6b7280" },
{ id: "cupcake", label: "Cupcake", primary: "#65c3c8", primaryFg: "#291334", activeBg: "#d9f5f6", activeFg: "#0e6b70", ring: "#a7eaec", bg: "#faf7f5", cardBg: "#fff", textColor: "#291334", borderColor: "#e9e3df", mutedText: "#9ca3af" },
{ id: "bumblebee", label: "Bee", primary: "#e0a82e", primaryFg: "#1f2937", activeBg: "#fef9e5", activeFg: "#92650a", ring: "#fde68a", bg: "#fff", cardBg: "#fff", textColor: "#1f2937", borderColor: "#e5e7eb", mutedText: "#6b7280" },
{ id: "synthwave", label: "Synth", primary: "#e779c1", primaryFg: "#2d1b69", activeBg: "rgba(231,121,193,0.2)",activeFg: "#f0abdc", ring: "#701a75", bg: "#1a103c", cardBg: "#221551", textColor: "#e2e8f0", borderColor: "#4c3585", mutedText: "#a78bfa" },
{ id: "cyberpunk", label: "Cyber", primary: "#ff7598", primaryFg: "#1f2937", activeBg: "#fff0f3", activeFg: "#9d174d", ring: "#fca5a5", bg: "#ffee00", cardBg: "#fff", textColor: "#1f2937", borderColor: "#1f2937", mutedText: "#374151" },
{ id: "retro", label: "Retro", primary: "#ef9995", primaryFg: "#282425", activeBg: "#fde8e7", activeFg: "#7f1d1d", ring: "#fca5a5", bg: "#e4d8b4", cardBg: "#f7f0d8", textColor: "#282425", borderColor: "#d4b483", mutedText: "#6b5745" },
{ id: "dracula", label: "Dracula", primary: "#ff79c6", primaryFg: "#282a36", activeBg: "rgba(255,121,198,0.15)",activeFg: "#ff79c6",ring: "#bd93f9", bg: "#282a36", cardBg: "#343746", textColor: "#f8f8f2", borderColor: "#44475a", mutedText: "#6272a4" },
{ id: "night", label: "Night", primary: "#38bdf8", primaryFg: "#0c1a2b", activeBg: "rgba(56,189,248,0.15)",activeFg: "#38bdf8", ring: "#0284c7", bg: "#1d232a", cardBg: "#191e24", textColor: "#a6adba", borderColor: "#2a323c", mutedText: "#4b5563" },
{ id: "forest", label: "Forest", primary: "#1eb854", primaryFg: "#fff", activeBg: "rgba(30,184,84,0.15)", activeFg: "#1eb854", ring: "#15803d", bg: "#171212", cardBg: "#1d1d1d", textColor: "#d1d5db", borderColor: "#292929", mutedText: "#4b5563" },
{ id: "coffee", label: "Coffee", primary: "#db924b", primaryFg: "#20150e", activeBg: "rgba(219,146,75,0.15)",activeFg: "#db924b", ring: "#92400e", bg: "#20150e", cardBg: "#2a1c12", textColor: "#d1b59c", borderColor: "#3d261a", mutedText: "#78523a" },
{ id: "winter", label: "Winter", primary: "#047aed", primaryFg: "#fff", activeBg: "#e0f0ff", activeFg: "#0369a1", ring: "#bae6fd", bg: "#fff", cardBg: "#f0f9ff", textColor: "#1e3a5f", borderColor: "#bae6fd", mutedText: "#64748b" },
];
export const TREMOR_THEMES: ThemeColor[] = [
{ id: "blue", label: "Blue", primary: "#2563eb", primaryFg: "#fff", activeBg: "#eff6ff", activeFg: "#1d4ed8", ring: "#bfdbfe" },
{ id: "indigo", label: "Indigo", primary: "#4f46e5", primaryFg: "#fff", activeBg: "#eef2ff", activeFg: "#3730a3", ring: "#c7d2fe" },
@@ -80,15 +102,16 @@ function ThemeSwatches({ themes, selected, onSelect }: {
onSelect: (t: ThemeColor) => void;
}) {
return (
<div className="flex items-center gap-1">
<div className="flex items-center gap-1 flex-wrap">
{themes.map(t => (
<button
key={t.id}
title={t.label}
onClick={() => onSelect(t)}
className="w-4 h-4 rounded-full transition-transform hover:scale-110"
className="w-4 h-4 rounded-full transition-transform hover:scale-110 border"
style={{
background: t.primary,
background: t.bg ? `linear-gradient(135deg, ${t.bg} 50%, ${t.primary} 50%)` : t.primary,
borderColor: selected.id === t.id ? t.primary : "transparent",
outline: selected.id === t.id ? `2px solid ${t.primary}` : "none",
outlineOffset: 2,
}}
@@ -653,80 +676,128 @@ export function WebAppTremor() {
// ---------------------------------------------------------------------------
export function MarketingDaisy() {
const [theme, setTheme] = useState<ThemeColor>(DAISY_THEMES[0]);
const isDark = !!theme.bg && ["#1d232a","#282a36","#1a103c","#171212","#20150e","#ffee00"].includes(theme.bg) === false
? theme.bg.startsWith("#1") || theme.bg.startsWith("#2") || theme.bg === "#ffee00"
: false;
const textColor = theme.textColor ?? "#f8f8f2";
const mutedText = theme.mutedText ?? "rgba(255,255,255,0.5)";
const cardBg = theme.cardBg ?? "rgba(255,255,255,0.05)";
const borderColor = theme.borderColor ?? "rgba(255,255,255,0.1)";
const bg = theme.bg ?? "#1d232a";
return (
<div className="h-full font-sans" style={{ background:"#1d232a", color:"#a6adba" }}>
<nav className="flex items-center justify-between px-6 py-3" style={{ borderBottom:"1px solid rgba(255,255,255,0.1)" }}>
<div className="h-full font-sans" style={{ background: bg, color: textColor }}>
<nav className="flex items-center justify-between px-6 py-3" style={{ borderBottom:`1px solid ${borderColor}` }}>
<div className="flex items-center gap-2">
<div className="w-6 h-6 rounded" style={{ background:"#f59e0b" }} />
<span className="font-bold text-white text-sm">Acme</span>
<div className="w-6 h-6 rounded" style={{ background: theme.primary }} />
<span className="font-bold text-sm" style={{ color: textColor }}>Acme</span>
</div>
<div className="flex gap-4 text-xs" style={{ color:"rgba(255,255,255,0.6)" }}>
{["Features","Pricing","Docs","Blog"].map(i=><span key={i} className="cursor-pointer hover:text-white">{i}</span>)}
<div className="flex gap-4 text-xs" style={{ color: mutedText }}>
{["Features","Pricing","Docs","Blog"].map(i=><span key={i}>{i}</span>)}
</div>
<div className="flex gap-2">
<button className="h-7 px-3 rounded-full text-[11px] font-bold" style={{ background:"rgba(255,255,255,0.1)", color:"white" }}>Login</button>
<button className="h-7 px-3 rounded-full text-[11px] font-bold text-black" style={{ background:"#f59e0b" }}>Get started</button>
<div className="flex items-center gap-2">
<ThemeSwatches themes={DAISY_THEMES} selected={theme} onSelect={setTheme} />
<button className="h-7 px-3 rounded-full text-[11px] font-bold" style={{ background:`${borderColor}`, color: textColor }}>Login</button>
<button className="h-7 px-3 rounded-full text-[11px] font-bold" style={{ background: theme.primary, color: theme.primaryFg }}>Get started</button>
</div>
</nav>
<div className="px-10 pt-12 pb-6 text-center">
<div className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-[10px] font-bold mb-4" style={{ background:"rgba(245,158,11,0.15)", color:"#f59e0b", border:"1px solid rgba(245,158,11,0.3)" }}>
New v2.0 is here
<div className="px-10 pt-10 pb-6 text-center">
<div className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-[10px] font-bold mb-4" style={{ background:`${theme.primary}22`, color: theme.primary, border:`1px solid ${theme.primary}44` }}>
{theme.label} theme v2.0
</div>
<h1 className="text-2xl font-black text-white mb-2">Build faster,<br />ship smarter</h1>
<p className="text-xs mb-6" style={{ color:"rgba(255,255,255,0.5)", maxWidth:280, margin:"0 auto 20px" }}>The all-in-one platform that helps teams build, launch, and scale their products.</p>
<div className="flex gap-2 justify-center">
<button className="h-9 px-5 rounded-full text-xs font-bold text-black" style={{ background:"#f59e0b" }}>Start for free</button>
<button className="h-9 px-5 rounded-full text-xs font-bold" style={{ border:"1px solid rgba(255,255,255,0.2)", color:"white" }}>See demo </button>
<h1 className="text-2xl font-black mb-2" style={{ color: textColor }}>Build faster,<br />ship smarter</h1>
<p className="text-xs mb-6 mx-auto" style={{ color: mutedText, maxWidth:280 }}>The all-in-one platform that helps teams build, launch, and scale their products.</p>
<div className="flex gap-2 justify-center mb-6">
<button className="h-9 px-5 rounded-full text-xs font-bold" style={{ background: theme.primary, color: theme.primaryFg }}>Start for free</button>
<button className="h-9 px-5 rounded-full text-xs font-bold" style={{ border:`1px solid ${borderColor}`, color: textColor }}>See demo </button>
</div>
</div>
<div className="grid grid-cols-3 gap-3 px-8 mt-2">
<div className="grid grid-cols-3 gap-3 px-8">
{[{icon:"⚡",title:"Lightning fast",desc:"Deploy in seconds, not hours"},{icon:"🔒",title:"Secure by default",desc:"Enterprise-grade security built in"},{icon:"📈",title:"Scales with you",desc:"From zero to millions of users"}].map(f=>(
<div key={f.title} className="p-3 rounded-xl text-center" style={{ background:"rgba(255,255,255,0.05)", border:"1px solid rgba(255,255,255,0.08)" }}>
<div key={f.title} className="p-3 rounded-xl text-center" style={{ background: cardBg, border:`1px solid ${borderColor}` }}>
<div className="text-xl mb-1">{f.icon}</div>
<p className="text-[11px] font-bold text-white mb-0.5">{f.title}</p>
<p className="text-[10px]" style={{ color:"rgba(255,255,255,0.4)" }}>{f.desc}</p>
<p className="text-[11px] font-bold mb-0.5" style={{ color: textColor }}>{f.title}</p>
<p className="text-[10px]" style={{ color: mutedText }}>{f.desc}</p>
</div>
))}
</div>
<div className="px-8 mt-4">
<div className="rounded-xl p-4" style={{ background: cardBg, border:`1px solid ${borderColor}` }}>
<div className="flex items-center gap-3 mb-3">
<div className="flex-1 h-8 rounded-lg" style={{ background: borderColor }} />
<button className="h-8 px-3 rounded-lg text-[11px] font-bold" style={{ background: theme.primary, color: theme.primaryFg }}>Subscribe</button>
</div>
<div className="flex gap-2">
{["badge","badge-outline","badge-soft"].map((b,i)=>(
<span key={b} className="px-2 py-0.5 rounded-full text-[9px] font-bold" style={i===0?{background:theme.primary,color:theme.primaryFg}:i===1?{border:`1px solid ${theme.primary}`,color:theme.primary}:{background:`${theme.primary}22`,color:theme.primary}}>{["Primary","Outline","Soft"][i]}</span>
))}
</div>
</div>
</div>
</div>
);
}
// Extended HeroUI marketing themes — these match heroui.com/themes prebuilt options
const HEROUI_MARKETING_THEMES: ThemeColor[] = [
{ id: "purple", label: "Purple", primary: "#7c3aed", primaryFg: "#fff", activeBg: "rgba(124,58,237,0.08)", activeFg: "#7c3aed", ring: "rgba(124,58,237,0.15)", bg: "#fff" },
{ id: "blue", label: "Blue", primary: "#2563eb", primaryFg: "#fff", activeBg: "rgba(37,99,235,0.08)", activeFg: "#2563eb", ring: "rgba(37,99,235,0.15)", bg: "#fff" },
{ id: "teal", label: "Teal", primary: "#0d9488", primaryFg: "#fff", activeBg: "rgba(13,148,136,0.08)", activeFg: "#0d9488", ring: "rgba(13,148,136,0.15)", bg: "#fff" },
{ id: "rose", label: "Rose", primary: "#e11d48", primaryFg: "#fff", activeBg: "rgba(225,29,72,0.08)", activeFg: "#e11d48", ring: "rgba(225,29,72,0.15)", bg: "#fff" },
{ id: "dark", label: "Dark", primary: "#7c3aed", primaryFg: "#fff", activeBg: "rgba(124,58,237,0.2)", activeFg: "#c084fc", ring: "rgba(124,58,237,0.3)", bg: "#09090b", cardBg: "#18181b", textColor: "#f4f4f5", borderColor: "#27272a", mutedText: "#71717a" },
{ id: "modern", label: "Modern", primary: "#06b6d4", primaryFg: "#fff", activeBg: "rgba(6,182,212,0.08)", activeFg: "#06b6d4", ring: "rgba(6,182,212,0.15)", bg: "#fff" },
];
export function MarketingHeroUI() {
const [theme, setTheme] = useState<ThemeColor>(HEROUI_MARKETING_THEMES[0]);
const isDark = theme.id === "dark";
const bg = theme.bg ?? "#fff";
const textColor = theme.textColor ?? "#18181b";
const mutedText = theme.mutedText ?? "#71717a";
const cardBg = theme.cardBg ?? "#fff";
const borderColor = theme.borderColor ?? "#f4f4f5";
return (
<div className="h-full font-sans bg-white">
<nav className="flex items-center justify-between px-6 py-3 border-b">
<div className="h-full font-sans" style={{ background: bg }}>
<nav className="flex items-center justify-between px-6 py-3" style={{ borderBottom:`1px solid ${borderColor}` }}>
<div className="flex items-center gap-2">
<div className="w-6 h-6 rounded-full" style={{ background:"linear-gradient(135deg,#7c3aed,#ec4899)" }} />
<span className="font-bold text-xs" style={{ color:"#18181b" }}>Acme</span>
<div className="w-6 h-6 rounded-full" style={{ background: theme.primary }} />
<span className="font-bold text-xs" style={{ color: textColor }}>Acme</span>
</div>
<div className="flex gap-4 text-xs text-zinc-500">
<div className="flex gap-4 text-xs" style={{ color: mutedText }}>
{["Features","Pricing","Docs","Blog"].map(i=><span key={i}>{i}</span>)}
</div>
<div className="flex gap-2">
<button className="h-7 px-3 rounded-full text-[11px]" style={{ border:"1px solid #e4e4e7", color:"#71717a" }}>Login</button>
<button className="h-7 px-3 rounded-full text-[11px] font-semibold text-white" style={{ background:"linear-gradient(135deg,#7c3aed,#ec4899)" }}>Get started</button>
<div className="flex items-center gap-2">
<ThemeSwatches themes={HEROUI_MARKETING_THEMES} selected={theme} onSelect={setTheme} />
<button className="h-7 px-3 rounded-full text-[11px]" style={{ border:`1px solid ${borderColor}`, color: mutedText }}>Login</button>
<button className="h-7 px-3 rounded-full text-[11px] font-semibold text-white" style={{ background: theme.primary }}>Get started</button>
</div>
</nav>
<div className="px-10 pt-10 pb-6 text-center">
<div className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-[10px] font-semibold mb-4" style={{ background:"rgba(124,58,237,0.08)", color:"#7c3aed", border:"1px solid rgba(124,58,237,0.15)" }}>
🚀 Just launched v2.0
<div className="px-10 pt-10 pb-4 text-center">
<div className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-[10px] font-semibold mb-4" style={{ background: theme.activeBg, color: theme.activeFg, border:`1px solid ${theme.ring}` }}>
🚀 {theme.label} theme v2.0
</div>
<h1 className="text-2xl font-black mb-2" style={{ background:"linear-gradient(135deg,#7c3aed,#ec4899,#f97316)", WebkitBackgroundClip:"text", WebkitTextFillColor:"transparent" }}>
<h1 className="text-2xl font-black mb-2" style={{ color: theme.primary }}>
Build faster,<br />ship smarter
</h1>
<p className="text-xs text-zinc-500 mb-6 mx-auto" style={{ maxWidth:280 }}>The all-in-one platform for teams that move fast.</p>
<div className="flex gap-2 justify-center mb-8">
<button className="h-9 px-5 rounded-full text-xs font-semibold text-white shadow-lg" style={{ background:"linear-gradient(135deg,#7c3aed,#ec4899)" }}>Start for free</button>
<button className="h-9 px-5 rounded-full text-xs font-medium" style={{ border:"1px solid #e4e4e7", color:"#71717a" }}>Live demo </button>
<p className="text-xs mb-5 mx-auto" style={{ color: mutedText, maxWidth:280 }}>The all-in-one platform for teams that move fast.</p>
<div className="flex gap-2 justify-center mb-5">
<button className="h-9 px-5 rounded-full text-xs font-semibold shadow-lg" style={{ background: theme.primary, color: theme.primaryFg }}>Start for free</button>
<button className="h-9 px-5 rounded-full text-xs font-medium" style={{ border:`1px solid ${borderColor}`, color: mutedText }}>Live demo </button>
</div>
<div className="rounded-2xl mx-auto overflow-hidden shadow-2xl" style={{ maxWidth:400, border:"1px solid #f4f4f5" }}>
<div className="h-6 flex items-center gap-1.5 px-3" style={{ background:"#fafafa", borderBottom:"1px solid #f4f4f5" }}>
<div className="rounded-2xl mx-auto overflow-hidden shadow-xl" style={{ maxWidth:400, border:`1px solid ${borderColor}`, background: cardBg }}>
<div className="h-6 flex items-center gap-1.5 px-3" style={{ background: isDark ? "#27272a" : "#fafafa", borderBottom:`1px solid ${borderColor}` }}>
{["#ff5f56","#ffbd2e","#27c93f"].map(c=><div key={c} className="w-2 h-2 rounded-full" style={{ background:c }} />)}
</div>
<div className="p-4" style={{ background:"#fff" }}>
<div className="p-4">
<div className="grid grid-cols-2 gap-2">
{["Revenue","Users","Growth","Churn"].map((m,i)=><div key={m} className="rounded-xl p-2.5" style={{ background:"linear-gradient(135deg,rgba(124,58,237,0.05),rgba(236,72,153,0.05))", border:"1px solid rgba(124,58,237,0.1)" }}><p className="text-[9px] text-zinc-400">{m}</p><p className="text-sm font-bold" style={{ color:"#18181b" }}>{["$12k","2.8k","+24%","2.1%"][i]}</p></div>)}
{["Revenue","Users","Growth","Churn"].map((m,i)=>(
<div key={m} className="rounded-xl p-2.5" style={{ background: theme.activeBg, border:`1px solid ${theme.ring}` }}>
<p className="text-[9px]" style={{ color: mutedText }}>{m}</p>
<p className="text-sm font-bold" style={{ color: textColor }}>{["$12k","2.8k","+24%","2.1%"][i]}</p>
</div>
))}
</div>
</div>
</div>