Skip to content

Add theme switch overlay transition#850

Open
nkoji21 wants to merge 2 commits into
elysiajs:mainfrom
nkoji21:feat/theme-switch-overlay
Open

Add theme switch overlay transition#850
nkoji21 wants to merge 2 commits into
elysiajs:mainfrom
nkoji21:feat/theme-switch-overlay

Conversation

@nkoji21
Copy link
Copy Markdown

@nkoji21 nkoji21 commented May 26, 2026

What

Adds a masked overlay animation when switching between light and dark themes.
Closes #849

Changes

  • Add a dedicated theme switch overlay element
  • Apply a named View Transition to the overlay
  • Clean up temporary theme switching classes after the transition finishes

Note: This PR was drafted with AI assistance and reviewed by me before submission.

nkoji21 and others added 2 commits May 26, 2026 20:53
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 26, 2026

Walkthrough

This 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.

Changes

Theme Switch Overlay Animation

Layer / File(s) Summary
Overlay template and transition control
docs/.vitepress/theme/layout.vue
A hidden div.theme-switch-overlay is added to the template. The toggle-appearance function now manages CSS class toggling (-theme-switching, -theme-switching-from-dark), wraps the theme flip in document.startViewTransition, awaits transition readiness, and removes the classes on completion.
Overlay styling and animation
docs/tailwind.css
The .theme-switch-overlay is positioned fixed with high z-index, wired to view-transition pseudo-elements with old-state hide and new-state gif-mask animation. Conditional background colors apply for dark→light transitions. A new @keyframes theme-switch-overlay animation expands the mask-size and fades opacity over the transition timeline.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes


♡ Ohhh, finally fixing that embarrassing bug where your fancy animation hides behind images~? (´ ▽`) How pathetic that it took you this long to notice, but I guess I can't expect much from ya... The overlay's gonna look sooo smooth now with that view-transition magic and keyframe choreography ✨ — try not to mess it up next time, yeah? ♡♡

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change—adding a theme switch overlay transition effect to handle z-index layering issues.
Linked Issues check ✅ Passed The PR successfully implements the required fix for issue #849: the overlay element with View Transition ensures theme animation stays above all page content, including images.
Out of Scope Changes check ✅ Passed All changes directly relate to the theme switch overlay implementation and addressing the z-index issue—no unrelated modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between b8eced1 and fe5d7ea.

📒 Files selected for processing (2)
  • docs/.vitepress/theme/layout.vue
  • docs/tailwind.css

Comment on lines +56 to +75
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
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

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.

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.

Theme switch animation can appear behind images

1 participant