From be275cfc6c7b80fe43e9d66c6d14b6d2bbe58a10 Mon Sep 17 00:00:00 2001 From: mikey Date: Mon, 27 Jul 2026 10:47:02 -0600 Subject: [PATCH] fix(desktop): keep identity key help dialog readable in dark mode (#2854) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem With macOS in dark mode (the default for fresh profiles is to follow the system scheme), the onboarding "What's an identity key?" help dialog renders its title in near-white on the always-white textured card, making it unreadable. The body paragraphs stay readable because they use the fixed olive `--buzz-onboarding-backup-ink`; only the `text-foreground` title (and the close button's hover color) flip with the theme. ## Cause The dialog's `DialogContent` carries `buzz-onboarding-neutral-theme` but is portaled outside the `buzz-startup-shell` subtree, so in dark mode it matches `.dark .buzz-onboarding-neutral-theme:not(.buzz-startup-shell)` (`components.css`), which flips `--foreground` to `0 0% 98%`. The textured powder card (`buzz-card-textured`) has no dark variant — it is baked light — so the near-white title disappears against it. ## Fix One attribute: pin the dialog to the light neutral theme with `data-system-color-scheme="light"`. This is the established pattern for always-light onboarding dialogs (`HostedCommunityOnboarding.tsx`, the `CommunityOnboardingFlow.tsx` avatar dialog), and the pinned-light CSS rule already exists and out-specifies the dark-mode flip. No new CSS. ## Testing - Added a dark-mode regression test to `tests/e2e/identity-key-help.spec.ts` (already registered in the Playwright smoke project): emulates `prefers-color-scheme: dark`, opens the dialog, and asserts the title resolves to the pinned light-neutral ink `rgb(23, 23, 23)`. Before the fix it rendered `rgb(250, 250, 250)`. - Manual repro: macOS appearance set to Dark → fresh profile → machine onboarding → click "What's an identity key?". Before/after screenshots are in the comment below. Signed-off-by: Michael Pfister --- .../onboarding/ui/IdentityKeyHelpDialog.tsx | 1 + desktop/tests/e2e/identity-key-help.spec.ts | 35 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/desktop/src/features/onboarding/ui/IdentityKeyHelpDialog.tsx b/desktop/src/features/onboarding/ui/IdentityKeyHelpDialog.tsx index e597dfdbd..0abcd77cb 100644 --- a/desktop/src/features/onboarding/ui/IdentityKeyHelpDialog.tsx +++ b/desktop/src/features/onboarding/ui/IdentityKeyHelpDialog.tsx @@ -67,6 +67,7 @@ export function IdentityKeyHelpDialog() { { "1", ); }); + +test("identity key help stays readable when the app resolves dark mode", async ({ + page, +}) => { + await page.emulateMedia({ colorScheme: "dark" }); + await installMockBridge(page, undefined, { + skipCommunitySeed: true, + skipOnboardingSeed: true, + }); + await page.goto("/"); + + // Fresh profiles follow the system scheme, so the emulated dark scheme is + // the first-run repro: the app resolves the dark theme while onboarding. + await expect + .poll(() => + page.evaluate(() => document.documentElement.classList.contains("dark")), + ) + .toBe(true); + + const trigger = page.getByTestId("identity-key-help-trigger"); + await expect(trigger).toHaveCSS("opacity", "1", { timeout: 5000 }); + await trigger.click(); + + const dialog = page.getByTestId("identity-key-help-dialog"); + await expect(dialog).toBeVisible(); + await waitForAnimations(page); + + // The textured powder card is baked light in both themes, so the dialog pins + // the neutral onboarding theme to its light variant. Without the pin the + // dark theme flips --foreground to near-white and the title disappears + // against the white card. + await expect( + dialog.getByRole("heading", { name: "What’s an identity key?" }), + ).toHaveCSS("color", "rgb(23, 23, 23)"); +});