feat(index): remove animations

This commit is contained in:
z0x 2025-01-17 19:25:11 -05:00
parent 7c73c45ce2
commit 0105437b6a
8 changed files with 170 additions and 134 deletions

View file

@ -1,32 +1,32 @@
{ {
"name": "blog.z0x.ca", "name": "blog.z0x.ca",
"type": "module", "type": "module",
"version": "1.0.0", "version": "1.0.0",
"scripts": { "scripts": {
"dev": "astro dev", "dev": "astro dev",
"start": "astro dev", "start": "astro dev",
"build": "astro check && astro build", "build": "astro check && astro build",
"preview": "astro preview", "preview": "astro preview",
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
"@astrojs/check": "^0.9.4", "@astrojs/check": "^0.9.4",
"@astrojs/rss": "^4.0.11", "@astrojs/rss": "^4.0.11",
"@astrojs/sitemap": "^3.2.1", "@astrojs/sitemap": "^3.2.1",
"@astrojs/tailwind": "^5.1.4", "@astrojs/tailwind": "^5.1.4",
"@fontsource/geist-mono": "^5.1.1", "@fontsource/geist-mono": "^5.1.1",
"@fontsource/geist-sans": "^5.1.0", "@fontsource/geist-sans": "^5.1.0",
"@r4ai/remark-callout": "^0.6.2", "@r4ai/remark-callout": "^0.6.2",
"@yeskunall/astro-umami": "^0.0.3", "@yeskunall/astro-umami": "^0.0.3",
"astro": "^5.1.7", "astro": "^5.1.7",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"tailwind-merge": "^2.6.0", "tailwind-merge": "^2.6.0",
"tailwindcss": "^3.4.17", "tailwindcss": "^3.4.17",
"typescript": "^5.7.3" "typescript": "^5.7.3"
}, },
"devDependencies": { "devDependencies": {
"@biomejs/biome": "1.9.4", "@biomejs/biome": "1.9.4",
"@tailwindcss/typography": "^0.5.16" "@tailwindcss/typography": "^0.5.16"
}, },
"trustedDependencies": ["@biomejs/biome"] "trustedDependencies": ["@biomejs/biome", "esbuild", "sharp"]
} }

View file

