diff --git a/src/App.tsx b/src/App.tsx index 523dd5a..2e1397f 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,19 +1,37 @@ -import { useEffect } from "react"; +import { useState, useEffect, useCallback } from "react"; import { useAppStore } from "@/stores/app-store"; import { AppShell } from "@/components/layout/AppShell"; import { BoardList } from "@/components/boards/BoardList"; import { BoardView } from "@/components/board/BoardView"; import { CommandPalette } from "@/components/command-palette/CommandPalette"; +import { SettingsDialog } from "@/components/settings/SettingsDialog"; export default function App() { const initialized = useAppStore((s) => s.initialized); const init = useAppStore((s) => s.init); const view = useAppStore((s) => s.view); + const [settingsOpen, setSettingsOpen] = useState(false); + useEffect(() => { init(); }, [init]); + // Listen for custom event to open settings from TopBar or command palette + useEffect(() => { + function handleOpenSettings() { + setSettingsOpen(true); + } + document.addEventListener("open-settings-dialog", handleOpenSettings); + return () => { + document.removeEventListener("open-settings-dialog", handleOpenSettings); + }; + }, []); + + const handleOpenSettings = useCallback(() => { + setSettingsOpen(true); + }, []); + if (!initialized) { return (
@@ -29,7 +47,8 @@ export default function App() { {view.type === "board-list" ? : } - {}} /> + + ); } diff --git a/src/components/settings/SettingsDialog.tsx b/src/components/settings/SettingsDialog.tsx new file mode 100644 index 0000000..7cd2de3 --- /dev/null +++ b/src/components/settings/SettingsDialog.tsx @@ -0,0 +1,86 @@ +import { Sun, Moon, Monitor } from "lucide-react"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogDescription, +} from "@/components/ui/dialog"; +import { Separator } from "@/components/ui/separator"; +import { Button } from "@/components/ui/button"; +import { useAppStore } from "@/stores/app-store"; +import type { AppSettings } from "@/types/settings"; + +interface SettingsDialogProps { + open: boolean; + onOpenChange: (open: boolean) => void; +} + +const THEME_OPTIONS: { + value: AppSettings["theme"]; + label: string; + icon: typeof Sun; +}[] = [ + { value: "light", label: "Light", icon: Sun }, + { value: "dark", label: "Dark", icon: Moon }, + { value: "system", label: "System", icon: Monitor }, +]; + +export function SettingsDialog({ open, onOpenChange }: SettingsDialogProps) { + const theme = useAppStore((s) => s.settings.theme); + const setTheme = useAppStore((s) => s.setTheme); + + return ( + + + + + Settings + + + Configure your OpenPylon preferences. + + + +
+ {/* Theme section */} +
+ +
+ {THEME_OPTIONS.map(({ value, label, icon: Icon }) => ( + + ))} +
+
+ + + + {/* About section */} +
+ +
+

OpenPylon v0.1.0

+

+ Local-first Kanban board +

+
+
+
+
+
+ ); +}