diff --git a/app/app.vue b/app/app.vue
index 9fd297c..67ab371 100644
--- a/app/app.vue
+++ b/app/app.vue
@@ -32,4 +32,37 @@ body {
opacity: 0;
transform: translateY(5px);
}
+
+/* view transition api */
+::view-transition-group(root) {
+ animation-duration: 0.7s;
+ animation-timing-function: linear(
+ 0 0%, 0.2342 12.49%, 0.4374 24.99%,
+ 0.6093 37.49%, 0.6835 43.74%,
+ 0.7499 49.99%, 0.8086 56.25%,
+ 0.8593 62.5%, 0.9023 68.75%, 0.9375 75%,
+ 0.9648 81.25%, 0.9844 87.5%,
+ 0.9961 93.75%, 1 100%
+ );
+}
+
+::view-transition-new(root) {
+ mask: url('data:image/svg+xml,') top left / 0 no-repeat;
+ mask-origin: content-box;
+ animation: scale 1s;
+ transform-origin: top left;
+}
+
+::view-transition-old(root),
+.dark::view-transition-old(root) {
+ animation: scale 1s;
+ transform-origin: top left;
+ z-index: -1;
+}
+
+@keyframes scale {
+ to {
+ mask-size: 350vmax;
+ }
+}
diff --git a/app/components/AppHeader.vue b/app/components/AppHeader.vue
index c985679..e35ecf2 100644
--- a/app/components/AppHeader.vue
+++ b/app/components/AppHeader.vue
@@ -28,6 +28,15 @@ const navs = [
icon: 'i-ph-address-book-duotone'
}
]
+
+function toggleTheme() {
+ if (!document.startViewTransition) {
+ isDark.value = !isDark.value
+ }
+
+ // @ts-ignore
+ document.startViewTransition(() => isDark.value = !isDark.value)
+}
@@ -61,7 +70,7 @@ const navs = [
variant="link"
color="gray"
size="sm"
- @click="isDark = !isDark"
+ @click="toggleTheme()"
/>