mirror of
https://github.com/element-plus/element-plus.git
synced 2024-11-21 01:02:59 +08:00
feat(docs): theme switch use startViewTransition api (#14489)
* feat(docs): theme switch use startViewTransition api * chore: format * feat: update
This commit is contained in:
parent
ef0d5820b4
commit
e0f47610e4
@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import { nextTick, ref, watch } from 'vue'
|
||||
import { isDark, toggleDark } from '../../composables/dark'
|
||||
import DarkIcon from '../icons/dark.vue'
|
||||
import LightIcon from '../icons/light.vue'
|
||||
@ -12,13 +12,60 @@ watch(
|
||||
toggleDark()
|
||||
}
|
||||
)
|
||||
|
||||
let resolveFn: (value: boolean | PromiseLike<boolean>) => void
|
||||
const switchTheme = (event: MouseEvent) => {
|
||||
const isAppearanceTransition =
|
||||
// @ts-expect-error
|
||||
document.startViewTransition &&
|
||||
!window.matchMedia('(prefers-reduced-motion: reduce)').matches
|
||||
if (!isAppearanceTransition || !event) {
|
||||
resolveFn(true)
|
||||
return
|
||||
}
|
||||
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
|
||||
const transition = document.startViewTransition(async () => {
|
||||
resolveFn(true)
|
||||
await nextTick()
|
||||
})
|
||||
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)',
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
const beforeChange = (): Promise<boolean> => {
|
||||
return new Promise((resolve) => {
|
||||
resolveFn = resolve
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div @click.stop="switchTheme">
|
||||
<ClientOnly>
|
||||
<el-switch
|
||||
v-model="darkMode"
|
||||
:before-change="beforeChange"
|
||||
:active-action-icon="DarkIcon"
|
||||
:inactive-action-icon="LightIcon"
|
||||
/>
|
||||
|
@ -171,6 +171,7 @@ a.header-anchor {
|
||||
padding-right: 0.23em;
|
||||
font-size: 0.85em;
|
||||
opacity: 0;
|
||||
|
||||
&:hover,
|
||||
:focus {
|
||||
text-decoration: none;
|
||||
@ -200,6 +201,7 @@ li > ol {
|
||||
overflow-y: hidden;
|
||||
overflow-x: auto;
|
||||
margin-bottom: 45px;
|
||||
|
||||
& > table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
@ -271,6 +273,7 @@ details {
|
||||
p:not(.custom-block-title) {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
&.tip {
|
||||
padding: 8px 16px;
|
||||
background-color: var(--block-tip-bg-color);
|
||||
@ -297,3 +300,25 @@ details {
|
||||
white-space: nowrap;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
::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;
|
||||
}
|
||||
|
||||
.dark::view-transition-old(root) {
|
||||
z-index: 2147483646;
|
||||
}
|
||||
|
||||
.dark::view-transition-new(root) {
|
||||
z-index: 1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user