Command Palette

Search for a command to run...

Theme Switcher

21st.dev

A theme switcher component with smooth animations between light, dark, and system modes.

Current: system

import { ThemeSwitcher } from "@/registry/optics/theme-switcher";import { useTheme } from "next-themes";import {	useModeAnimation,	ThemeAnimationType,} from "react-theme-switch-animation";import * as React from "react";export function MyComponent() {	const [themeSwitch, setThemeSwitch] = React.useState("system");	const { theme, setTheme, resolvedTheme, systemTheme } = useTheme();	const { ref, toggleSwitchTheme, isDarkMode } = useModeAnimation();	const checkTheme = () => {		let tema = resolvedTheme;		if (tema === "system") {			tema = systemTheme;		}		return tema === "light" ? false : true;	};	const handleSetTheme = (newTheme) => {		let temaActual = localStorage.getItem("theme2");		setThemeSwitch(newTheme);		if (newTheme === "system") {			if (systemTheme === localStorage.getItem("theme"))				return setTimeout(() => {					localStorage.setItem("theme2", newTheme);				}, 200);			toggleSwitchTheme({				animationType: ThemeAnimationType.BLUR_CIRCLE,				isDarkMode: checkTheme(),				onDarkModeChange: null,			});			return setTimeout(() => {				localStorage.setItem("theme2", newTheme);			}, 200);		}		if (			newTheme === localStorage.getItem("theme") ||			(temaActual === "system" &&				systemTheme === newTheme &&				temaActual !== newTheme)		)			return setTimeout(() => {				localStorage.setItem("theme2", newTheme);			}, 200);		toggleSwitchTheme({			animationType: ThemeAnimationType.BLUR_CIRCLE,			isDarkMode: checkTheme(),			onDarkModeChange: null,		});		setTimeout(() => {			localStorage.setItem("theme2", newTheme);		}, 200);	};	React.useEffect(() => {		let tema = localStorage.getItem("theme2") || "system";		setThemeSwitch(tema);		localStorage.setItem("theme", tema === "system" ? resolvedTheme : tema);	}, [resolvedTheme]);	React.useEffect(() => {		if (			systemTheme !== localStorage.getItem("theme") &&			localStorage.getItem("theme2") === "system"		) {			toggleSwitchTheme({				animationType: ThemeAnimationType.BLUR_CIRCLE,				isDarkMode: localStorage.getItem("theme") === "light" ? false : true,				onDarkModeChange: null,			});		}	}, [systemTheme, toggleSwitchTheme]);		return (		<ThemeSwitcher			ref={ref}			defaultValue={themeSwitch}			onChange={handleSetTheme}			value={themeSwitch}		/>	);}

Installation

pnpm dlx shadcn@latest add https://optics.agusmayol.com.ar/r/theme-switcher.json

Props

<ThemeSwitcher />
Name
Type
className
string
value
"system" | "light" | "dark"
onChange
(theme: string) => void
defaultValue
"system" | "light" | "dark" (default: "system")