diff --git a/.changeset/calm-themes-follow.md b/.changeset/calm-themes-follow.md new file mode 100644 index 0000000000..0293c32e81 --- /dev/null +++ b/.changeset/calm-themes-follow.md @@ -0,0 +1,5 @@ +--- +"@emdash-cms/admin": patch +--- + +Fixes the admin appearance toggle so every click changes the visible color scheme. The admin follows the system preference whenever the selected appearance matches it. diff --git a/e2e/tests/visual-regression.spec.ts-snapshots/content-editor-ltr-chromium-linux.png b/e2e/tests/visual-regression.spec.ts-snapshots/content-editor-ltr-chromium-linux.png index d4705349c7..ed1379a5e2 100644 Binary files a/e2e/tests/visual-regression.spec.ts-snapshots/content-editor-ltr-chromium-linux.png and b/e2e/tests/visual-regression.spec.ts-snapshots/content-editor-ltr-chromium-linux.png differ diff --git a/e2e/tests/visual-regression.spec.ts-snapshots/content-editor-rtl-chromium-linux.png b/e2e/tests/visual-regression.spec.ts-snapshots/content-editor-rtl-chromium-linux.png index 545a062ace..491f2d3ef9 100644 Binary files a/e2e/tests/visual-regression.spec.ts-snapshots/content-editor-rtl-chromium-linux.png and b/e2e/tests/visual-regression.spec.ts-snapshots/content-editor-rtl-chromium-linux.png differ diff --git a/e2e/tests/visual-regression.spec.ts-snapshots/content-list-byline-filter-ltr-chromium-linux.png b/e2e/tests/visual-regression.spec.ts-snapshots/content-list-byline-filter-ltr-chromium-linux.png index 92ad6a0663..1ac09eecf5 100644 Binary files a/e2e/tests/visual-regression.spec.ts-snapshots/content-list-byline-filter-ltr-chromium-linux.png and b/e2e/tests/visual-regression.spec.ts-snapshots/content-list-byline-filter-ltr-chromium-linux.png differ diff --git a/e2e/tests/visual-regression.spec.ts-snapshots/content-list-byline-filter-rtl-chromium-linux.png b/e2e/tests/visual-regression.spec.ts-snapshots/content-list-byline-filter-rtl-chromium-linux.png index 3a747fb80a..6334016894 100644 Binary files a/e2e/tests/visual-regression.spec.ts-snapshots/content-list-byline-filter-rtl-chromium-linux.png and b/e2e/tests/visual-regression.spec.ts-snapshots/content-list-byline-filter-rtl-chromium-linux.png differ diff --git a/e2e/tests/visual-regression.spec.ts-snapshots/content-list-date-field-filter-ltr-chromium-linux.png b/e2e/tests/visual-regression.spec.ts-snapshots/content-list-date-field-filter-ltr-chromium-linux.png index c5400181d2..37444bc723 100644 Binary files a/e2e/tests/visual-regression.spec.ts-snapshots/content-list-date-field-filter-ltr-chromium-linux.png and b/e2e/tests/visual-regression.spec.ts-snapshots/content-list-date-field-filter-ltr-chromium-linux.png differ diff --git a/e2e/tests/visual-regression.spec.ts-snapshots/content-list-date-field-filter-rtl-chromium-linux.png b/e2e/tests/visual-regression.spec.ts-snapshots/content-list-date-field-filter-rtl-chromium-linux.png index 3351c7fac0..9aecc41f92 100644 Binary files a/e2e/tests/visual-regression.spec.ts-snapshots/content-list-date-field-filter-rtl-chromium-linux.png and b/e2e/tests/visual-regression.spec.ts-snapshots/content-list-date-field-filter-rtl-chromium-linux.png differ diff --git a/e2e/tests/visual-regression.spec.ts-snapshots/content-list-date-range-filter-ltr-chromium-linux.png b/e2e/tests/visual-regression.spec.ts-snapshots/content-list-date-range-filter-ltr-chromium-linux.png index 5fa5243521..12483c800f 100644 Binary files a/e2e/tests/visual-regression.spec.ts-snapshots/content-list-date-range-filter-ltr-chromium-linux.png and b/e2e/tests/visual-regression.spec.ts-snapshots/content-list-date-range-filter-ltr-chromium-linux.png differ diff --git a/e2e/tests/visual-regression.spec.ts-snapshots/content-list-date-range-filter-rtl-chromium-linux.png b/e2e/tests/visual-regression.spec.ts-snapshots/content-list-date-range-filter-rtl-chromium-linux.png index 6ceac5b737..a7f5f2d6a2 100644 Binary files a/e2e/tests/visual-regression.spec.ts-snapshots/content-list-date-range-filter-rtl-chromium-linux.png and b/e2e/tests/visual-regression.spec.ts-snapshots/content-list-date-range-filter-rtl-chromium-linux.png differ diff --git a/e2e/tests/visual-regression.spec.ts-snapshots/content-list-ltr-chromium-linux.png b/e2e/tests/visual-regression.spec.ts-snapshots/content-list-ltr-chromium-linux.png index 60b6f6ddb6..e7c14303e9 100644 Binary files a/e2e/tests/visual-regression.spec.ts-snapshots/content-list-ltr-chromium-linux.png and b/e2e/tests/visual-regression.spec.ts-snapshots/content-list-ltr-chromium-linux.png differ diff --git a/e2e/tests/visual-regression.spec.ts-snapshots/content-list-rtl-chromium-linux.png b/e2e/tests/visual-regression.spec.ts-snapshots/content-list-rtl-chromium-linux.png index a5da628a60..18e9761fe7 100644 Binary files a/e2e/tests/visual-regression.spec.ts-snapshots/content-list-rtl-chromium-linux.png and b/e2e/tests/visual-regression.spec.ts-snapshots/content-list-rtl-chromium-linux.png differ diff --git a/e2e/tests/visual-regression.spec.ts-snapshots/content-list-status-filter-ltr-chromium-linux.png b/e2e/tests/visual-regression.spec.ts-snapshots/content-list-status-filter-ltr-chromium-linux.png index 54880994fd..1efc8a6ab2 100644 Binary files a/e2e/tests/visual-regression.spec.ts-snapshots/content-list-status-filter-ltr-chromium-linux.png and b/e2e/tests/visual-regression.spec.ts-snapshots/content-list-status-filter-ltr-chromium-linux.png differ diff --git a/e2e/tests/visual-regression.spec.ts-snapshots/content-list-status-filter-rtl-chromium-linux.png b/e2e/tests/visual-regression.spec.ts-snapshots/content-list-status-filter-rtl-chromium-linux.png index 7a6c0f8a38..ddc60df239 100644 Binary files a/e2e/tests/visual-regression.spec.ts-snapshots/content-list-status-filter-rtl-chromium-linux.png and b/e2e/tests/visual-regression.spec.ts-snapshots/content-list-status-filter-rtl-chromium-linux.png differ diff --git a/e2e/tests/visual-regression.spec.ts-snapshots/content-new-ltr-chromium-linux.png b/e2e/tests/visual-regression.spec.ts-snapshots/content-new-ltr-chromium-linux.png index a75b5bb96d..4aa5978740 100644 Binary files a/e2e/tests/visual-regression.spec.ts-snapshots/content-new-ltr-chromium-linux.png and b/e2e/tests/visual-regression.spec.ts-snapshots/content-new-ltr-chromium-linux.png differ diff --git a/e2e/tests/visual-regression.spec.ts-snapshots/content-new-rtl-chromium-linux.png b/e2e/tests/visual-regression.spec.ts-snapshots/content-new-rtl-chromium-linux.png index 56ea358dcb..31cf633e74 100644 Binary files a/e2e/tests/visual-regression.spec.ts-snapshots/content-new-rtl-chromium-linux.png and b/e2e/tests/visual-regression.spec.ts-snapshots/content-new-rtl-chromium-linux.png differ diff --git a/e2e/tests/visual-regression.spec.ts-snapshots/dashboard-ltr-chromium-linux.png b/e2e/tests/visual-regression.spec.ts-snapshots/dashboard-ltr-chromium-linux.png index da352b3a39..6641d06742 100644 Binary files a/e2e/tests/visual-regression.spec.ts-snapshots/dashboard-ltr-chromium-linux.png and b/e2e/tests/visual-regression.spec.ts-snapshots/dashboard-ltr-chromium-linux.png differ diff --git a/e2e/tests/visual-regression.spec.ts-snapshots/dashboard-rtl-chromium-linux.png b/e2e/tests/visual-regression.spec.ts-snapshots/dashboard-rtl-chromium-linux.png index 9362c4bea1..6d3f148caa 100644 Binary files a/e2e/tests/visual-regression.spec.ts-snapshots/dashboard-rtl-chromium-linux.png and b/e2e/tests/visual-regression.spec.ts-snapshots/dashboard-rtl-chromium-linux.png differ diff --git a/e2e/tests/visual-regression.spec.ts-snapshots/media-ltr-chromium-linux.png b/e2e/tests/visual-regression.spec.ts-snapshots/media-ltr-chromium-linux.png index 6a1565c96d..c611092535 100644 Binary files a/e2e/tests/visual-regression.spec.ts-snapshots/media-ltr-chromium-linux.png and b/e2e/tests/visual-regression.spec.ts-snapshots/media-ltr-chromium-linux.png differ diff --git a/e2e/tests/visual-regression.spec.ts-snapshots/media-mobile-ltr-chromium-linux.png b/e2e/tests/visual-regression.spec.ts-snapshots/media-mobile-ltr-chromium-linux.png index 9ffb29d096..3c81878b06 100644 Binary files a/e2e/tests/visual-regression.spec.ts-snapshots/media-mobile-ltr-chromium-linux.png and b/e2e/tests/visual-regression.spec.ts-snapshots/media-mobile-ltr-chromium-linux.png differ diff --git a/e2e/tests/visual-regression.spec.ts-snapshots/media-mobile-rtl-chromium-linux.png b/e2e/tests/visual-regression.spec.ts-snapshots/media-mobile-rtl-chromium-linux.png index 4bdaec5de6..e31c870026 100644 Binary files a/e2e/tests/visual-regression.spec.ts-snapshots/media-mobile-rtl-chromium-linux.png and b/e2e/tests/visual-regression.spec.ts-snapshots/media-mobile-rtl-chromium-linux.png differ diff --git a/e2e/tests/visual-regression.spec.ts-snapshots/media-rtl-chromium-linux.png b/e2e/tests/visual-regression.spec.ts-snapshots/media-rtl-chromium-linux.png index cd7d15cf10..cc125eaf19 100644 Binary files a/e2e/tests/visual-regression.spec.ts-snapshots/media-rtl-chromium-linux.png and b/e2e/tests/visual-regression.spec.ts-snapshots/media-rtl-chromium-linux.png differ diff --git a/e2e/tests/visual-regression.spec.ts-snapshots/menus-ltr-chromium-linux.png b/e2e/tests/visual-regression.spec.ts-snapshots/menus-ltr-chromium-linux.png index e2a1cac322..cf21b8c4ea 100644 Binary files a/e2e/tests/visual-regression.spec.ts-snapshots/menus-ltr-chromium-linux.png and b/e2e/tests/visual-regression.spec.ts-snapshots/menus-ltr-chromium-linux.png differ diff --git a/e2e/tests/visual-regression.spec.ts-snapshots/menus-rtl-chromium-linux.png b/e2e/tests/visual-regression.spec.ts-snapshots/menus-rtl-chromium-linux.png index 07322f7455..21252403b4 100644 Binary files a/e2e/tests/visual-regression.spec.ts-snapshots/menus-rtl-chromium-linux.png and b/e2e/tests/visual-regression.spec.ts-snapshots/menus-rtl-chromium-linux.png differ diff --git a/e2e/tests/visual-regression.spec.ts-snapshots/settings-ltr-chromium-linux.png b/e2e/tests/visual-regression.spec.ts-snapshots/settings-ltr-chromium-linux.png index 509e755206..29b875bc13 100644 Binary files a/e2e/tests/visual-regression.spec.ts-snapshots/settings-ltr-chromium-linux.png and b/e2e/tests/visual-regression.spec.ts-snapshots/settings-ltr-chromium-linux.png differ diff --git a/e2e/tests/visual-regression.spec.ts-snapshots/settings-rtl-chromium-linux.png b/e2e/tests/visual-regression.spec.ts-snapshots/settings-rtl-chromium-linux.png index 3407207dde..12150afd4b 100644 Binary files a/e2e/tests/visual-regression.spec.ts-snapshots/settings-rtl-chromium-linux.png and b/e2e/tests/visual-regression.spec.ts-snapshots/settings-rtl-chromium-linux.png differ diff --git a/packages/admin/src/components/ThemeProvider.tsx b/packages/admin/src/components/ThemeProvider.tsx index 3e6a1a3cfb..277bfe9c4a 100644 --- a/packages/admin/src/components/ThemeProvider.tsx +++ b/packages/admin/src/components/ThemeProvider.tsx @@ -79,7 +79,11 @@ export function ThemeProvider({ children, defaultTheme = "system" }: ThemeProvid const setTheme = React.useCallback((newTheme: Theme) => { setThemeState(newTheme); - localStorage.setItem(STORAGE_KEY, newTheme); + if (newTheme === "system") { + localStorage.removeItem(STORAGE_KEY); + } else { + localStorage.setItem(STORAGE_KEY, newTheme); + } }, []); const value = React.useMemo( diff --git a/packages/admin/src/components/ThemeToggle.tsx b/packages/admin/src/components/ThemeToggle.tsx index fc084718ad..fcb0dc86c6 100644 --- a/packages/admin/src/components/ThemeToggle.tsx +++ b/packages/admin/src/components/ThemeToggle.tsx @@ -1,45 +1,34 @@ import { Button } from "@cloudflare/kumo"; import { useLingui } from "@lingui/react/macro"; -import { Sun, Moon, Monitor } from "@phosphor-icons/react"; -import * as React from "react"; +import { Sun, Moon } from "@phosphor-icons/react"; import { useTheme } from "./ThemeProvider"; -/** - * Theme toggle button that cycles through: system -> light -> dark - */ export function ThemeToggle() { const { t } = useLingui(); - const { theme, setTheme, resolvedTheme } = useTheme(); + const { setTheme, resolvedTheme } = useTheme(); - const cycleTheme = () => { - const order: ["system", "light", "dark"] = ["system", "light", "dark"]; - const currentIndex = order.indexOf(theme); - const nextIndex = (currentIndex + 1) % order.length; - setTheme(order[nextIndex]!); + const toggleTheme = () => { + const nextTheme = resolvedTheme === "light" ? "dark" : "light"; + const systemTheme = window.matchMedia("(prefers-color-scheme: dark)").matches + ? "dark" + : "light"; + setTheme(nextTheme === systemTheme ? "system" : nextTheme); }; - const resolvedLabel = resolvedTheme === "light" ? t`light` : t`dark`; - const label = - theme === "system" ? t`System (${resolvedLabel})` : theme === "light" ? t`Light` : t`Dark`; + const label = resolvedTheme === "light" ? t`Switch to dark` : t`Switch to light`; return ( ); } diff --git a/packages/admin/tests/components/Header.test.tsx b/packages/admin/tests/components/Header.test.tsx index 7ecdb9e637..36f18fd80f 100644 --- a/packages/admin/tests/components/Header.test.tsx +++ b/packages/admin/tests/components/Header.test.tsx @@ -53,7 +53,7 @@ const { Header } = await import("../../src/components/Header"); // Constants // --------------------------------------------------------------------------- -const THEME_BUTTON_REGEX = /Toggle theme/; +const THEME_BUTTON_REGEX = /Switch to (light|dark)/; function TestWrapper({ children }: { children: React.ReactNode }) { const qc = new QueryClient({ @@ -80,7 +80,7 @@ describe("Header", () => {
, ); - // ThemeToggle renders a button with aria-label "Toggle theme (current: …)" + // ThemeToggle exposes its next action in the aria-label. // (Kumo 2.x wraps `