Add theme switch overlay transition#850
Conversation
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
WalkthroughThis PR adds a full-screen animated overlay that plays during theme transitions, ensuring the visual effect stays on top of all page content—including large cover images. The overlay uses the View Transition API with custom class management, gradient masking, and a keyframe animation that expands and fades the effect over the transition duration. ChangesTheme Switch Overlay Animation
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/.vitepress/theme/layout.vue`:
- Around line 56-75: The cleanup is clearing the global "-theme-switching"
classes unconditionally, so a slow/late transition can remove classes belonging
to a newer toggle; fix by associating each startViewTransition with a unique
token (e.g., incrementing id or Symbol) stored on a shared place (like a
property on root or a module-scoped variable) when you create transition, then
in the transition.finished.finally handler only remove the classes if the stored
token still matches the token for that transition; update the code paths that
set root.classList.add('-theme-switching') and
root.classList.toggle('-theme-switching-from-dark') to set the token and ensure
the finally handler checks the token before calling root.classList.remove.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 34257bb2-d21c-4220-b956-8075615f80e2
📒 Files selected for processing (2)
docs/.vitepress/theme/layout.vuedocs/tailwind.css
| const root = document.documentElement | ||
| root.classList.add('-theme-switching') | ||
| root.classList.toggle( | ||
| '-theme-switching-from-dark', | ||
| root.classList.contains('dark') | ||
| ) | ||
|
|
||
| if (document.startViewTransition !== undefined) { | ||
| const transition = document.startViewTransition(async () => { | ||
| darkTheme.value = !darkTheme.value | ||
| await nextTick() | ||
| }).ready | ||
| }) | ||
|
|
||
| void transition.finished.finally(() => { | ||
| root.classList.remove('-theme-switching') | ||
| root.classList.remove('-theme-switching-from-dark') | ||
| }) | ||
|
|
||
| await transition.ready | ||
| } |
There was a problem hiding this comment.
Your cleanup is racing on rapid toggles, baka~ (¬‿¬)♡
Line 69 removes global switching classes unconditionally. If users toggle twice quickly, the first transition can finish later and clear classes while the second is still running, causing overlay flicker/state desync.
Suggested fix
+let themeSwitchTransitionToken = 0
+
provide('toggle-appearance', async ({ clientX: x, clientY: y }: MouseEvent) => {
@@
const root = document.documentElement
+ const token = ++themeSwitchTransitionToken
root.classList.add('-theme-switching')
@@
if (document.startViewTransition !== undefined) {
const transition = document.startViewTransition(async () => {
darkTheme.value = !darkTheme.value
await nextTick()
})
void transition.finished.finally(() => {
+ if (token !== themeSwitchTransitionToken) return
root.classList.remove('-theme-switching')
root.classList.remove('-theme-switching-from-dark')
})🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/.vitepress/theme/layout.vue` around lines 56 - 75, The cleanup is
clearing the global "-theme-switching" classes unconditionally, so a slow/late
transition can remove classes belonging to a newer toggle; fix by associating
each startViewTransition with a unique token (e.g., incrementing id or Symbol)
stored on a shared place (like a property on root or a module-scoped variable)
when you create transition, then in the transition.finished.finally handler only
remove the classes if the stored token still matches the token for that
transition; update the code paths that set
root.classList.add('-theme-switching') and
root.classList.toggle('-theme-switching-from-dark') to set the token and ensure
the finally handler checks the token before calling root.classList.remove.
What
Adds a masked overlay animation when switching between light and dark themes.
Closes #849
Changes
Note: This PR was drafted with AI assistance and reviewed by me before submission.