theme-switcher
kibo-ui-registry/theme-switcherFreeComponent
A component to switch between light, dark and system theme.
Live preview
live · rendered by the registry
Rendered by Kibo UI Registry on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://www.kibo-ui.com/r/theme-switcher.jsonSource
1"use client";23import { useControllableState } from "@radix-ui/react-use-controllable-state";4import { Monitor, Moon, Sun } from "lucide-react";5import { motion } from "motion/react";6import { useCallback, useEffect, useState } from "react";7import { cn } from "@/lib/utils";89const themes = [10 {11 key: "system",12 icon: Monitor,13 label: "System theme",14 },15 {16 key: "light",17 icon: Sun,18 label: "Light theme",19 },20 {21 key: "dark",22 icon: Moon,23 label: "Dark theme",24 },25];2627export type ThemeSwitcherProps = {28 value?: "light" | "dark" | "system";29 onChange?: (theme: "light" | "dark" | "system") => void;30 defaultValue?: "light" | "dark" | "system";31 className?: string;32};3334export const ThemeSwitcher = ({35 value,36 onChange,37 defaultValue = "system",38 className,39}: ThemeSwitcherProps) => {40 const [theme, setTheme] = useControllableState({41 defaultProp: defaultValue,42 prop: value,43 onChange,44 });45 const [mounted, setMounted] = useState(false);4647 const handleThemeClick = useCallback(48 (themeKey: "light" | "dark" | "system") => {49 setTheme(themeKey);50 },51 [setTheme]52 );5354 // Prevent hydration mismatch55 useEffect(() => {56 setMounted(true);57 }, []);5859 if (!mounted) {60 return null;61 }6263 return (64 <div65 className={cn(66 "relative isolate flex h-8 rounded-full bg-background p-1 ring-1 ring-border",67 className68 )}69 >70 {themes.map(({ key, icon: Icon, label }) => {71 const isActive = theme === key;7273 return (74 <button75 aria-label={label}76 className="relative h-6 w-6 rounded-full"77 key={key}78 onClick={() => handleThemeClick(key as "light" | "dark" | "system")}79 type="button"80 >81 {isActive && (82 <motion.div83 className="absolute inset-0 rounded-full bg-secondary"84 layoutId="activeTheme"85 transition={{ type: "spring", duration: 0.5 }}86 />87 )}88 <Icon89 className={cn(90 "relative z-10 m-auto h-4 w-4",91 isActive ? "text-foreground" : "text-muted-foreground"92 )}93 />94 </button>95 );96 })}97 </div>98 );99};
What it pulls in
npm packages
Files it writes
More from Kibo UI Registry
All 41 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| announcementannouncement | Kibo UI Registry | Components | Free | no deps | |
| avatar-stackavatar-stack | Kibo UI Registry | Components | Free | no deps | |
| bannerbanner | Kibo UI Registry | Components | Free | 2 deps | |
| calendarcalendar | Kibo UI Registry | Components | Free | 3 deps | |
| choiceboxchoicebox | Kibo UI Registry | Components | Free | 2 deps | |
| code-blockcode-block | Kibo UI Registry | Components | Free | 5 deps · 2 files | |
| color-pickercolor-picker | Kibo UI Registry | Components | Free | 3 deps | |
| comboboxcombobox | Kibo UI Registry | Components | Free | 2 deps |
