Skip to content

Default color theme can be overridden by the OS preference on a first visit #3613

Description

@tom2drum

Description

An instance that sets NEXT_PUBLIC_COLOR_THEME_DEFAULT=light may still serve the dark theme to a first-time visitor whose operating system prefers dark. The configured default wins the initial paint and then loses to the OS preference on hydration.

Needs confirmation in a production-like run before being treated as a real defect — see the open question below.

Details

SettingsColorTheme's mount effect reads the chakra-ui-color-mode cookie and, when it is absent, falls back to prefers-color-scheme. It never consults config.shell.topBar.colorTheme.default, and it writes the resolved value back into the cookies, so the OS-derived choice becomes sticky:

https://github.com/blockscout/frontend/blob/main/src/shell/top-bar/settings/color-theme/SettingsColorTheme.tsx#L45-L63

ColorModeProvider does pass the configured default to next-themes, which is why the first paint is correct:

https://github.com/blockscout/frontend/blob/main/src/toolkit/chakra/color-mode.tsx#L20

colorThemeMiddleware is presumably what normally prevents this, by planting the default cookie when none is present:

https://github.com/blockscout/frontend/blob/main/src/server/middlewares/colorTheme.ts

Steps to reproduce

Observed on a dev server with NEXT_PUBLIC_COLOR_THEME_DEFAULT=light and a browser reporting prefers-color-scheme: dark:

  1. Clear the chakra-ui-color-mode and chakra-ui-color-theme cookies.
  2. Reload the homepage.
  3. document.documentElement.className is light immediately after load, then becomes dark once the app hydrates, and both cookies are rewritten to dark.

Open question

colorThemeMiddleware is wired up in proxy.ts with a matcher that covers /, but a plain request to / returned no theme cookie in dev:

curl -s -D - -o /dev/null http://localhost:3000/ | grep -i set-cookie

Only uuid came back. Worth checking whether that middleware runs at all under next dev (Next 16 renamed middleware.ts to proxy.ts) and whether it behaves differently in a container. If the middleware does reliably fire in production, the impact is limited to cases where the cookie is missing or cleared client-side.

Expected behavior

A visitor with no theme cookie gets the theme configured by NEXT_PUBLIC_COLOR_THEME_DEFAULT, regardless of their OS setting. The OS preference should only apply when the instance sets no default.

Possible fix, if confirmed: make the no-cookie branch in SettingsColorTheme prefer config.shell.topBar.colorTheme.default and fall back to prefers-color-scheme only when it is unset.

Metadata

Metadata

Assignees

No one assigned

    Labels

    ENVsbugSomething isn't working

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions