diff --git a/understand-anything-plugin/packages/dashboard/src/components/ThemePicker.tsx b/understand-anything-plugin/packages/dashboard/src/components/ThemePicker.tsx new file mode 100644 index 0000000..525e37d --- /dev/null +++ b/understand-anything-plugin/packages/dashboard/src/components/ThemePicker.tsx @@ -0,0 +1,143 @@ +import { useCallback, useEffect, useRef, useState } from "react"; +import { useTheme, PRESETS } from "../themes/index.ts"; + +export function ThemePicker() { + const { config, preset, setPreset, setAccent } = useTheme(); + const [open, setOpen] = useState(false); + const ref = useRef(null); + + // Close on outside click + useEffect(() => { + if (!open) return; + function handleClick(e: MouseEvent) { + if (ref.current && !ref.current.contains(e.target as Node)) { + setOpen(false); + } + } + document.addEventListener("mousedown", handleClick); + return () => document.removeEventListener("mousedown", handleClick); + }, [open]); + + // Close on Escape + useEffect(() => { + if (!open) return; + function handleKey(e: KeyboardEvent) { + if (e.key === "Escape") setOpen(false); + } + document.addEventListener("keydown", handleKey); + return () => document.removeEventListener("keydown", handleKey); + }, [open]); + + const handlePreset = useCallback( + (id: string) => { + setPreset(id as Parameters[0]); + }, + [setPreset], + ); + + return ( +
+ + + {open && ( +
+ {/* Presets */} +
+
+ Theme +
+
+ {PRESETS.map((p) => ( + + ))} +
+
+ + {/* Accent swatches */} +
+
+ Accent Color +
+
+ {preset.accentSwatches.map((swatch) => ( +
+
+
+ )} +
+ ); +}