feat: add View Transitions API hero animation for favicon between pages
The favicon animates from its large position in the WelcomeWorld title to the smaller header position in PublicNoteListView and PublicNoteListByDidView.
This commit is contained in:
10
src/App.vue
10
src/App.vue
@@ -21,4 +21,14 @@ const { isATProtoReady } = useATProtoLogin()
|
||||
display: flex;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
::view-transition-old(root),
|
||||
::view-transition-new(root) {
|
||||
animation-duration: 0.25s;
|
||||
}
|
||||
|
||||
::view-transition-group(remanso-logo) {
|
||||
animation-duration: 0.4s;
|
||||
animation-timing-function: cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -14,7 +14,7 @@ const { userInput, repoInput, submit } = useForm()
|
||||
<template>
|
||||
<div class="welcome-world">
|
||||
<h1 class="title is-1">
|
||||
<img src="/favicon.png" alt="Remanso icon" />
|
||||
<img src="/favicon.png" alt="Remanso icon" class="remanso-logo" />
|
||||
Remanso
|
||||
</h1>
|
||||
|
||||
@@ -93,6 +93,10 @@ h1 {
|
||||
}
|
||||
}
|
||||
|
||||
.remanso-logo {
|
||||
view-transition-name: remanso-logo;
|
||||
}
|
||||
|
||||
.welcome-world {
|
||||
padding: 1rem;
|
||||
margin: auto;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { nextTick } from "vue"
|
||||
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router"
|
||||
|
||||
import Home from "@/views/HomeApp.vue"
|
||||
@@ -93,3 +94,13 @@ export const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
routes,
|
||||
})
|
||||
|
||||
router.beforeEach(() => {
|
||||
if (!("startViewTransition" in document)) return
|
||||
return new Promise<void>((resolve) => {
|
||||
;(document as Document & { startViewTransition: (cb: () => Promise<void>) => void }).startViewTransition(async () => {
|
||||
resolve()
|
||||
await nextTick()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -20,6 +20,7 @@ const author = computedAsync(async () => getAuthor(did.value))
|
||||
<main class="public-note-list-view">
|
||||
<div class="header">
|
||||
<home-button class="back-button" />
|
||||
<img src="/favicon.png" alt="Remanso" class="remanso-logo" />
|
||||
<h1 v-if="author">{{ author.handle }}</h1>
|
||||
<div v-else class="skeleton h-8 w-40"></div>
|
||||
</div>
|
||||
@@ -65,6 +66,13 @@ const author = computedAsync(async () => getAuthor(did.value))
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.remanso-logo {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
box-shadow: none;
|
||||
view-transition-name: remanso-logo;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 769px) {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ const following = useFollowingNoteList(follows, followingEnabled)
|
||||
<main class="public-note-list-view">
|
||||
<div class="header">
|
||||
<home-button class="back-button" />
|
||||
<img src="/favicon.png" alt="Remanso" class="remanso-logo" />
|
||||
</div>
|
||||
|
||||
<div v-if="isLoggedIn" role="tablist" class="tabs tabs-border">
|
||||
@@ -135,6 +136,14 @@ const following = useFollowingNoteList(follows, followingEnabled)
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.remanso-logo {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
box-shadow: none;
|
||||
view-transition-name: remanso-logo;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 769px) {
|
||||
|
||||
Reference in New Issue
Block a user