feat: add tabbed Settings, 10 themes with custom accent/text color pickers, main project directory selector, and export filename/directory controls

This commit is contained in:
Schwitzz
2026-10-30 14:06:46 -05:00
parent fa22a755ee
commit 1d209fedd2
8 changed files with 1660 additions and 648 deletions
+24 -2
View File
@@ -1,5 +1,12 @@
import { create } from "zustand";
import { applyDensity, applyFontSettings, applyTheme, type ThemeId } from "@pubscript/ui";
import {
applyColorOverrides,
applyDensity,
applyFontSettings,
applyTheme,
THEME_TOKENS,
type ThemeId,
} from "@pubscript/ui";
import { discoverLocalProviders, type ProviderKind, type ThinkingEffort } from "@pubscript/ai";
import { createUlid } from "@pubscript/core";
@@ -238,6 +245,7 @@ export const DEFAULT_AI_AGENTS: AIAgentConfig[] = [
export interface AppSettings {
theme: ThemeId;
accentColor: string;
textColor: string;
density: Density;
fontFamily: FontFamily;
fontSize: number;
@@ -247,6 +255,7 @@ export interface AppSettings {
wordCountGoal: number;
autoSave: boolean;
focusMode: boolean;
projectDirectory: string;
// Navigation & AI Sidebars
navCollapsed: boolean;
aiSidebarOpen: boolean;
@@ -272,6 +281,7 @@ export interface AppSettings {
export const DEFAULT_SETTINGS: AppSettings = {
theme: "ink",
accentColor: "#7c8bf5",
textColor: "",
density: "comfortable",
fontFamily: "serif",
fontSize: 16,
@@ -281,6 +291,7 @@ export const DEFAULT_SETTINGS: AppSettings = {
wordCountGoal: 80_000,
autoSave: true,
focusMode: false,
projectDirectory: "~/Documents/PubScript",
navCollapsed: false,
aiSidebarOpen: false,
aiSidebarWidth: 370,
@@ -351,6 +362,10 @@ export interface SettingsStore extends AppSettings {
export const useSettings = create<SettingsStore>((set, get) => {
const initial = loadSettings();
applyTheme(initial.theme);
applyColorOverrides({
accentColor: initial.accentColor,
textColor: initial.textColor,
});
applyDensity(initial.density);
applyFontSettings({
size: initial.fontSize,
@@ -371,6 +386,12 @@ export const useSettings = create<SettingsStore>((set, get) => {
if (patch.theme != null) {
applyTheme(next.theme);
}
if (patch.theme != null || patch.accentColor != null || patch.textColor != null) {
applyColorOverrides({
accentColor: next.accentColor,
textColor: next.textColor,
});
}
if (patch.density != null) {
applyDensity(next.density);
}
@@ -391,7 +412,8 @@ export const useSettings = create<SettingsStore>((set, get) => {
},
setTheme: (theme) => {
applyTheme(theme);
get().set({ theme });
const themeDefaultAccent = THEME_TOKENS[theme]?.css["--ps-accent"] ?? "#7c8bf5";
get().set({ theme, accentColor: themeDefaultAccent, textColor: "" });
},
updateProvider: (id, patch) => {
const nextProviders = get().aiProviders.map((p) =>