fix(navbar): keep the navbar and body in sync when switching color mode#2000
Merged
Conversation
The body and the navbar each declared their own transition for a color mode switch. The body omitted a timing function, so it defaulted to ease, while the navbar asked for ease-in-out. Both ran for 0.5s and therefore started and ended together, but they drifted by up to 77/255 in between, with the body running ahead. A transparent navbar was worse off: its own rule shares the specificity of the color mode rule but comes later, so it replaced the transition altogether and animated over 0.3s. Define the transition once as $theme-mode-transition and use it for every element that repaints on a switch. The transparent navbar keeps the faster curve for its backdrop filter, which is a scroll effect rather than a color mode one. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
At the top of a page without an overlay, the navbar assigned defaultTheme, which is null there, so setAttribute stored the string "null". The guard above it already computed targetTheme, which falls back to the stored color mode. Assign that instead. The invalid value happened to be harmless, as the navbar then inherited the color mode from the document, but it left the navbar claiming a theme that does not exist. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The navbar carries its own data-bs-theme, so it only repaints once that attribute is reassigned. On a color mode switch that reassignment was deferred by 600ms, which is longer than the 0.5s transition of the body. The body therefore completed its fade before the navbar started its own, leaving the two visibly out of step. The delay was there because the navbar samples the background beneath it and would otherwise read a color the body is still fading through. Read that color from the --bs-body-bg custom property instead: custom properties are not animated, so it holds the target color from the outset. Sampling is now independent of the transition, so the navbar can update immediately and the delay can go, along with the sleep helper that served it. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
✅ Deploy Preview for gethinode-demo ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Collaborator
Author
|
🎉 This PR is included in version 2.19.3 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Switching between light and dark mode changed the navbar and the body at visibly different times.
Problem
The navbar does not inherit the document's color mode.
navbar.jsgives it its owndata-bs-themeattribute so it can adapt to the section beneath it, and on a color mode switch that attribute was only reassigned after a hardcoded 600ms delay — longer than the body's 0.5s transition. The body finished fading before the navbar began.Measured on the exampleSite, scrolled down, dark → light (background red channel):
Two smaller defects compounded it:
ease, while the navbar asked forease-in-out. Same 0.5s, but they diverged by up to 77/255 mid-flight..navbar[data-transparent="true"]shares the specificity of the color mode rule but comes later, so it replaced the transition entirely and animated over 0.3s.Changes
Three commits, one per concern:
fix(theme)— define the transition once as$theme-mode-transitionand use it for every element that repaints on a switch. The transparent navbar keeps its faster curve for the backdrop blur, which is a scroll effect, not a color mode one.fix(navbar)— assigntargetThemerather thandefaultTheme, which wasnullat the top of a page without an overlay and stored the string"null".fix(navbar)— drop the 600ms delay. It existed because the navbar samples the background beneath it and would otherwise read a color the body is still fading through. Reading--bs-body-bginstead solves that at the source: custom properties are not animated, so the property holds the target color from the outset. Sampling no longer depends on the transition, so the navbar updates immediately and the delay (and itssleephelper) can go.Verification
Sampled both elements every animation frame through real toggles. Maximum divergence in the background red channel, previously up to 77/255 with the navbar a further ~600ms behind:
The behaviour the changed rules protect still works: the navbar's theme attribute is a valid mode at every scroll position,
data-bs-overlaystill wins at the top of an overlay page, and the transparent navbar is still clear at the top withblur(10px)once scrolled. The transparent cases were exercised by temporarily enablingnavigation.transparent, which is off in the exampleSite.🤖 Generated with Claude Code