From adac1e37337c50b15e6fb358fca6efd98cbe30a3 Mon Sep 17 00:00:00 2001 From: taskylizard <75871323+taskylizard@users.noreply.github.com> Date: Sat, 23 Dec 2023 03:02:38 +0000 Subject: [PATCH] transitions on appearance switch --- .vitepress/theme/Layout.vue | 64 +++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/.vitepress/theme/Layout.vue b/.vitepress/theme/Layout.vue index 2de3a90d1..ed1359982 100644 --- a/.vitepress/theme/Layout.vue +++ b/.vitepress/theme/Layout.vue @@ -2,6 +2,44 @@ import DefaultTheme from "vitepress/theme"; import Sidebar from "./components/SidebarCard.vue"; import Announcement from "./components/Announcement.vue"; +import { useData } from "vitepress"; +import { nextTick, provide } from "vue"; + +const { isDark } = useData(); + +const enableTransitions = () => + "startViewTransition" in document && + window.matchMedia("(prefers-reduced-motion: no-preference)").matches; + +provide("toggle-appearance", async ({ clientX: x, clientY: y }: MouseEvent) => { + if (!enableTransitions()) { + isDark.value = !isDark.value; + return; + } + + const clipPath = [ + `circle(0px at ${x}px ${y}px)`, + `circle(${Math.hypot( + Math.max(x, innerWidth - x), + Math.max(y, innerHeight - y), + )}px at ${x}px ${y}px)`, + ]; + + // @ts-expect-error + await document.startViewTransition(async () => { + isDark.value = !isDark.value; + await nextTick(); + }).ready; + + document.documentElement.animate( + { clipPath: isDark.value ? clipPath.reverse() : clipPath }, + { + duration: 300, + easing: "ease-in", + pseudoElement: `::view-transition-${isDark.value ? "old" : "new"}(root)`, + }, + ); +}); const { Layout } = DefaultTheme; @@ -17,3 +55,29 @@ const { Layout } = DefaultTheme; + +