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 */