refactor: replace css fade animations with gsap, optimize post page animations and mobile responsiveness

This commit is contained in:
radishzzz 2025-05-18 16:03:17 +01:00
parent 90c2099fec
commit db4aa56987
9 changed files with 239 additions and 211 deletions

View file

@ -19,8 +19,7 @@ const { waline: { serverURL = '', emoji = [], search = false, imageUploader = fa
<div
id="waline"
class="animation-fade-in mt-16"
style="--animation-delay: 0.8s;"
class="mt-16"
></div>
<!-- >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -->

View file

@ -4,7 +4,7 @@ import GoBackIcon from '@/assets/icons/go-back.svg';
<button
id="back-button"
class="animation-fade-goback hidden"
class="hidden"
lg="block absolute c-secondary/40 left--10 top-1/2 aspect-square w-4.5 translate-y--1/2 transition-colors duration-300 ease-out c-secondary active:scale-90 hover:c-primary/80"
aria-label="Go back"
>

View file

@ -0,0 +1,97 @@
<script>
import { gsap } from 'gsap'
function setupPostPageAnimation() {
const allElements = Array.from(document.querySelectorAll('#gsap-post-page-content > *, #gsap-post-page-tags, #waline'))
const tocListChildren = Array.from(document.querySelectorAll('#toc-list > *')).slice(0, 20)
const dateElement = document.getElementById('gsap-post-page-date')
const backButton = document.getElementById('back-button')
const tocIcon = document.getElementById('toc-icon')
const tocContainer = document.getElementById('toc-container')
const isLargeScreen = window.matchMedia('(min-width: 1024px)').matches
// Post Content + Tags + Comments (First 15 elements)
gsap.from(allElements.slice(0, 15), {
opacity: 0,
y: '3rem',
duration: 0.5,
delay: 0.1,
ease: 'power2.out',
stagger: 0.05,
})
// Post Content + Tags + Comments (Rest elements)
if (allElements.length > 15) {
gsap.from(allElements.slice(15), {
opacity: 0,
y: '3rem',
duration: 0.5,
delay: 0.05 * 15 + 0.1,
ease: 'power2.out',
})
}
if (isLargeScreen) {
// Desktop Post Date
if (dateElement) {
gsap.from(dateElement, {
opacity: 0,
y: '1.5rem',
duration: 0.5,
delay: 0.1,
ease: 'power2.out',
})
}
// Desktop TOC Icon
if (tocIcon) {
gsap.from(tocIcon, {
opacity: 0,
y: '0.5rem',
duration: 0.5,
delay: 0.125,
ease: 'power2.out',
})
}
// Desktop Toc List
if (tocListChildren.length > 0) {
gsap.from(tocListChildren, {
opacity: 0,
y: '1.5rem',
duration: 0.5,
delay: 0.15,
ease: 'power2.out',
stagger: 0.025,
})
}
// Desktop Back Button
if (backButton) {
gsap.from(backButton, {
opacity: 0,
x: '0.5rem',
duration: 0.5,
delay: 0.15,
ease: 'power2.out',
})
}
}
else {
// Mobile TOC Container
if (tocContainer) {
gsap.from(tocContainer, {
opacity: 0,
y: '3rem',
duration: 0.5,
delay: 0.1,
ease: 'power2.out',
})
}
}
}
setupPostPageAnimation()
document.addEventListener('astro:after-swap', setupPostPageAnimation)
</script>

View file

@ -19,7 +19,10 @@ const filteredHeadings = headings.filter(heading =>
---
{filteredHeadings.length > 0 && (
<div class="mb-4 uno-round-border bg-secondary/5 2xl:(fixed left-0 top-43.5 max-w-[min(calc(50vw-38rem),13rem)] border-none bg-secondary/0)">
<div
id="toc-container"
class="mb-4 uno-round-border bg-secondary/5 2xl:(fixed left-0 top-43.5 max-w-[min(calc(50vw-38rem),13rem)] border-none bg-secondary/0)"
>
<input
type="checkbox"
id="toc-toggle"
@ -36,8 +39,9 @@ const filteredHeadings = headings.filter(heading =>
</span>
<TocIcon
id="toc-icon"
aria-hidden="true"
class="animation-fade-in ml-1 hidden aspect-square w-4.2 2xl:(mt-4 block origin-center active:scale-90)"
class="ml-1 hidden aspect-square w-4.2 2xl:(mt-4 block origin-center active:scale-90)"
fill="currentColor"
/>
</label>
@ -51,8 +55,8 @@ const filteredHeadings = headings.filter(heading =>
aria-label="Table of Contents"
>
<ul
class="animation-fade-up toc-list"
style="--animation-interval: 0.04s;"
id="toc-list"
class="toc-list"
>
{filteredHeadings.map(heading => (
<li
@ -83,13 +87,13 @@ const filteredHeadings = headings.filter(heading =>
<!-- Override heti default styles >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -->
<style>
.toc-title {
--at-apply: 'font-semibold ml-4 select-none 2xl:hidden';
--at-apply: 'font-semibold ml-4 2xl:hidden';
}
.toc-list {
--at-apply: 'list-none pl-0 space-y-2 mt-1 mb-4 2xl:space-y-1.2';
--at-apply: 'list-none pb-3.3 pl-0 space-y-2 mt-1 mb-4 2xl:space-y-1.2';
}
.toc-link-h2, .toc-link-h3, .toc-link-h4 {
--at-apply: 'text-sm no-underline font-normal text-balance select-none 2xl:(text-3.2 c-secondary/60 transition-colors transition-font-weight duration-300 ease-out hover:(c-secondary font-medium))';
--at-apply: 'text-sm no-underline font-normal text-balance 2xl:(text-3.2 c-secondary/60 transition-colors transition-font-weight duration-300 ease-out hover:(c-secondary font-medium))';
}
/* Initial collapsed state with zero height grid row */
@ -97,7 +101,7 @@ const filteredHeadings = headings.filter(heading =>
--at-apply: 'grid rows-[0fr] duration-300 ease-in-out';
}
.accordion-content {
--at-apply: 'max-h-66 overflow-hidden pl-4 pr-6 2xl:(max-h-[calc(100vh-21.5rem)] pl-1)';
--at-apply: 'max-h-66 overflow-hidden pl-4 pr-6 2xl:(max-h-[calc(100vh-26rem)] pl-1)';
}
/* When toggle is checked, expand the wrapper to show content */

View file

@ -3,13 +3,12 @@ import Button from '@/components/Button.astro'
import Footer from '@/components/Footer.astro'
import Header from '@/components/Header.astro'
import Navbar from '@/components/Navbar.astro'
import FadeUpAnimation from '@/components/Widgets/FadeUpAnimation.astro'
import GithubCard from '@/components/Widgets/GithubCard.astro'
import GsapAnimation from '@/components/Widgets/GsapAnimation.astro'
import PhotoSwipe from '@/components/Widgets/PhotoSwipe.astro'
import themeConfig from '@/config'
import Head from '@/layouts/Head.astro'
import { getPageInfo } from '@/utils/page'
import '@/styles/animation.css'
import '@/styles/global.css'
import '@/styles/font.css'
import '@/styles/heti.css'
@ -48,7 +47,7 @@ const MarginBottom = isPost && themeConfig.comment?.enabled
</main>
<Footer />
</div>
<FadeUpAnimation />
<GsapAnimation />
<Button supportedLangs={supportedLangs} />
<GithubCard />
<PhotoSwipe />

View file

@ -3,7 +3,7 @@ import type { CollectionEntry } from 'astro:content'
import { getCollection, render } from 'astro:content'
import Comments from '@/components/Comments/index.astro'
import PostDate from '@/components/PostDate.astro'
import GoBack from '@/components/Widgets/GoBack.astro'
import BackButton from '@/components/Widgets/BackButton.astro'
import TOC from '@/components/Widgets/TOC.astro'
import { allLocales, defaultLocale, moreLocales } from '@/config'
import { getTagPath } from '@/i18n/path'
@ -109,7 +109,7 @@ const { Content, headings, remarkPluginFrontmatter } = await render(post)
<article class="heti mb-12.6">
<div class="relative">
<!-- Go Back Button On Desktop -->
<GoBack />
<BackButton />
<!-- Title -->
<h1 class="post-title">
<span
@ -123,8 +123,8 @@ const { Content, headings, remarkPluginFrontmatter } = await render(post)
<!-- Date -->
<div
class="animation-fade-in mb-16.3 block c-primary font-time"
style="--animation-distance: 1rem;"
id="gsap-post-page-date"
class="mb-16.3 block c-primary font-time"
transition:name={`time-${post.data.abbrlink || post.id}-${lang}`}
data-disable-theme-transition
>
@ -137,26 +137,25 @@ const { Content, headings, remarkPluginFrontmatter } = await render(post)
<!-- TOC -->
{post.data.toc && <TOC headings={headings} />}
<!-- Content -->
<div class="animation-fade-up">
<div id="gsap-post-page-content">
<Content />
</div>
</article>
<!-- Tags -->
{post.data.tags && post.data.tags.length > 0 && (
<div
class="animation-fade-in uno-decorative-line"
style="--animation-delay: 0.8s;"
></div>
<div class="uno-tags-wrapper">
{post.data.tags.map((tag: string) => (
<a
href={getTagPath(tag, lang)}
class="uno-tags-style"
>
{tag}
</a>
))}
<div id="gsap-post-page-tags">
<div class="uno-decorative-line"></div>
<div class="uno-tags-wrapper">
{post.data.tags.map((tag: string) => (
<a
href={getTagPath(tag, lang)}
class="uno-tags-style"
>
{tag}
</a>
))}
</div>
</div>
)}
<!-- Comments -->