feat: use Swug for transition animations instead of ViewTransitions

This commit is contained in:
saicaca 2024-03-12 14:04:58 +08:00
parent e64bd923da
commit a80d69d843
10 changed files with 3646 additions and 297 deletions

View File

@ -9,6 +9,7 @@ import rehypeSlug from "rehype-slug"
import remarkMath from "remark-math" import remarkMath from "remark-math"
import { remarkReadingTime } from "./src/plugins/remark-reading-time.mjs" import { remarkReadingTime } from "./src/plugins/remark-reading-time.mjs"
import svelte from "@astrojs/svelte" import svelte from "@astrojs/svelte"
import swup from '@swup/astro';
const oklchToHex = (str) => { const oklchToHex = (str) => {
const DEFAULT_HUE = 250 const DEFAULT_HUE = 250
@ -26,6 +27,16 @@ export default defineConfig({
base: "/", base: "/",
integrations: [ integrations: [
tailwind(), tailwind(),
swup({
theme: false,
animationClass: 'transition-',
containers: ['main'],
smoothScrolling: true,
cache: true,
preload: true,
accessibility: true,
globalInstance: true,
}),
icon({ icon({
include: { include: {
"material-symbols": ["*"], "material-symbols": ["*"],

View File

@ -18,8 +18,9 @@
"@astrojs/tailwind": "^5.1.0", "@astrojs/tailwind": "^5.1.0",
"@fontsource-variable/jetbrains-mono": "^5.0.19", "@fontsource-variable/jetbrains-mono": "^5.0.19",
"@fontsource/roboto": "^5.0.8", "@fontsource/roboto": "^5.0.8",
"astro": "^4.4.0", "@swup/astro": "^1.4.0",
"astro-icon": "1.0.2", "astro": "^4.5.1",
"astro-icon": "1.1.0",
"colorjs.io": "^0.4.5", "colorjs.io": "^0.4.5",
"mdast-util-to-string": "^4.0.0", "mdast-util-to-string": "^4.0.0",
"overlayscrollbars": "^2.4.6", "overlayscrollbars": "^2.4.6",

File diff suppressed because it is too large Load Diff

View File

@ -5,9 +5,9 @@ import {profileConfig} from "../config";
--- ---
<div class="card-base max-w-[var(--page-width)] min-h-[4.5rem] rounded-b-none mx-auto flex items-center px-6"> <div class="card-base max-w-[var(--page-width)] min-h-[4.5rem] rounded-b-none mx-auto flex items-center px-6">
<div class="text-50 text-sm"> <div class="transition text-50 text-sm">
© 2023 {profileConfig.name}. All Rights Reserved. © 2023 {profileConfig.name}. All Rights Reserved.
<br> <br>
Powered by <a class="link text-[var(--primary)]" target="_blank" href="https://github.com/saicaca/fuwari">Fuwari</a> Powered by <a class="link text-[var(--primary)] font-medium" target="_blank" href="https://github.com/saicaca/fuwari">Fuwari</a>
</div> </div>
</div> </div>

View File

@ -236,5 +236,13 @@ color_set({
.text-25 { .text-25 {
@apply text-black/25 dark:text-white/25 @apply text-black/25 dark:text-white/25
} }
html.is-changing .transition-fade {
@apply transition-all duration-200
}
html.is-animating .transition-fade {
@apply opacity-0 translate-y-4
}
} }
</style> </style>

View File

@ -16,7 +16,7 @@ let links: NavBarLink[] = navBarConfig.links.map((item: NavBarLink | LinkPreset)
}); });
--- ---
<div transition:animate="none" class:list={[ <div class:list={[
className, className,
"card-base sticky top-0 overflow-visible max-w-[var(--page-width)] h-[4.5rem] rounded-t-none mx-auto flex items-center justify-between px-4"]}> "card-base sticky top-0 overflow-visible max-w-[var(--page-width)] h-[4.5rem] rounded-t-none mx-auto flex items-center justify-between px-4"]}>
<a href="/" class="btn-plain h-[3.25rem] px-5 font-bold rounded-lg active:scale-95"> <a href="/" class="btn-plain h-[3.25rem] px-5 font-bold rounded-lg active:scale-95">

View File

@ -3,7 +3,7 @@ import { Icon } from 'astro-icon/components';
--- ---
<!-- There can't be a filter on parent element, or it will break `fixed` --> <!-- There can't be a filter on parent element, or it will break `fixed` -->
<div class="back-to-top-wrapper hidden lg:block" transition:persist> <div class="back-to-top-wrapper hidden lg:block">
<div id="back-to-top-btn" class="back-to-top-btn hide flex items-center rounded-2xl overflow-hidden transition" onclick="backToTop()"> <div id="back-to-top-btn" class="back-to-top-btn hide flex items-center rounded-2xl overflow-hidden transition" onclick="backToTop()">
<button aria-label="Back to Top" class="btn-card h-[3.75rem] w-[3.75rem]"> <button aria-label="Back to Top" class="btn-card h-[3.75rem] w-[3.75rem]">
<Icon name="material-symbols:keyboard-arrow-up-rounded" class="mx-auto"></Icon> <Icon name="material-symbols:keyboard-arrow-up-rounded" class="mx-auto"></Icon>

View File

@ -5,11 +5,11 @@ import Categories from "./Categories.astro";
const className = Astro.props.class; const className = Astro.props.class;
--- ---
<div id="sidebar" class:list={[className, "w-full"]} transition:persist> <div id="sidebar" class:list={[className, "w-full"]}>
<div class="flex flex-col w-full gap-4 mb-4" transition:animate="none"> <div class="flex flex-col w-full gap-4 mb-4">
<Profile></Profile> <Profile></Profile>
</div> </div>
<div class="flex flex-col w-full gap-4 top-4 sticky top-4" transition:animate="none"> <div class="flex flex-col w-full gap-4 top-4 sticky top-4">
<Categories></Categories> <Categories></Categories>
<Tag></Tag> <Tag></Tag>
</div> </div>

View File

@ -3,10 +3,8 @@ import GlobalStyles from "@components/GlobalStyles.astro";
import '@fontsource/roboto/400.css'; import '@fontsource/roboto/400.css';
import '@fontsource/roboto/500.css'; import '@fontsource/roboto/500.css';
import '@fontsource/roboto/700.css'; import '@fontsource/roboto/700.css';
import { ViewTransitions } from 'astro:transitions';
import ImageWrapper from "@components/misc/ImageWrapper.astro"; import ImageWrapper from "@components/misc/ImageWrapper.astro";
import { fade } from 'astro:transitions';
import {pathsEqual} from "@utils/url-utils"; import {pathsEqual} from "@utils/url-utils";
import ConfigCarrier from "@components/ConfigCarrier.astro"; import ConfigCarrier from "@components/ConfigCarrier.astro";
import {siteConfig} from "@/config"; import {siteConfig} from "@/config";
@ -54,6 +52,8 @@ if (!banner || typeof banner !== 'string' || banner.trim() === '') {
// TODO don't use post cover as banner for now // TODO don't use post cover as banner for now
banner = siteConfig.banner.src; banner = siteConfig.banner.src;
const enableBanner = siteConfig.banner.enable;
let pageTitle; let pageTitle;
if (title) { if (title) {
pageTitle = `${title} - ${siteConfig.title}`; pageTitle = `${title} - ${siteConfig.title}`;
@ -66,7 +66,6 @@ if (title) {
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" isHome={isHomePage} pathname={testPathName} class="bg-[var(--page-bg)] transition text-[14px] md:text-[16px]"> <html lang="en" isHome={isHomePage} pathname={testPathName} class="bg-[var(--page-bg)] transition text-[14px] md:text-[16px]">
<head> <head>
<ViewTransitions />
<title>{pageTitle}</title> <title>{pageTitle}</title>
@ -88,15 +87,12 @@ if (title) {
<style define:vars={{ configHue }}></style> <!-- defines global css variables. This will be applied to <html> <body> and some other elements idk why --> <style define:vars={{ configHue }}></style> <!-- defines global css variables. This will be applied to <html> <body> and some other elements idk why -->
</head> </head>
<body class=" min-h-screen transition "> <body class=" min-h-screen transition " class:list={[{"is-home": isHomePage, "enable-banner": enableBanner}]}>
<ConfigCarrier></ConfigCarrier> <ConfigCarrier></ConfigCarrier>
<GlobalStyles> <GlobalStyles>
<div id="banner-wrapper" class="absolute w-full transition-all" <div id="banner-wrapper" class="absolute w-full">
class:list={{'banner-home': isHomePage, 'banner-else': !isHomePage}}
>
<ImageWrapper id="boxtest" alt="Banner image of the blog" class:list={["object-center object-cover h-full", {"hidden": !siteConfig.banner.enable}]} <ImageWrapper id="boxtest" alt="Banner image of the blog" class:list={["object-center object-cover h-full", {"hidden": !siteConfig.banner.enable}]}
src={siteConfig.banner.src} transition:animate="fade" src={siteConfig.banner.src}
> >
</ImageWrapper> </ImageWrapper>
</div> </div>
@ -110,36 +106,32 @@ if (title) {
--page-width: 75rem; --page-width: 75rem;
} }
</style> </style>
<style> <style is:global>
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
@layer components { @layer components {
.banner-home { /* TODO: temporarily make banner height same for all pages since I cannot make the transition feel good
I want to make the height transition parallel with the content transition instead of blocking it
*/
/*
.enable-banner.is-home #banner-wrapper {
@apply h-[var(--banner-height)] md:h-[var(--banner-height-home)] @apply h-[var(--banner-height)] md:h-[var(--banner-height-home)]
} }
.banner-else { */
.enable-banner #banner-wrapper {
@apply h-[var(--banner-height)] @apply h-[var(--banner-height)]
} }
}
#banner-wrapper { /*
view-transition-name: banner-ani; .enable-banner.is-home #top-row {
} @apply h-[calc(var(--banner-height)_-_4.5rem)] md:h-[calc(var(--banner-height-home)_-_4.5rem)]
/* i don't know how this work*/ }
html::view-transition-old(banner-ani) { */
mix-blend-mode: normal; .enable-banner #top-row {
animation: none; @apply h-[calc(var(--banner-height)_-_4.5rem)]
height: 100%; }
overflow: clip;
object-fit: none;
}
html::view-transition-new(banner-ani) {
mix-blend-mode: normal;
animation: none;
height: 100%;
overflow: clip;
object-fit: none;
} }
</style> </style>
<script> <script>
@ -281,6 +273,27 @@ init();
/* Load settings before swapping */ /* Load settings before swapping */
/* astro:after-swap event happened before swap animation */ /* astro:after-swap event happened before swap animation */
document.addEventListener('astro:after-swap', init); document.addEventListener('astro:after-swap', init);
const setup = () => {
// TODO: temp solution to change the height of the banner
/*
window.swup.hooks.on('animation:out:start', () => {
const path = window.location.pathname
const body = document.querySelector('body')
if (path[path.length - 1] === '/' && !body.classList.contains('is-home')) {
body.classList.add('is-home')
} else if (path[path.length - 1] !== '/' && body.classList.contains('is-home')) {
body.classList.remove('is-home')
}
})
*/
}
if (window.swup.hooks) {
setup()
} else {
document.addEventListener('swup:enable', setup)
}
</script> </script>
<style is:global lang="stylus"> <style is:global lang="stylus">
@ -291,5 +304,4 @@ document.addEventListener('astro:after-swap', init);
#banner-wrapper #banner-wrapper
top: -120px top: -120px
opacity: 0 opacity: 0
</style> </style>

View File

@ -21,51 +21,23 @@ const enableBanner = siteConfig.banner.enable
<Layout title={title} banner={banner}> <Layout title={title} banner={banner}>
<div class="max-w-[var(--page-width)] min-h-screen grid grid-cols-[17.5rem_auto] grid-rows-[auto_auto_1fr_auto] lg:grid-rows-[auto_1fr_auto] <div class="max-w-[var(--page-width)] min-h-screen grid grid-cols-[17.5rem_auto] grid-rows-[auto_auto_1fr_auto] lg:grid-rows-[auto_1fr_auto]
mx-auto gap-4 relative px-0 md:px-4" mx-auto gap-4 relative px-0 md:px-4"
transition:animate="none"
> >
<div id="top-row" class="col-span-2 grid-rows-1 z-50" class:list={["transition-all", { <div id="top-row" class="col-span-2 grid-rows-1 z-50" class:list={[""]}>
'h-[calc(var(--banner-height)_-_4.5rem)] md:h-[calc(var(--banner-height-home)_-_4.5rem)]': enableBanner && isHomePage, <Navbar></Navbar>
'h-[calc(var(--banner-height)_-_4.5rem)]': enableBanner && !isHomePage,}]}
>
<Navbar transition:animate="fade" transition:persist></Navbar>
</div> </div>
<SideBar class="row-start-3 row-end-4 col-span-2 lg:row-start-2 lg:row-end-3 lg:col-span-1 lg:max-w-[17.5rem]" transition:persist></SideBar> <SideBar class="row-start-3 row-end-4 col-span-2 lg:row-start-2 lg:row-end-3 lg:col-span-1 lg:max-w-[17.5rem]"></SideBar>
<div class="row-start-2 row-end-3 col-span-2 lg:col-span-1 overflow-hidden" transition:animate="slide"> <div class="row-start-2 row-end-3 col-span-2 lg:col-span-1 overflow-hidden">
<!-- the overflow-hidden here prevent long text break the layout--> <!-- the overflow-hidden here prevent long text break the layout-->
<main id="swup" class="transition-fade">
<slot></slot> <slot></slot>
</main>
</div> </div>
<div class="grid-rows-3 col-span-2 mt-4" transition:persist transition:animate="fade"> <div class="grid-rows-3 col-span-2 mt-4">
<Footer transition:persist></Footer> <Footer></Footer>
</div> </div>
<BackToTop></BackToTop> <BackToTop></BackToTop>
</div> </div>
</Layout> </Layout>
<style>
#top-row {
view-transition-name: rrrr;
}
/* i don't know how this work*/
html::view-transition-old(rrrr) {
mix-blend-mode: normal;
animation: none;
height: auto;
overflow: clip;
object-fit: none;
}
html::view-transition-new(rrrr) {
mix-blend-mode: normal;
animation: none;
height: auto;
overflow: clip;
object-fit: none;
}
</style>
<style lang="stylus" is:global>
.banner-closed
#top-row
height: 4.5rem;
</style>