refactor(settings): reorganize appearance section into folder

- Move appearance-section.tsx into appearance/ folder
- Move theme-options.ts into appearance/config/
- Update import paths in appearance-section.tsx
- Update settings-view.tsx to import from new location
- All TypeScript diagnostics passing
- Follows api-keys folder pattern
This commit is contained in:
Kacper
2025-12-11 00:29:06 +01:00
parent 9af6866a9d
commit 7e3819da4b
3 changed files with 150 additions and 1 deletions

View File

@@ -34,7 +34,7 @@ import {
ClaudeCliStatus,
CodexCliStatus,
} from "./settings-view/cli-status-section";
import { AppearanceSection } from "./settings-view/appearance-section";
import { AppearanceSection } from "./settings-view/appearance/appearance-section";
import { KanbanDisplaySection } from "./settings-view/kanban-display-section";
import { KeyboardShortcutsSection } from "./settings-view/keyboard-shortcuts-section";
import { FeatureDefaultsSection } from "./settings-view/feature-defaults-section";

View File

@@ -0,0 +1,61 @@
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { Palette } from "lucide-react";
import { themeOptions } from "./config/theme-options";
import type { Theme, Project } from "../types";
interface AppearanceSectionProps {
effectiveTheme: Theme;
currentProject: Project | null;
onThemeChange: (theme: Theme) => void;
}
export function AppearanceSection({
effectiveTheme,
currentProject,
onThemeChange,
}: AppearanceSectionProps) {
return (
<div
id="appearance"
className="rounded-xl border border-border bg-card backdrop-blur-md overflow-hidden scroll-mt-6"
>
<div className="p-6 border-b border-border">
<div className="flex items-center gap-2 mb-2">
<Palette className="w-5 h-5 text-brand-500" />
<h2 className="text-lg font-semibold text-foreground">Appearance</h2>
</div>
<p className="text-sm text-muted-foreground">
Customize the look and feel of your application.
</p>
</div>
<div className="p-6 space-y-4">
<div className="space-y-3">
<Label className="text-foreground">
Theme{" "}
{currentProject ? `(for ${currentProject.name})` : "(Global)"}
</Label>
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
{themeOptions.map(({ value, label, Icon, testId }) => {
const isActive = effectiveTheme === value;
return (
<Button
key={value}
variant={isActive ? "secondary" : "outline"}
onClick={() => onThemeChange(value)}
className={`flex items-center justify-center gap-2 px-3 py-3 h-auto ${
isActive ? "border-brand-500 ring-1 ring-brand-500/50" : ""
}`}
data-testid={testId}
>
<Icon className="w-4 h-4" />
<span className="font-medium text-sm">{label}</span>
</Button>
);
})}
</div>
</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,88 @@
import {
type LucideIcon,
Atom,
Cat,
Eclipse,
Flame,
Ghost,
Moon,
Radio,
Snowflake,
Sparkles,
Sun,
Terminal,
Trees,
} from "lucide-react";
import { Theme } from "../types";
export interface ThemeOption {
value: Theme;
label: string;
Icon: LucideIcon;
testId: string;
}
export const themeOptions: ReadonlyArray<ThemeOption> = [
{ value: "dark", label: "Dark", Icon: Moon, testId: "dark-mode-button" },
{ value: "light", label: "Light", Icon: Sun, testId: "light-mode-button" },
{
value: "retro",
label: "Retro",
Icon: Terminal,
testId: "retro-mode-button",
},
{
value: "dracula",
label: "Dracula",
Icon: Ghost,
testId: "dracula-mode-button",
},
{
value: "nord",
label: "Nord",
Icon: Snowflake,
testId: "nord-mode-button",
},
{
value: "monokai",
label: "Monokai",
Icon: Flame,
testId: "monokai-mode-button",
},
{
value: "tokyonight",
label: "Tokyo Night",
Icon: Sparkles,
testId: "tokyonight-mode-button",
},
{
value: "solarized",
label: "Solarized",
Icon: Eclipse,
testId: "solarized-mode-button",
},
{
value: "gruvbox",
label: "Gruvbox",
Icon: Trees,
testId: "gruvbox-mode-button",
},
{
value: "catppuccin",
label: "Catppuccin",
Icon: Cat,
testId: "catppuccin-mode-button",
},
{
value: "onedark",
label: "One Dark",
Icon: Atom,
testId: "onedark-mode-button",
},
{
value: "synthwave",
label: "Synthwave",
Icon: Radio,
testId: "synthwave-mode-button",
},
];