fix(desktop): keep identity key help dialog readable in dark mode (#2854)

## 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 <pfista@gmail.com>
This commit is contained in:
mikey
2026-07-27 09:47:02 -07:00
committed by GitHub
parent f2fe3b63c2
commit be275cfc6c
2 changed files with 36 additions and 0 deletions
@@ -67,6 +67,7 @@ export function IdentityKeyHelpDialog() {
<DialogContent
className="buzz-onboarding-neutral-theme max-w-[47.5rem] -translate-y-5"
closeButtonClassName={ONBOARDING_INK_ICON_CLASS}
data-system-color-scheme="light"
data-testid="identity-key-help-dialog"
overlayVariant="transparent"
surface="textured"
@@ -56,3 +56,38 @@ test("identity key help explains the first-run choice", async ({ page }) => {
"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: "Whats an identity key?" }),
).toHaveCSS("color", "rgb(23, 23, 23)");
});