@ -4,7 +4,7 @@ import Container from "@components/Container.astro";
import { SITE } from "@consts"; import { SITE } from "@consts";
--- ---
<footer class="animate"> <footer>
<Container> <Container>
<div class="relative"> <div class="relative">
<div class="absolute -top-12 right-0"> <div class="absolute -top-12 right-0">
@ -14,15 +14,46 @@ import { SITE } from "@consts";
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<div>&copy; {new Date().getFullYear()} • {SITE.TITLE}</div> <div>&copy; {new Date().getFullYear()} • {SITE.TITLE}</div>
<div class="flex flex-wrap items-center gap-1.5"> <div class="flex flex-wrap items-center gap-1.5">
<a aria-label="RSS" href="/rss.xml" target="_blank" class="group flex size-9 items-center justify-center rounded border border-black/15 hover:bg-black/5 focus-visible:bg-black/5 dark:border-white/20 dark:hover:bg-white/5 dark:focus-visible:bg-white/5"> <a
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="transition-colors duration-300 ease-in-out group-hover:animate-pulse group-hover:stroke-black group-focus-visible:animate-pulse group-focus-visible:stroke-black group-hover:dark:stroke-white dark:group-focus-visible:stroke-white"> aria-label="RSS"
href="/rss.xml"
target="_blank"
class="group flex size-9 items-center justify-center rounded border border-black/15 hover:bg-black/5 focus-visible:bg-black/5 dark:border-white/20 dark:hover:bg-white/5 dark:focus-visible:bg-white/5"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
class="transition-colors duration-300 ease-in-out group-hover:animate-pulse group-hover:stroke-black group-focus-visible:animate-pulse group-focus-visible:stroke-black group-hover:dark:stroke-white dark:group-focus-visible:stroke-white"
>
<path d="M5 19m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"></path> <path d="M5 19m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"></path>
<path d="M4 4a16 16 0 0 1 16 16"></path> <path d="M4 4a16 16 0 0 1 16 16"></path>
<path d="M4 11a9 9 0 0 1 9 9"></path> <path d="M4 11a9 9 0 0 1 9 9"></path>
</svg> </svg>
</a> </a>
<button id="light-theme-button" aria-label="Light theme" class="group flex size-9 items-center justify-center rounded border border-black/15 hover:bg-black/5 focus-visible:bg-black/5 dark:border-white/20 dark:hover:bg-white/5 dark:focus-visible:bg-white/5"> <button
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="transition-colors duration-300 ease-in-out group-hover:animate-pulse group-hover:stroke-black group-focus-visible:animate-pulse group-focus-visible:stroke-black group-hover:dark:stroke-white dark:group-focus-visible:stroke-white"> id="light-theme-button"
aria-label="Light theme"
class="group flex size-9 items-center justify-center rounded border border-black/15 hover:bg-black/5 focus-visible:bg-black/5 dark:border-white/20 dark:hover:bg-white/5 dark:focus-visible:bg-white/5"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
class="transition-colors duration-300 ease-in-out group-hover:animate-pulse group-hover:stroke-black group-focus-visible:animate-pulse group-focus-visible:stroke-black group-hover:dark:stroke-white dark:group-focus-visible:stroke-white"
>
<circle cx="12" cy="12" r="5"></circle> <circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line> <line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line> <line x1="12" y1="21" x2="12" y2="23"></line>
@ -34,13 +65,43 @@ import { SITE } from "@consts";
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line> <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg> </svg>
</button> </button>
<button id="dark-theme-button" aria-label="Dark theme" class="group flex size-9 items-center justify-center rounded border border-black/15 hover:bg-black/5 focus-visible:bg-black/5 dark:border-white/20 dark:hover:bg-white/5 dark:focus-visible:bg-white/5"> <button
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="transition-colors duration-300 ease-in-out group-hover:animate-pulse group-hover:stroke-black group-focus-visible:animate-pulse group-focus-visible:stroke-black group-hover:dark:stroke-white dark:group-focus-visible:stroke-white"> id="dark-theme-button"
aria-label="Dark theme"
class="group flex size-9 items-center justify-center rounded border border-black/15 hover:bg-black/5 focus-visible:bg-black/5 dark:border-white/20 dark:hover:bg-white/5 dark:focus-visible:bg-white/5"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
class="transition-colors duration-300 ease-in-out group-hover:animate-pulse group-hover:stroke-black group-focus-visible:animate-pulse group-focus-visible:stroke-black group-hover:dark:stroke-white dark:group-focus-visible:stroke-white"
>
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path> <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
</svg> </svg>
</button> </button>
<button id="system-theme-button" aria-label="System theme" class="group flex size-9 items-center justify-center rounded border border-black/15 hover:bg-black/5 focus-visible:bg-black/5 dark:border-white/20 dark:hover:bg-white/5 dark:focus-visible:bg-white/5"> <button
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="transition-colors duration-300 ease-in-out group-hover:animate-pulse group-hover:stroke-black group-focus-visible:animate-pulse group-focus-visible:stroke-black group-hover:dark:stroke-white dark:group-focus-visible:stroke-white"> id="system-theme-button"
aria-label="System theme"
class="group flex size-9 items-center justify-center rounded border border-black/15 hover:bg-black/5 focus-visible:bg-black/5 dark:border-white/20 dark:hover:bg-white/5 dark:focus-visible:bg-white/5"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
class="transition-colors duration-300 ease-in-out group-hover:animate-pulse group-hover:stroke-black group-focus-visible:animate-pulse group-focus-visible:stroke-black group-hover:dark:stroke-white dark:group-focus-visible:stroke-white"
>
<rect x="2" y="3" width="20" height="14" rx="2" ry="2"></rect> <rect x="2" y="3" width="20" height="14" rx="2" ry="2"></rect>
<line x1="8" y1="21" x2="16" y2="21"></line> <line x1="8" y1="21" x2="16" y2="21"></line>
<line x1="12" y1="17" x2="12" y2="21"></line> <line x1="12" y1="17" x2="12" y2="21"></line>

View file

