diff --git a/src/components/layout/AppLayout.tsx b/src/components/layout/AppLayout.tsx
index f936d53..991cbd1 100644
--- a/src/components/layout/AppLayout.tsx
+++ b/src/components/layout/AppLayout.tsx
@@ -10,6 +10,7 @@ import { useConnectionStore } from "../../stores/connectionStore";
import { useEditorStore } from "../../stores/editorStore";
import { useResultStore } from "../../stores/resultStore";
import { useSettingsStore } from "../../stores/settingsStore";
+import { useThemeStore } from "../../stores/themeStore";
import { AIChatPanel } from "../ai/AIChatPanel";
import { BackupDialog } from "../backup/BackupDialog";
import { RestoreDialog } from "../backup/RestoreDialog";
@@ -161,6 +162,18 @@ export function AppLayout() {
case "check-for-updates":
void useSettingsStore.getState().checkForUpdates();
break;
+ case "cycle-theme":
+ // Cycle Dark → Light → System, mirroring Toolbar.cycleTheme so
+ // macOS users get the same one-click action as everyone else.
+ // (refs #453)
+ {
+ const themeStore = useThemeStore.getState();
+ const themeOrder = ["dark", "light", "system"] as const;
+ const idx = themeOrder.indexOf(themeStore.theme);
+ const next = themeOrder[(idx + 1) % themeOrder.length];
+ themeStore.setTheme(next);
+ }
+ break;
case "about":
setHelpTab("about");
setShowShortcuts(true);
diff --git a/src/components/layout/MenuBar.tsx b/src/components/layout/MenuBar.tsx
index 9ee5e39..44d4ac1 100644
--- a/src/components/layout/MenuBar.tsx
+++ b/src/components/layout/MenuBar.tsx
@@ -57,6 +57,8 @@ const MENUS: MenuDef[] = [
items: [
{ type: "item", id: "check-for-updates", label: "Check for Updates…" },
{ type: "separator" },
+ { type: "item", id: "cycle-theme", label: "Cycle Theme (Dark / Light / System)" },
+ { type: "separator" },
{ type: "item", id: "keyboard-shortcuts", label: "Keyboard Shortcuts", shortcut: "F1" },
{ type: "separator" },
{ type: "item", id: "about", label: "About SQLPilot" },
diff --git a/src/components/layout/__tests__/MenuBar.test.tsx b/src/components/layout/__tests__/MenuBar.test.tsx
index affc822..483a482 100644
--- a/src/components/layout/__tests__/MenuBar.test.tsx
+++ b/src/components/layout/__tests__/MenuBar.test.tsx
@@ -160,4 +160,21 @@ describe("MenuBar", () => {
expect.objectContaining({ detail: "check-for-updates" }),
);
});
+
+ it("includes a 'Cycle Theme' entry under the Help menu (refs #453)", () => {
+ render();
+
+ fireEvent.click(screen.getByText("Help"));
+ expect(screen.getByText(/Cycle Theme/)).toBeInTheDocument();
+ });
+
+ it("dispatches 'cycle-theme' menu-action when the entry is clicked", () => {
+ render();
+
+ fireEvent.click(screen.getByText("Help"));
+ fireEvent.click(screen.getByText(/Cycle Theme/));
+ expect(dispatchSpy).toHaveBeenCalledWith(
+ expect.objectContaining({ detail: "cycle-theme" }),
+ );
+ });
});