This commit is contained in:
76
app/components/ColorModeButton.vue
Normal file
76
app/components/ColorModeButton.vue
Normal file
@@ -0,0 +1,76 @@
|
||||
<script setup lang="ts">
|
||||
const colorMode = useColorMode()
|
||||
|
||||
const nextTheme = computed(() => (colorMode.value === 'dark' ? 'light' : 'dark'))
|
||||
|
||||
const switchTheme = () => {
|
||||
colorMode.preference = nextTheme.value
|
||||
}
|
||||
|
||||
const startViewTransition = (event: MouseEvent) => {
|
||||
if (!document.startViewTransition) {
|
||||
switchTheme()
|
||||
return
|
||||
}
|
||||
|
||||
const x = event.clientX
|
||||
const y = event.clientY
|
||||
const endRadius = Math.hypot(
|
||||
Math.max(x, window.innerWidth - x),
|
||||
Math.max(y, window.innerHeight - y)
|
||||
)
|
||||
|
||||
const transition = document.startViewTransition(() => {
|
||||
switchTheme()
|
||||
})
|
||||
|
||||
transition.ready.then(() => {
|
||||
const duration = 600
|
||||
document.documentElement.animate(
|
||||
{
|
||||
clipPath: [
|
||||
`circle(0px at ${x}px ${y}px)`,
|
||||
`circle(${endRadius}px at ${x}px ${y}px)`
|
||||
]
|
||||
},
|
||||
{
|
||||
duration: duration,
|
||||
easing: 'cubic-bezier(.76,.32,.29,.99)',
|
||||
pseudoElement: '::view-transition-new(root)'
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ClientOnly>
|
||||
<UButton
|
||||
:aria-label="`Switch to ${nextTheme} mode`"
|
||||
:icon="`i-lucide-${nextTheme === 'dark' ? 'sun' : 'moon'}`"
|
||||
color="neutral"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
class="rounded-full"
|
||||
@click="startViewTransition"
|
||||
/>
|
||||
<template #fallback>
|
||||
<div class="size-4" />
|
||||
</template>
|
||||
</ClientOnly>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
::view-transition-old(root),
|
||||
::view-transition-new(root) {
|
||||
animation: none;
|
||||
mix-blend-mode: normal;
|
||||
}
|
||||
|
||||
::view-transition-new(root) {
|
||||
z-index: 9999;
|
||||
}
|
||||
::view-transition-old(root) {
|
||||
z-index: 1;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user