Skip to content

Fix header theme flash when toggling theme in footer#496

Open
vimzh wants to merge 1 commit intopayloadcms:mainfrom
vimzh:fix/footer-theme-toggle-header-flash
Open

Fix header theme flash when toggling theme in footer#496
vimzh wants to merge 1 commit intopayloadcms:mainfrom
vimzh:fix/footer-theme-toggle-header-flash

Conversation

@vimzh
Copy link

@vimzh vimzh commented Mar 14, 2026

Why

When a user scrolls to the bottom of the landing page and toggles the theme selector (e.g. from Auto to Light), the top navbar briefly flashes the selected theme color before reverting on scroll. This happens because the footer's onThemeChange handler directly calls setHeaderTheme(), which immediately overrides the header's theme — but the IntersectionObserver then corrects it back based on the currently visible section's data-theme attribute.

Steps to reproduce:

  1. Go to https://payloadcms.com (landing page)
  2. Scroll to the bottom of the page
  3. Change the theme selector in the footer from "Auto" to "Light"
  4. Observe: the top navbar briefly flashes white (light theme)
  5. Scroll up
  6. Observe: the navbar reverts to dark — the toggle didn't "stick" for the header

Approach

The header theme should be determined solely by the IntersectionObserver based on the currently visible section, not directly manipulated by the footer. The global setTheme() call already triggers the observer recreation chain (via its dependency array), which re-evaluates the correct header theme. The direct setHeaderTheme() calls create a transient inconsistent state and are unnecessary.

How it works

  1. Remove setHeaderTheme() calls from Footer and CloudFooter — Both components were importing useHeaderObserver solely to call setHeaderTheme() alongside setTheme(). The setTheme() call is sufficient: it updates the global theme preference, which the HeaderIntersectionObserver already depends on to recreate its observer and re-evaluate header theme.

  2. Fix missing theme dependency in HeaderIntersectionObserver — The pathname-reset effect (setHeaderTheme(theme)) only had [pathname] in its dependency array, meaning it could use a stale theme value. Adding theme ensures the header also updates when the global theme preference changes (covering edge cases where no IntersectionObserver element is in view).

The footer's theme toggle was directly calling setHeaderTheme(), which
immediately set the header to the user's chosen theme. This caused the
navbar to briefly flash the wrong color before the IntersectionObserver
corrected it based on the currently visible section's actual theme.

The fix removes direct setHeaderTheme() calls from both Footer and
CloudFooter components. The global setTheme() already triggers the
observer recreation chain (via its dependency array), which determines
the correct header theme based on visible sections.

Also fixes a missing `theme` dependency in HeaderIntersectionObserver's
pathname-reset effect, ensuring the header updates when the global theme
preference changes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant