diff --git a/app/src/components/views/settings-view.tsx b/app/src/components/views/settings-view.tsx
index 881df19f..5ee96fe0 100644
--- a/app/src/components/views/settings-view.tsx
+++ b/app/src/components/views/settings-view.tsx
@@ -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";
diff --git a/app/src/components/views/settings-view/appearance/appearance-section.tsx b/app/src/components/views/settings-view/appearance/appearance-section.tsx
new file mode 100644
index 00000000..4ccd0c24
--- /dev/null
+++ b/app/src/components/views/settings-view/appearance/appearance-section.tsx
@@ -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 (
+
+
+
+
+ Customize the look and feel of your application.
+
+
+
+
+
+
+ {themeOptions.map(({ value, label, Icon, testId }) => {
+ const isActive = effectiveTheme === value;
+ return (
+
+ );
+ })}
+
+
+
+
+ );
+}
diff --git a/app/src/components/views/settings-view/appearance/config/theme-options.ts b/app/src/components/views/settings-view/appearance/config/theme-options.ts
new file mode 100644
index 00000000..e59da056
--- /dev/null
+++ b/app/src/components/views/settings-view/appearance/config/theme-options.ts
@@ -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 = [
+ { 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",
+ },
+];