@ -2,8 +2,6 @@
import "../styles/global.css"; import "../styles/global.css";
import "../styles/callout.css"; import "../styles/callout.css";
import { ClientRouter } from "astro:transitions";
import "@fontsource/geist-sans/100.css"; import "@fontsource/geist-sans/100.css";
import "@fontsource/geist-sans/200.css"; import "@fontsource/geist-sans/200.css";
import "@fontsource/geist-sans/300.css"; import "@fontsource/geist-sans/300.css";
@ -24,9 +22,9 @@ import "@fontsource/geist-mono/800.css";
import "@fontsource/geist-mono/900.css"; import "@fontsource/geist-mono/900.css";
interface Props { interface Props {
title: string; title: string;
description: string; description: string;
image?: string; image?: string;
} }
const { title, description, image = "/blog-placeholder-1.jpg" } = Astro.props; const { title, description, image = "/blog-placeholder-1.jpg" } = Astro.props;
@ -35,7 +33,10 @@ const { title, description, image = "/blog-placeholder-1.jpg" } = Astro.props;
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" /> <meta name="viewport" content="width=device-width,initial-scale=1" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22></text></svg>" /> <link
rel="icon"
href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22></text></svg>"
/>
<meta name="generator" content={Astro.generator} /> <meta name="generator" content={Astro.generator} />
<title>{title}</title> <title>{title}</title>
@ -54,16 +55,12 @@ const { title, description, image = "/blog-placeholder-1.jpg" } = Astro.props;
<meta property="twitter:description" content={description} /> <meta property="twitter:description" content={description} />
<meta property="twitter:image" content={new URL(image, Astro.url)} /> <meta property="twitter:image" content={new URL(image, Astro.url)} />
<ClientRouter />
<script is:inline> <script is:inline>
function init() { function init() {
preloadTheme(); preloadTheme();
onScroll(); onScroll();
animate();
updateThemeButtons(); updateThemeButtons();
addCopyCodeButtons(); addCopyCodeButtons();
setGiscusTheme();
const backToTop = document.getElementById("back-to-top"); const backToTop = document.getElementById("back-to-top");
backToTop?.addEventListener("click", (event) => scrollToTop(event)); backToTop?.addEventListener("click", (event) => scrollToTop(event));
@ -92,11 +89,13 @@ const { title, description, image = "/blog-placeholder-1.jpg" } = Astro.props;
updateThemeButtons(); updateThemeButtons();
}); });
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", (event) => { window
if (localStorage.theme === "system") { .matchMedia("(prefers-color-scheme: dark)")
toggleTheme(event.matches); .addEventListener("change", (event) => {
} if (localStorage.theme === "system") {
}); toggleTheme(event.matches);
}
});
document.addEventListener("scroll", onScroll); document.addEventListener("scroll", onScroll);
} }
@ -130,16 +129,6 @@ const { title, description, image = "/blog-placeholder-1.jpg" } = Astro.props;
} }
} }
function animate() {
const animateElements = document.querySelectorAll(".animate");
animateElements.forEach((element, index) => {
setTimeout(() => {
element.classList.add("show");
}, index * 100);
});
}
function onScroll() { function onScroll() {
if (window.scrollY > 0) { if (window.scrollY > 0) {
document.documentElement.classList.add("scrolled"); document.documentElement.classList.add("scrolled");
@ -182,8 +171,6 @@ const { title, description, image = "/blog-placeholder-1.jpg" } = Astro.props;
window.getComputedStyle(css).opacity; window.getComputedStyle(css).opacity;
document.head.removeChild(css); document.head.removeChild(css);
setGiscusTheme();
} }
function preloadTheme() { function preloadTheme() {
@ -233,18 +220,6 @@ const { title, description, image = "/blog-placeholder-1.jpg" } = Astro.props;
} }
} }
const setGiscusTheme = () => {
const giscus = document.querySelector(".giscus-frame");
const isDark = document.documentElement.classList.contains("dark");
if (giscus) {
const url = new URL(giscus.src);
url.searchParams.set("theme", isDark ? "dark" : "light");
giscus.src = url.toString();
}
};
document.addEventListener("DOMContentLoaded", () => init()); document.addEventListener("DOMContentLoaded", () => init());
document.addEventListener("astro:after-swap", () => init()); document.addEventListener("astro:after-swap", () => init());
preloadTheme(); preloadTheme();

View file

@ -5,28 +5,28 @@ const { headings } = Astro.props;
const toc = buildToc(headings); const toc = buildToc(headings);
export interface Heading { export interface Heading {
depth: number; depth: number;
id: string; id: string;
text: string; text: string;
} }
function buildToc(headings: Heading[]) { function buildToc(headings: Heading[]) {
const toc: Heading[] = []; const toc: Heading[] = [];
const parentHeadings = new Map(); const parentHeadings = new Map();
headings.forEach((h) => { headings.forEach((h) => {
const heading = { ...h, subheadings: [] }; const heading = { ...h, subheadings: [] };
parentHeadings.set(heading.depth, heading); parentHeadings.set(heading.depth, heading);
if (heading.depth === 2) { if (heading.depth === 2) {
toc.push(heading); toc.push(heading);
} else { } else {
parentHeadings.get(heading.depth - 1).subheadings.push(heading); parentHeadings.get(heading.depth - 1).subheadings.push(heading);
} }
}); });
return toc; return toc;
} }
--- ---
<details open class="animate rounded-lg border border-black/15 dark:border-white/20"> <details open class="rounded-lg border border-black/15 dark:border-white/20">
<summary>Table of Contents</summary> <summary>Table of Contents</summary>
<nav class=""> <nav class="">
<ul class="py-3"> <ul class="py-3">

