Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
136d2c3
refactor(layout): remove CommandBar and utility buttons from TopBar
ParkerES Feb 20, 2026
8848657
refactor(css): remove 6 hardcoded color theme blocks from globals.css
ParkerES Feb 20, 2026
ad0bf58
feat(types): replace hardcoded theme constants with custom theme type…
ParkerES Feb 20, 2026
ab218e3
feat(projects): enhance dashboard with search, metrics, and rich proj…
ParkerES Feb 20, 2026
6721dd5
feat(layout): add screenshot, health, hub status buttons to TitleBar
ParkerES Feb 20, 2026
c5ac91c
feat(layout): restructure Sidebar into Personal/Development collapsib…
ParkerES Feb 20, 2026
a5e38a3
Merge work/custom-theme-editor/types-schemas: Types, schemas, constan…
ParkerES Feb 20, 2026
2ea8bac
Merge work/custom-theme-editor/globals-css: Remove 7 hardcoded theme …
ParkerES Feb 20, 2026
71d13eb
Merge work/custom-theme-editor/titlebar: Add utility buttons to TitleBar
ParkerES Feb 20, 2026
6d58643
Merge work/custom-theme-editor/topbar: Remove CommandBar and utilitie…
ParkerES Feb 20, 2026
c914983
Merge work/custom-theme-editor/sidebar: Restructure Sidebar with acco…
ParkerES Feb 20, 2026
2c25e1b
Merge work/custom-theme-editor/projects-dashboard: Enhance Projects D…
ParkerES Feb 20, 2026
b6797d9
feat(store): add custom theme token injection to theme store
ParkerES Feb 20, 2026
0d66bf1
Merge work/custom-theme-editor/theme-store: Custom theme token injection
ParkerES Feb 20, 2026
5719b16
refactor(settings): replace theme swatch grid with Customize Theme bu…
ParkerES Feb 20, 2026
2e585d1
Merge work/custom-theme-editor/settings-page: Settings page simplific…
ParkerES Feb 20, 2026
ba2e646
feat(settings): add Theme Editor page with full color token editing
ParkerES Feb 20, 2026
3d530c1
Merge work/custom-theme-editor/theme-editor: Theme Editor Page with c…
ParkerES Feb 20, 2026
30fa83f
feat(routing): wire /settings/themes route for Theme Editor page
ParkerES Feb 20, 2026
b028f32
Merge work/custom-theme-editor/wire-route: Wire /settings/themes rout…
ParkerES Feb 20, 2026
d710f3c
chore: update E2E tests for custom theme editor, remove orphan files,…
ParkerES Feb 20, 2026
e6024f1
Merge work/custom-theme-editor/e2e-docs: E2E tests, docs, orphan cleanup
ParkerES Feb 20, 2026
0c13f60
Merge origin/master into feature/custom-theme-editor
ParkerES Feb 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ai-docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,7 @@ The task dashboard uses AG-Grid Community v35.1.0 for the main data grid:
| Component | Location | Purpose |
|-----------|----------|---------|
| `RootLayout` | `src/renderer/app/layouts/RootLayout.tsx` | Root shell: renders TitleBar at top, then `react-resizable-panels` (Group/Panel/Separator) for resizable sidebar + content layout. Sidebar panel is collapsible (syncs with layout store). Layout persists to localStorage via `useDefaultLayout`. |
| `TitleBar` | `src/renderer/app/layouts/TitleBar.tsx` | Custom frameless window title bar (32px). Drag region for window movement + minimize/maximize/close controls via `window.*` IPC channels. |
| `TitleBar` | `src/renderer/app/layouts/TitleBar.tsx` | Custom frameless window title bar (32px). Drag region for window movement, utility buttons (screenshot, health, hub status) separated by vertical divider from minimize/maximize/close window controls via `window.*` IPC channels. |
| `Sidebar` | `src/renderer/app/layouts/Sidebar.tsx` | Navigation sidebar (fills its parent panel container) |
| `TopBar` | `src/renderer/app/layouts/TopBar.tsx` | Top bar with CommandBar trigger |
| `CommandBar` | `src/renderer/app/layouts/CommandBar.tsx` | Global command palette (Cmd+K) |
Expand Down
17 changes: 8 additions & 9 deletions ai-docs/FEATURES-INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Location: `src/renderer/features/`
|---------|---------|----------------|--------------|
| **agents** | Agent process management | AgentDashboard, AgentControls, AgentLogs | `agents.*` |
| **alerts** | Reminder/alert system | AlertsPage, AlertForm, AlertList | `alerts.*` |
| **assistant** | Built-in Claude assistant | AssistantWidget (WidgetFab, WidgetPanel, WidgetInput, WidgetMessageArea), CommandBar (TopBar) | `assistant.*` |
| **assistant** | Built-in Claude assistant | AssistantWidget (WidgetFab, WidgetPanel, WidgetInput, WidgetMessageArea) | `assistant.*` |
| **auth** | User authentication | LoginPage (TanStack Form + Zod), RegisterPage (TanStack Form + Zod), AuthGuard, UserMenu (in layouts); **Hooks**: useForceLogout (IPC-driven logout on token refresh failure) | `auth.*` |
| **changelog** | Project changelog viewer | ChangelogPage, ChangelogEntry | `changelog.*` |
| **communications** | Slack/Discord integration | SlackPanel, DiscordPanel | MCP tools |
Expand All @@ -42,8 +42,8 @@ Location: `src/renderer/features/`
| **productivity** | Productivity widgets | CalendarWidget, SpotifyWidget | `calendar.*`, `spotify.*` |
| **projects** | Project management | ProjectListPage, ProjectSettings, WorktreeManager, ProjectEditDialog, GitStatusIndicator (branch name + clean/changed badge in project list) | `projects.*`, `git.status` |
| **roadmap** | Project roadmap | RoadmapPage, MilestoneCard | `milestones.*` |
| **settings** | App settings | SettingsPage, ProfileFormModal (TanStack Form + Zod + FormSelect), HubSettings (ConnectionForm uses TanStack Form + Zod), OAuthProviderSettings, OAuthConnectionStatus, WebhookSettings (SlackForm + GitHubForm use TanStack Form + Zod), StorageManagementSection, StorageUsageBar, RetentionControl | `settings.*`, `oauth.*`, `dataManagement.*` |
| **tasks** | Task management (AG-Grid dashboard) | TaskDataGrid (AG-Grid v35 wrapped in `<Card>` from `@ui`; themed via compound `.ag-theme-quartz.ag-theme-claude` CSS class with design-system token overrides in `ag-grid-theme.css`), TaskFiltersToolbar, TaskDetailRow (subtasks use `?? []` fallback for Hub data), TaskStatusBadge, CreateTaskDialog, PlanFeedbackDialog, TaskResultView (status/duration/cost/log summary for completed tasks), CreatePrDialog (GitHub PR creation post-task-completion); **Hooks**: useTaskEvents (→ useAgentEvents + useQaEvents), useAgentMutations (useStartPlanning, useStartExecution, useReplanWithFeedback, useKillAgent, useRestartFromCheckpoint), useQaMutations, QaReportViewer | `hub.tasks.*`, `tasks.*`, `agent.*` (incl. `agent.replanWithFeedback`), `qa.*`, `git.createPr`, `event:agent.orchestrator.*`, `event:qa.*` |
| **settings** | App settings | SettingsPage, ProfileFormModal (TanStack Form + Zod + FormSelect), HubSettings (ConnectionForm uses TanStack Form + Zod), OAuthProviderSettings, OAuthConnectionStatus, WebhookSettings (SlackForm + GitHubForm use TanStack Form + Zod), StorageManagementSection, StorageUsageBar, RetentionControl, ColorThemeSection; **Theme Editor** (`components/theme-editor/`, 10 files): ThemeEditorPage, ColorControl, ColorSection, ThemePreview, SavedThemesBar, CssImportDialog, css-parser.ts, css-exporter.ts, token-sections.ts — Route: `/settings/themes` | `settings.*`, `oauth.*`, `dataManagement.*` |
| **tasks** | Task management (AG-Grid dashboard) | TaskDataGrid (AG-Grid v35 wrapped in `<Card>` from `@ui`; themed via compound `.ag-theme-quartz.ag-theme-claude` CSS class with design-system token overrides via AG-Grid Theming API in `ag-grid-modules.ts`), TaskFiltersToolbar, TaskDetailRow (subtasks use `?? []` fallback for Hub data), TaskStatusBadge, CreateTaskDialog, PlanFeedbackDialog, TaskResultView (status/duration/cost/log summary for completed tasks), CreatePrDialog (GitHub PR creation post-task-completion); **Hooks**: useTaskEvents (→ useAgentEvents + useQaEvents), useAgentMutations (useStartPlanning, useStartExecution, useReplanWithFeedback, useKillAgent, useRestartFromCheckpoint), useQaMutations, QaReportViewer | `hub.tasks.*`, `tasks.*`, `agent.*` (incl. `agent.replanWithFeedback`), `qa.*`, `git.createPr`, `event:agent.orchestrator.*`, `event:qa.*` |
| **terminals** | Terminal emulator | TerminalGrid, TerminalInstance | `terminals.*` |
| **briefing** | Daily briefing & suggestions | BriefingPage, SuggestionCard | `briefing.*` |
| **merge** | Branch merge workflow | MergeConfirmModal, MergePreviewPanel, ConflictResolver, FileDiffViewer (`@git-diff-view/react`) | `merge.*` |
Expand Down Expand Up @@ -388,11 +388,11 @@ Location: `src/renderer/app/layouts/`

