diff --git a/packages/blocks/src/blocks/appearance/index.ts b/packages/blocks/src/blocks/appearance/index.ts index 3331a14..bdf0ae7 100644 --- a/packages/blocks/src/blocks/appearance/index.ts +++ b/packages/blocks/src/blocks/appearance/index.ts @@ -1,5 +1,6 @@ export { appearanceDialogHandle, AppearanceTrigger } from "./dialog" export { AppearanceController } from "./controller" +export { ThemeToggleButton } from "./theme-toggle-button" export { UiStateProvider, type UiStateProviderProps, diff --git a/packages/blocks/src/blocks/appearance/theme-toggle-button.tsx b/packages/blocks/src/blocks/appearance/theme-toggle-button.tsx new file mode 100644 index 0000000..876b196 --- /dev/null +++ b/packages/blocks/src/blocks/appearance/theme-toggle-button.tsx @@ -0,0 +1,57 @@ +import React from "react" + +import { Button } from "@workspace/ui/components/button" +import { useUiState } from "./ui-state" +import { Icon, Moon02Icon, Sun03Icon } from "@workspace/icons" +import { cn } from "@workspace/ui/lib/utils" + +type ThemeToggleButtonProps = Omit< + React.ComponentProps, + "children" | "onClick" +> + +export function ThemeToggleButton({ + className, + ...props +}: ThemeToggleButtonProps) { + const [themeMode, setThemeMode] = useUiState("theme-mode") + const [systemTheme, setSystemTheme] = React.useState<"light" | "dark">( + "light" + ) + const [mounted, setMounted] = React.useState(false) + const resolvedTheme = themeMode === "system" ? systemTheme : themeMode + + React.useEffect(() => { + const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)") + const updateSystemTheme = () => { + setSystemTheme(mediaQuery.matches ? "dark" : "light") + } + + updateSystemTheme() + mediaQuery.addEventListener("change", updateSystemTheme) + setMounted(true) + return () => mediaQuery.removeEventListener("change", updateSystemTheme) + }, []) + + return ( + + ) +}