SPB Git forge
38commits 1branches 0releases
338.7 MBsize
maindefault branch
4 h agolast push
HTML 53.9% TypeScript 44.5% JavaScript 0.6% SQL 0.5%
1.2 KB · 32 lines tsx
Raw Blame History
1"use client";23import { Moon, Sun } from "lucide-react";4import { ThemeProvider, useTheme } from "next-themes";5import { useSyncExternalStore, type ReactNode } from "react";6import { IconButton } from "@/components/ui/button";78const noop = (): (() => void) => () => {};9/** true after hydration, false during SSR — without a setState-in-effect. */10export function useMounted(): boolean {11  return useSyncExternalStore(noop, () => true, () => false);12}1314export function Providers({ children }: { children: ReactNode }) {15  return (16    <ThemeProvider attribute="class" defaultTheme="light" enableSystem disableTransitionOnChange>17      {children}18    </ThemeProvider>19  );20}2122export function ThemeToggle({ className }: { className?: string }) {23  const { resolvedTheme, setTheme } = useTheme();24  const mounted = useMounted();25  const dark = mounted ? resolvedTheme === "dark" : false;26  return (27    <IconButton label={dark ? "Switch to light theme" : "Switch to dark theme"} variant="ghost" onClick={() => setTheme(dark ? "light" : "dark")} className={className}>28      {dark ? <Sun className="size-4" strokeWidth={1.75} /> : <Moon className="size-4" strokeWidth={1.75} />}29    </IconButton>30  );31}32