From 62ccb07fecede5cb9c1a8aa3d0ff8bc49d9436e3 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 15 Feb 2026 20:24:09 +0200 Subject: [PATCH] feat: wire app store with appearance actions and CSS variable application --- src/stores/app-store.ts | 66 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 8 deletions(-) diff --git a/src/stores/app-store.ts b/src/stores/app-store.ts index 3f2e7c5..1b74fb7 100644 --- a/src/stores/app-store.ts +++ b/src/stores/app-store.ts @@ -1,6 +1,6 @@ import { create } from "zustand"; import type { AppSettings } from "@/types/settings"; -import type { BoardMeta } from "@/types/board"; +import type { BoardMeta, ColumnWidth } from "@/types/board"; import { loadSettings, saveSettings, listBoards, ensureDataDirs } from "@/lib/storage"; export type View = { type: "board-list" } | { type: "board"; boardId: string }; @@ -13,6 +13,10 @@ interface AppState { init: () => Promise; setTheme: (theme: AppSettings["theme"]) => void; + setAccentColor: (hue: string) => void; + setUiZoom: (zoom: number) => void; + setDensity: (density: AppSettings["density"]) => void; + setDefaultColumnWidth: (width: ColumnWidth) => void; setView: (view: View) => void; refreshBoards: () => Promise; addRecentBoard: (boardId: string) => void; @@ -28,8 +32,37 @@ function applyTheme(theme: AppSettings["theme"]): void { } } +function applyAppearance(settings: AppSettings): void { + const root = document.documentElement; + root.style.fontSize = `${settings.uiZoom * 16}px`; + const hue = settings.accentColor; + const isDark = root.classList.contains("dark"); + const lightness = isDark ? "60%" : "55%"; + root.style.setProperty("--pylon-accent", `oklch(${lightness} 0.12 ${hue})`); + const densityMap = { compact: "0.75", comfortable: "1", spacious: "1.25" }; + root.style.setProperty("--density-factor", densityMap[settings.density]); +} + +function updateAndSave( + get: () => AppState, + set: (partial: Partial) => void, + patch: Partial +): void { + const settings = { ...get().settings, ...patch }; + set({ settings }); + saveSettings(settings); +} + export const useAppStore = create((set, get) => ({ - settings: { theme: "system", dataDirectory: null, recentBoardIds: [] }, + settings: { + theme: "system", + dataDirectory: null, + recentBoardIds: [], + accentColor: "160", + uiZoom: 1, + density: "comfortable", + defaultColumnWidth: "standard", + }, boards: [], view: { type: "board-list" }, initialized: false, @@ -40,13 +73,32 @@ export const useAppStore = create((set, get) => ({ const boards = await listBoards(); set({ settings, boards, initialized: true }); applyTheme(settings.theme); + applyAppearance(settings); }, setTheme: (theme) => { - const settings = { ...get().settings, theme }; - set({ settings }); - saveSettings(settings); + updateAndSave(get, set, { theme }); applyTheme(theme); + applyAppearance({ ...get().settings, theme }); + }, + + setAccentColor: (accentColor) => { + updateAndSave(get, set, { accentColor }); + applyAppearance(get().settings); + }, + + setUiZoom: (uiZoom) => { + updateAndSave(get, set, { uiZoom }); + applyAppearance(get().settings); + }, + + setDensity: (density) => { + updateAndSave(get, set, { density }); + applyAppearance(get().settings); + }, + + setDefaultColumnWidth: (defaultColumnWidth) => { + updateAndSave(get, set, { defaultColumnWidth }); }, setView: (view) => set({ view }), @@ -62,8 +114,6 @@ export const useAppStore = create((set, get) => ({ boardId, ...settings.recentBoardIds.filter((id) => id !== boardId), ].slice(0, 10); - const updated = { ...settings, recentBoardIds: recent }; - set({ settings: updated }); - saveSettings(updated); + updateAndSave(get, set, { recentBoardIds: recent }); }, }));