11<script lang="ts" setup>
22import VPSwitch from ' @theme/VPSwitch.vue'
33import { computed , inject , nextTick , ref , watchPostEffect } from ' vue'
4- import { enableTransitions , useData } from ' ../composables/index.js'
4+ import { enableTransitions , resolveTransitionKeyframes , useData } from ' ../composables/index.js'
55
66const checked = ref (false )
77const { theme, isDark } = useData ()
@@ -15,7 +15,7 @@ const transitionMode = computed(() => {
1515 return typeof options .appearance === ' string' ? options .appearance : ' fade'
1616})
1717
18- const toggleAppearance = inject (' toggle-appearance' , async ({ clientX : x , clientY : y }: MouseEvent ) => {
18+ const toggleAppearance = inject (' toggle-appearance' , async ({ clientX , clientY }: MouseEvent ) => {
1919 if (! enableTransitions () || transitionMode .value === false ) {
2020 isDark .value = ! isDark .value
2121 return
@@ -26,45 +26,12 @@ const toggleAppearance = inject('toggle-appearance', async ({ clientX: x, client
2626 await nextTick ()
2727 }).ready
2828
29- const keyframes: PropertyIndexedKeyframes = {}
30- const mode = transitionMode .value
31- let duration = 400
32-
33- if (mode === ' circle-clip' ) {
34- const clipPath = [
35- ` circle(0px at ${x }px ${y }px) ` ,
36- ` circle(${Math .hypot (
37- Math .max (x , innerWidth - x ),
38- Math .max (y , innerHeight - y ),
39- )}px at ${x }px ${y }px) ` ,
40- ]
41- keyframes .clipPath = isDark .value ? clipPath .reverse () : clipPath
42- }
43- else if (mode === ' horizontal-clip' ) {
44- const clipPath = [
45- ` inset(0px ${innerWidth }px 0px 0px) ` ,
46- ` inset(0px 0px 0px 0px) ` ,
47- ]
48- keyframes .clipPath = isDark .value ? clipPath .reverse () : clipPath
49- }
50- else if (mode === ' vertical-clip' ) {
51- const clipPath = [
52- ` inset(0px 0px ${innerHeight }px 0px) ` ,
53- ` inset(0px 0px 0px 0px) ` ,
54- ]
55- keyframes .clipPath = isDark .value ? clipPath .reverse () : clipPath
56- }
57- else if (mode === ' skew-clip' ) {
58- const clipPath = [
59- ' polygon(0px 0px, 0px 0px, 0px 0px)' ,
60- ` polygon(0px 0px, ${innerWidth * 2 }px 0px, 0px ${innerHeight * 2 }px) ` ,
61- ]
62- keyframes .clipPath = isDark .value ? clipPath .reverse () : clipPath
63- }
64- else {
65- keyframes .opacity = isDark .value ? [1 , 0 ] : [0 , 1 ]
66- duration = 300
67- }
29+ const { keyframes, duration } = resolveTransitionKeyframes (
30+ clientX ,
31+ clientY ,
32+ transitionMode .value ,
33+ isDark .value ,
34+ )
6835
6936 document .documentElement .animate (
7037 keyframes ,
@@ -86,12 +53,7 @@ watchPostEffect(() => {
8653 </script >
8754
8855<template >
89- <VPSwitch
90- class =" vp-switch-appearance"
91- :title =" switchTitle"
92- :aria-checked =" checked"
93- @click =" toggleAppearance"
94- >
56+ <VPSwitch class =" vp-switch-appearance" :title =" switchTitle" :aria-checked =" checked" @click =" toggleAppearance" >
9557 <span class =" vpi-sun sun" />
9658 <span class =" vpi-moon moon" />
9759 </VPSwitch >
@@ -121,13 +83,23 @@ watchPostEffect(() => {
12183 </style >
12284
12385<style >
86+ [data-theme ] {
87+ will-change : clip-path, filter, opacity;
88+ }
89+
12490::view-transition-image-pair(root) {
12591 isolation : auto ;
12692}
12793
94+ ::view-transition-group(root) {
95+ animation-timing-function : cubic-bezier (0.4 , 0 , 0.2 , 1 );
96+ }
97+
12898::view-transition-old(root),
12999::view-transition-new(root) {
100+ clip-path : none ;
130101 mix-blend-mode : normal ;
102+ mask : none ;
131103 transition : none !important ;
132104 animation : none !important ;
133105}
0 commit comments