| Layout | Purpose |
|--------|---------|
| `RootLayout.tsx` | Root shell: renders TitleBar at top, then `react-resizable-panels` (Group/Panel/Separator) for sidebar + content layout with localStorage persistence. Sidebar panel is collapsible (collapses to 56px, minSize 160px so labels are visible when expanded, maxSize 300px) and syncs with layout store. |
| `TitleBar.tsx` | Custom frameless window title bar (32px). Drag region for window movement + minimize/maximize/close controls. Uses `window.*` IPC channels. |
| `RootLayout.tsx` | Root shell: renders TitleBar at top, then `react-resizable-panels` (Group/Panel/Separator) for sidebar + content layout with localStorage persistence. Sidebar panel is collapsible (collapses to 56px, minSize 160px, maxSize 300px) and syncs with layout store. |
| `TitleBar.tsx` | Custom frameless window title bar (32px). Drag region for window movement, utility buttons (screenshot, health indicator, hub status) separated by vertical divider from minimize/maximize/close window controls. Uses `window.*` IPC channels. |
| `TitleBarScreenshot.tsx` | Camera icon button that captures the primary screen via `screen.listSources` + `screen.capture` IPC channels and copies PNG to clipboard. Shows checkmark feedback for 1.5s on success. |
| `Sidebar.tsx` | Navigation sidebar (fills its parent panel, collapse state driven by layout store). Uses `bg-sidebar text-sidebar-foreground` theme variables. |
| `TopBar.tsx` | Top bar with assistant command input |
| `CommandBar.tsx` | Global command palette (Cmd+K) |
| `TopBar.tsx` | Top bar with project tabs + add button |
| `ProjectTabBar.tsx` | Horizontal tab bar for switching between open projects |
| `UserMenu.tsx` | Avatar + logout dropdown in sidebar footer |

