spb/datacenterindex
Public
HTML 53.9%
TypeScript 44.5%
JavaScript 0.6%
SQL 0.5%
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