View file

@ -7,7 +7,9 @@ import Layout from "@layouts/Layout.astro";
<Layout title="404" description={SITE.DESCRIPTION}> <Layout title="404" description={SITE.DESCRIPTION}>
<Container> <Container>
<div class="text-center"> <div class="text-center">
<h4 class="animate text-2xl font-semibold text-black dark:text-white">404: Page not found</h4> <h4 class="text-2xl font-semibold text-black dark:text-white">
404: Page not found
</h4>
</div> </div>
</Container> </Container>
</Layout> </Layout>

View file

@ -50,23 +50,27 @@ const { Content, headings } = await render(post);
--- ---
<Layout title={post.data.title} description={post.data.description}> <Layout title={post.data.title} description={post.data.description}>
<Container> <Container>
<div class="my-10 space-y-1"> <div class="my-10 space-y-1">
<div class="animate flex items-center gap-1.5"> <div class="flex items-center gap-1.5">
<div class="font-base text-sm"> <div class="font-base text-sm">
<FormattedDate date={post.data.date} /> <FormattedDate date={post.data.date} />
</div> </div>
&bull; &bull;
{post.body && <div class="font-base text-sm">{readingTime(post.body)}</div>} {
</div> post.body && (
<h1 class="animate text-3xl font-semibold text-black dark:text-white"> <div class="font-base text-sm">{readingTime(post.body)}</div>
{post.data.title} )
</h1> }
</div> </div>
{headings.length > 0 && <TableOfContents headings={headings} />} <h1 class="text-3xl font-semibold text-black dark:text-white">
<article class="animate"> {post.data.title}
<Content /> </h1>
<PostNavigation prevPost={prevPost} nextPost={nextPost} /> </div>
</article> {headings.length > 0 && <TableOfContents headings={headings} />}
</Container> <article>
<Content />
<PostNavigation prevPost={prevPost} nextPost={nextPost} />
</article>
</Container>
</Layout> </Layout>

View file

@ -7,24 +7,24 @@ import { HOME } from "@consts";
import Layout from "@layouts/Layout.astro"; import Layout from "@layouts/Layout.astro";
const data = (await getCollection("blog")) const data = (await getCollection("blog"))
.filter((post) => !post.data.draft) .filter((post) => !post.data.draft)
.sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf()); .sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf());
type Acc = { type Acc = {
[year: string]: CollectionEntry<"blog">[]; [year: string]: CollectionEntry<"blog">[];
}; };
const posts = data.reduce((acc: Acc, post) => { const posts = data.reduce((acc: Acc, post) => {
const year = post.data.date.getFullYear().toString(); const year = post.data.date.getFullYear().toString();
if (!acc[year]) { if (!acc[year]) {
acc[year] = []; acc[year] = [];
} }
acc[year].push(post); acc[year].push(post);
return acc; return acc;
}, {}); }, {});
const years = Object.keys(posts).sort( const years = Object.keys(posts).sort(
(a, b) => Number.parseInt(b) - Number.parseInt(a), (a, b) => Number.parseInt(b) - Number.parseInt(a),
); );
--- ---
@ -35,8 +35,10 @@ const years = Object.keys(posts).sort(
<div class="space-y-4"> <div class="space-y-4">
{ {
years.map((year) => ( years.map((year) => (
<section class="animate space-y-4"> <section class="space-y-4">
<div class="font-semibold text-black dark:text-white">{year}</div> <div class="font-semibold text-black dark:text-white">
{year}
</div>
<div> <div>
<ul class="not-prose flex flex-col gap-4"> <ul class="not-prose flex flex-col gap-4">
{posts[year].map((post) => ( {posts[year].map((post) => (

View file

@ -56,14 +56,6 @@ article {
} }
} }
.animate {
@apply -translate-y-3 opacity-0;
@apply transition-all duration-300 ease-out;
}
.animate.show {
@apply translate-y-0 opacity-100;
}
html #back-to-top { html #back-to-top {
@apply pointer-events-none opacity-0; @apply pointer-events-none opacity-0;