Expand Down Expand Up @@ -474,7 +474,6 @@ Location: `src/renderer/shared/stores/`
| Store | Purpose |
|-------|---------|
| `assistant-widget-store.ts` | Floating assistant widget open/close state (`useAssistantWidgetStore`) |
| `command-bar-store.ts` | CommandBar processing state, input history, toast visibility |
| `layout-store.ts` | Sidebar state, active project, project tabs, resizable panel layout (persisted via `react-resizable-panels` `useDefaultLayout`) |
| `theme-store.ts` | Dark/light mode, color theme, UI scale |
| `toast-store.ts` | Toast notification queue (max 3, auto-dismiss 5s) |
Expand Down Expand Up @@ -541,7 +540,7 @@ ADC/
│ │ │ │ └── ui/ # 30 design system primitives (shadcn/ui pattern, barrel: @ui)
│ │ │ ├── hooks/ # 6 shared hooks (+ useLooseParams)
│ │ │ ├── lib/ # Utilities (cn, ipc helper)
│ │ │ └── stores/ # 5 Zustand stores + ThemeHydrator
│ │ │ └── stores/ # 4 Zustand stores + ThemeHydrator
│ │ └── styles/globals.css # Theme tokens + Tailwind
│ └── shared/ # Shared between main + renderer
│ ├── ipc-contract.ts # Thin re-export from ipc/ barrel
Expand Down
77 changes: 26 additions & 51 deletions ai-docs/PATTERNS.md
Original file line number Diff line number Diff line change
Expand Up @@ -470,25 +470,35 @@ Every theme block must define all tokens. Template:

### Theme Switching Flow

Custom themes inject CSS variables at runtime via `document.documentElement.style.setProperty('--token', value)`.

```
User selects theme → useThemeStore.setColorTheme('ocean')
User selects custom theme → useThemeStore.setColorTheme(themeId)
→ Zustand state updates
→ applyColorTheme() sets data-theme="ocean" on <html>
CSS [data-theme="ocean"] variables take effect
→ applyColorTheme() sets data-theme="{uuid}" on <html>
applyCustomTokens() calls setProperty() for all 33 CSS tokens
→ All Tailwind classes (bg-primary, etc.) automatically use new values
→ color-mix() expressions automatically use new values
```
→ AG-Grid reads the same CSS vars automatically via its Theming API

### Constants for Theme Names
User selects default theme → useThemeStore.setColorTheme('default')
→ removeProperty() clears all custom CSS var overrides
→ data-theme attribute is removed from <html>
→ Base :root / .dark CSS variables take effect
```

```typescript
import { COLOR_THEMES } from '@shared/constants';
import type { ColorTheme } from '@shared/constants';
### Custom Theme Token Injection

