ThemeSelect
Applies a Warren theme via data-theme on <html> with optional localStorage persistence.
Signal Watch
TOKENS ONLY · ZERO COMPONENT EDITSSource
"use client"
import { Badge } from "@/registry/warren/badge/badge"
import { Panel } from "@/registry/warren/panel/panel"
import { Stat } from "@/registry/warren/stat/stat"
import { ThemeSelect } from "@/registry/warren/theme-select/theme-select"
export default function ThemeSelectDemo() {
return (
<div className="flex flex-wrap items-start gap-4">
<div className="flex flex-col gap-1">
<span className="font-mono text-[10px] uppercase tracking-wide text-muted-foreground">
Theme
</span>
<ThemeSelect />
</div>
<Panel
title="Signal Watch"
subtitle="TOKENS ONLY · ZERO COMPONENT EDITS"
actions={
<Badge variant="success" dot>
OK
</Badge>
}
footer="PICK A THEME — CANVAS, INK AND DOT GRID FOLLOW"
>
<div className="flex divide-x divide-border">
<Stat label="Throughput" value="84.2%" tone="primary" className="flex-1 pr-3" />
<Stat label="Rejected" value="12" tone="danger" className="flex-1 px-3" />
<Stat label="Latency" value="142ms" tone="teal" className="flex-1 pl-3" />
</div>
</Panel>
</div>
)
}
Installation
npx shadcn@latest add https://warren.eduard3v.com/r/theme-select.jsonUsage
import { ThemeSelect } from "@/components/ui/theme-select"<ThemeSelect />How theming works
Selecting an option sets data-theme="<name>" on <html>. The five palettes —
light, dark, jade, green-neon, dracula — ship inside @warren/warren-base
as token-for-token override blocks, so every Warren component recolors without a
single component edit (:root stays the canonical light palette; setting
data-theme="light" explicitly is inert).
The choice persists as a plain string under the warren-theme localStorage key.
To avoid a flash of light theme before React hydrates, restore it pre-paint with an
inline script as early in <head> as possible (key must match DEFAULT_STORAGE_KEY):
<script>
try {
var t = localStorage.getItem("warren-theme")
if (t) document.documentElement.setAttribute("data-theme", t)
} catch (e) {}
</script>Custom theme lists
Source
"use client"
import { ThemeSelect } from "@/registry/warren/theme-select/theme-select"
export default function ThemeSelectCustomThemes() {
/* Isolated from the page theme: target={null} keeps this demo from fighting
the site-chrome selects over documentElement — a mounted select otherwise
applies its default on mount, clobbering the pre-paint-restored theme. */
return (
<ThemeSelect
themes={[
{ value: "light", label: "PAPER" },
{ value: "dark", label: "NIGHT" },
]}
storageKey={null}
target={null}
/>
)
}
Pass themes to offer any subset (or your own values backed by matching
[data-theme] blocks), and storageKey={null} to disable persistence entirely.
Pair storageKey={null} with target={null} for controls that must not drive
the page theme: a mounted select otherwise applies its default to
documentElement, which would clobber a theme restored by the pre-paint script
above (multiple selects on one page fight over the attribute).
API Reference
Prop
Type
Prop
Type