All Taste components
Micro-interactions
Sun and moon toggle
A light and dark switch whose sun folds its rays away and turns into a crescent moon.
switch · icon button · light and dark
SwitchIcon button
"use client";
import { useState } from "react";
import { cn } from "@/lib/utils";
function SunMoon({ dark }: { dark: boolean }) {
const spring = "transition duration-500 ease-spring motion-reduce:transition-none";
return (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2} strokeLinecap="round" aria-hidden className="size-[18px] overflow-visible">
<g className={cn(spring, "origin-center [transform-box:view-box]", dark && "rotate-90 scale-[.4] opacity-0")}>
<path d="M12 2.6v2M12 19.4v2M2.6 12h2M19.4 12h2M17.2 6.8l1.4-1.4M6.8 6.8 5.4 5.4M17.2 17.2l1.4 1.4M6.8 17.2l-1.4 1.4" />
</g>
<circle cx="12" cy="12" r="7" fill="currentColor" stroke="none" className={cn(spring, "origin-center [transform-box:fill-box]", dark ? "scale-100" : "scale-[.6]")} />
<circle cx="17.5" cy="6.5" r="5.5" stroke="none" className={cn(spring, "fill-bg origin-center [transform-box:fill-box]", dark ? "opacity-100" : "translate-x-[7px] -translate-y-[7px] scale-[.4] opacity-0")} />
</svg>
);
}
export function ThemeSwitch({ dark, onChange }: { dark: boolean; onChange: (dark: boolean) => void }) {
return (
<button
type="button"
role="switch"
aria-checked={dark}
aria-label="Dark mode"
onClick={() => onChange(!dark)}
className={cn(
"relative h-[34px] w-16 rounded-full transition-colors duration-500 motion-reduce:transition-none",
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
dark ? "bg-primary-soft" : "bg-warning-soft",
)}
>
<span
className={cn(
"absolute left-[3px] top-[3px] grid size-7 place-items-center rounded-full bg-bg shadow transition duration-500 ease-spring motion-reduce:transition-none",
dark ? "translate-x-[30px] text-primary" : "text-warning",
)}
>
<SunMoon dark={dark} />
</span>
</button>
);
}
export function ThemeToggleDemo() {
const [dark, setDark] = useState(false);
return <ThemeSwitch dark={dark} onChange={setDark} />;
}
The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.