// Available: 'default' | 'dusk' | 'lime' | 'ocean' | 'retro' | 'neo' | 'forest'
```
Custom themes inject CSS variables at runtime via `document.documentElement.style.setProperty('--token', value)`.
The theme store's `applyCustomTokens()` function applies all 33 tokens when a custom theme is selected.
To clear custom tokens: `removeProperty('--token')` for each key.
AG-Grid reads the same CSS vars automatically via its Theming API configuration in `ag-grid-modules.ts`.

When adding a theme, update BOTH `globals.css` AND `src/shared/constants/themes.ts`.
The Theme Editor page (`/settings/themes`) provides:
- Color pickers organized in sections (Base, Card & Surface, Brand, Semantic, Controls, Sidebar, Utility)
- Live preview with isolated CSS scope
- CSS import/export for theme portability
- Save/load named themes to local storage

### Terminal Theme Integration (xterm.js)

Expand Down Expand Up @@ -529,51 +539,16 @@ For branded buttons that need a dark appearance on light backgrounds and vice ve

## AG-Grid Theming Pattern

AG-Grid v35 uses the quartz theme with design-system token overrides. The theme CSS lives at `src/renderer/features/tasks/components/grid/ag-grid-theme.css` and is imported in `globals.css`.
AG-Grid v35 uses the quartz theme with design-system token overrides. Theme configuration is defined programmatically via the AG-Grid Theming API in `src/renderer/features/tasks/components/grid/ag-grid-modules.ts`, reading CSS custom properties at runtime.

### How It Works

1. **Base theme**: `ag-theme-quartz` (imported from `ag-grid-community/styles/`)
2. **Override class**: `ag-theme-claude` stacked with quartz for compound specificity
3. **CSS variables**: `--ag-*` properties mapped to design system tokens (`var(--card)`, `var(--foreground)`, etc.)
4. **Interactive states**: Use `color-mix()` for hover/selection (NEVER hardcode hex/rgb)
5. **Dark mode**: `.dark .ag-theme-quartz.ag-theme-claude` sets `color-scheme: dark` for native scrollbars/controls
6. **Explicit fallbacks**: `.ag-root-wrapper` and `.ag-body-viewport` get direct `background-color` overrides in case CSS variable inheritance doesn't cascade through AG-Grid's internal DOM

### Variable Categories

The theme CSS defines variables across these groups:
- **Core**: `--ag-background-color`, `--ag-foreground-color`, `--ag-data-background-color`, `--ag-border-color`, `--ag-secondary-border-color`
- **Header**: `--ag-header-background-color`, `--ag-header-foreground-color`, `--ag-header-cell-hover-background-color`
- **Rows**: `--ag-odd-row-background-color`, `--ag-row-hover-color`, `--ag-row-border-color`, `--ag-selected-row-background-color`, `--ag-range-selection-background-color`
- **Controls**: `--ag-input-focus-border-color`, `--ag-input-border-color`, `--ag-checkbox-checked-color`, `--ag-toggle-button-on-background-color`
- **Text**: `--ag-secondary-foreground-color`, `--ag-disabled-foreground-color`
- **Panels/Menus**: `--ag-control-panel-background-color`, `--ag-menu-background-color`, `--ag-panel-background-color`, `--ag-modal-overlay-background-color`, `--ag-tooltip-background-color`

**Critical**: `--ag-data-background-color` MUST be set explicitly — it controls the data viewport area and defaults to white if omitted, breaking dark mode.

### CSS Selector Pattern

```css
/* Compound selector ensures overrides beat quartz defaults */
.ag-theme-quartz.ag-theme-claude {
--ag-background-color: var(--card);
--ag-foreground-color: var(--foreground);
--ag-data-background-color: var(--card);
--ag-header-background-color: var(--muted);
--ag-row-hover-color: color-mix(in srgb, var(--accent) 50%, transparent);
/* ... */
}

/* Dark mode: native scrollbar + control dark rendering */
.dark .ag-theme-quartz.ag-theme-claude {
color-scheme: dark;
}

/* Explicit background fallbacks for AG-Grid internal DOM */
.ag-theme-quartz.ag-theme-claude .ag-root-wrapper { background-color: var(--card); }
.ag-theme-quartz.ag-theme-claude .ag-body-viewport { background-color: var(--card); }
```
3. **Theming API**: AG-Grid's `themeQuartz.withPart(colorSchemeDark).withParams()` maps theme params to design system CSS vars at runtime (defined in `ag-grid-theme.ts`)
4. **Custom themes**: Because AG-Grid reads CSS custom properties, custom themes applied via `setProperty()` are automatically picked up — no AG-Grid-specific reconfiguration needed
5. **Interactive states**: Use `color-mix()` for hover/selection (NEVER hardcode hex/rgb)
6. **Dark mode**: `colorSchemeDark` part handles native scrollbar/control rendering

### Component Usage

Expand Down
Loading
Loading