feat: add theme toggle transition
This commit is contained in:
parent
ed82c5cb07
commit
3ef3c2eed1
2 changed files with 60 additions and 1 deletions
|
@ -4,8 +4,46 @@ import { useDark, useToggle } from '@vueuse/core'
|
||||||
const isDark = useDark()
|
const isDark = useDark()
|
||||||
|
|
||||||
const toggleDark = useToggle(isDark)
|
const toggleDark = useToggle(isDark)
|
||||||
|
|
||||||
|
function toggleTheme(event: MouseEvent) {
|
||||||
|
const x = event.clientX
|
||||||
|
const y = event.clientY
|
||||||
|
const endRadius = Math.hypot(
|
||||||
|
Math.max(x, innerWidth - x),
|
||||||
|
Math.max(y, innerHeight - y),
|
||||||
|
)
|
||||||
|
// @ts-expect-error: Transition API
|
||||||
|
if (!document.startViewTransition) {
|
||||||
|
toggleDark()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// @ts-expect-error: Transition API
|
||||||
|
const transition = document.startViewTransition(async () => {
|
||||||
|
toggleDark()
|
||||||
|
})
|
||||||
|
|
||||||
|
transition.ready.then(() => {
|
||||||
|
const clipPath = [
|
||||||
|
`circle(0px at ${x}px ${y}px)`,
|
||||||
|
`circle(${endRadius}px at ${x}px ${y}px)`,
|
||||||
|
]
|
||||||
|
document.documentElement.animate(
|
||||||
|
{
|
||||||
|
clipPath: isDark.value ? [...clipPath].reverse() : clipPath,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
duration: 400,
|
||||||
|
easing: 'ease-in',
|
||||||
|
pseudoElement: isDark.value
|
||||||
|
? '::view-transition-old(root)'
|
||||||
|
: '::view-transition-new(root)',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<button :aria-label="isDark ? 'Dark Theme' : 'Light Theme'" nav-link dark:i-ri-moon-line i-ri-sun-line @click="toggleDark()" />
|
<button :aria-label="isDark ? 'Dark Theme' : 'Light Theme'" nav-link dark:i-ri-moon-line i-ri-sun-line @click="toggleTheme" />
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -41,3 +41,24 @@ article {
|
||||||
.prose-link i {
|
.prose-link i {
|
||||||
--at-apply: text-sm mr-1;
|
--at-apply: text-sm mr-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::view-transition-old(root),
|
||||||
|
::view-transition-new(root) {
|
||||||
|
animation: none;
|
||||||
|
mix-blend-mode: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
::view-transition-old(root) {
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
::view-transition-new(root) {
|
||||||
|
z-index: 2147483646;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark::view-transition-old(root) {
|
||||||
|
z-index: 2147483646;
|
||||||
|
}
|
||||||
|
html.dark::view-transition-new(root) {
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue