Context
The 5 feature buttons (Compare / Admin / Import / Backup / Restore) plus the theme-cycle button appear in three places, picked by isMac at AppLayout.tsx:248-263.
Problem
Three files duplicate the toolbar buttons:
src/components/layout/TitleBar.tsx:122-170 — Windows/Linux users see this. Renders Compare, Admin, Import, Backup, Restore, conditional AI, theme-cycle.
src/components/layout/Toolbar.tsx:69-118 — macOS users see this. Renders the same 5 buttons + AI + theme-cycle.
src/components/layout/MenuBar.tsx:11-89 — has menu items for many of the same features but no theme-cycle entry at all (see #452 / F8).
The cycleTheme function is duplicated:
Toolbar.tsx:46-50
TitleBar.tsx:68-72
Adding a new feature button requires editing two files (TitleBar + Toolbar). Forgetting one means Mac users get a feature Windows users don't (or vice versa).
The cross-cutting audit (docs/audits/cross-cutting.md F7) flagged this as P1.
Files
- src/components/layout/TitleBar.tsx:122-170 (5 buttons + theme cycle)
- src/components/layout/Toolbar.tsx:69-118 (5 buttons + theme cycle)
- src/components/layout/MenuBar.tsx:11-89 (menu items, no theme)
Repro
grep -n "Compare\|Admin\|Import\|Backup\|Restore" src/components/layout/TitleBar.tsx | head -20
grep -n "Compare\|Admin\|Import\|Backup\|Restore" src/components/layout/Toolbar.tsx | head -20
# Same buttons, different files
grep -n "cycleTheme" src/components/layout/*.tsx
# TitleBar.tsx:68-72, Toolbar.tsx:46-50 — duplicated
Expected
A single <FeatureToolbar /> component renders the buttons. A useThemeCycle() hook exposes theme, next, cycle. Both TitleBar and Toolbar compose the FeatureToolbar.
Proposed fix
Scope M. Extract:
src/components/layout/FeatureToolbar.tsx — { onShowImport, onShowBackup, onShowRestore, onToggleAI, aiPanelOpen, aiEnabled } props, renders the 5 buttons + AI.
src/hooks/useThemeCycle.ts — wraps useThemeStore.getState() + the cycle index logic.
- TitleBar and Toolbar both consume
<FeatureToolbar /> and <ThemeCycleButton />.
Acceptance
Adding "Open Query History" to the feature bar requires editing one component, not two. The two duplicated cycleTheme functions reduce to one hook. TitleBar.tsx and Toolbar.tsx both shrink by ~50 LOC.
Needs human verify
No (refactor only).
Labels: audit, area/cross-cutting, severity/p1, kind/bug
Context
The 5 feature buttons (Compare / Admin / Import / Backup / Restore) plus the theme-cycle button appear in three places, picked by
isMacatAppLayout.tsx:248-263.Problem
Three files duplicate the toolbar buttons:
src/components/layout/TitleBar.tsx:122-170— Windows/Linux users see this. RendersCompare,Admin,Import,Backup,Restore, conditionalAI, theme-cycle.src/components/layout/Toolbar.tsx:69-118— macOS users see this. Renders the same 5 buttons + AI + theme-cycle.src/components/layout/MenuBar.tsx:11-89— has menu items for many of the same features but no theme-cycle entry at all (see #452 / F8).The
cycleThemefunction is duplicated:Toolbar.tsx:46-50TitleBar.tsx:68-72Adding a new feature button requires editing two files (TitleBar + Toolbar). Forgetting one means Mac users get a feature Windows users don't (or vice versa).
The cross-cutting audit (docs/audits/cross-cutting.md F7) flagged this as P1.
Files
Repro
Expected
A single
<FeatureToolbar />component renders the buttons. AuseThemeCycle()hook exposestheme,next,cycle. Both TitleBar and Toolbar compose the FeatureToolbar.Proposed fix
Scope M. Extract:
src/components/layout/FeatureToolbar.tsx—{ onShowImport, onShowBackup, onShowRestore, onToggleAI, aiPanelOpen, aiEnabled }props, renders the 5 buttons + AI.src/hooks/useThemeCycle.ts— wrapsuseThemeStore.getState()+ the cycle index logic.<FeatureToolbar />and<ThemeCycleButton />.Acceptance
Adding "Open Query History" to the feature bar requires editing one component, not two. The two duplicated
cycleThemefunctions reduce to one hook. TitleBar.tsx and Toolbar.tsx both shrink by ~50 LOC.Needs human verify
No (refactor only).
Labels: audit, area/cross-cutting, severity/p1, kind/bug