Expanded transitions

This commit is contained in:
ClovertaTheTrilobita 2026-04-16 02:43:42 +03:00
parent 07a42ea123
commit 69e0e4e666
8 changed files with 78 additions and 56 deletions

View file

@ -12,14 +12,14 @@ const tags = data.tags;
<div class="post-link"> <div class="post-link">
<div class="post-text"> <div class="post-text">
<a href={data.url} class="post-title-link"> <a href={data.url} class="post-title-link">
<h2 class="post-title" transition:name={`post-title-${data.slug}`}> <h2 class="post-title" transition:name={`post-title-${data.postId}`}>
{data.title} {data.title}
</h2> </h2>
</a> </a>
<a href={data.url} class="post-description"> <a href={data.url} class="post-description">
{data.description} {data.description}
</a> </a>
<div class="tags"> <div class="tags" transition:name={`post-tags-${data.postId}`}>
{ {
tags.map((tag: string) => ( tags.map((tag: string) => (
<p class="tag"> <p class="tag">
@ -40,7 +40,13 @@ const tags = data.tags;
</div> </div>
<a href={data.url} class="post-image-link"> <a href={data.url} class="post-image-link">
<img src={data.img} alt={data.title} class="post-image" loading="lazy" /> <img
src={data.img}
alt={data.title}
class="post-image"
loading="lazy"
transition:name={`post-image-${data.postId}`}
/>
</a> </a>
</div> </div>
</li> </li>
@ -167,7 +173,7 @@ const tags = data.tags;
text-decoration: none; text-decoration: none;
font-weight: 400; font-weight: 400;
font-size: 0.92rem; font-size: 0.92rem;
font-style: italic; /* font-style: italic; */
} }
.post-meta-row { .post-meta-row {
@ -206,7 +212,7 @@ const tags = data.tags;
aspect-ratio: 16 / 10; aspect-ratio: 16 / 10;
object-fit: cover; object-fit: cover;
object-position: center; object-position: center;
border: 2px #94a0ab dashed; border: 1.5px #94a0ab dashed;
flex-shrink: 0; flex-shrink: 0;
display: block; display: block;
} }
@ -256,7 +262,7 @@ const tags = data.tags;
} }
.post-image { .post-image {
border: none; /* border: none; */
grid-area: image; grid-area: image;
width: 100%; width: 100%;
height: calc(145px * 10 / 16); height: calc(145px * 10 / 16);

View file

@ -39,6 +39,7 @@ const latestPosts = filteredPosts.slice(0, 7);
img={post.data.image.url} img={post.data.image.url}
tags={post.data.tags} tags={post.data.tags}
slug={slug} slug={slug}
postId={post.id}
/> />
); );
}) })

View file

@ -54,7 +54,7 @@ const groupedPosts = filteredPosts.reduce((acc: any[], post: any) => {
> >
<h2 <h2
class="post-title" class="post-title"
transition:name={`post-title-${slug}`} transition:name={`post-title-${post.id}`}
> >
{post.data.title} {post.data.title}
</h2> </h2>
@ -147,7 +147,8 @@ const groupedPosts = filteredPosts.reduce((acc: any[], post: any) => {
margin: 0; margin: 0;
font-size: 0.88rem; font-size: 0.88rem;
color: #555; color: #555;
font-style: italic; font-weight: 400;
/* font-style: italic; */
line-height: 1.5; line-height: 1.5;
overflow-wrap: anywhere; overflow-wrap: anywhere;
word-break: break-word; word-break: break-word;

View file

@ -70,15 +70,15 @@ const switchHref = "/" + segments.join("/");
} }
.lang-switch { .lang-switch {
color: black; !important color: black;
font-weight: 700; !important font-weight: 700;
font-size: 0.95rem; !important font-size: 0.95rem;
text-decoration: none; !important text-decoration: none;
line-height: 1; !important line-height: 1;
} }
.lang-switch:hover { .lang-switch:hover {
text-decoration: underline; !important text-decoration: underline;
} }
.sun { .sun {
@ -104,37 +104,37 @@ const switchHref = "/" + segments.join("/");
<script is:inline> <script is:inline>
function applyTheme() { function applyTheme() {
const localStorageTheme = localStorage?.getItem("theme") ?? ""; const localStorageTheme = localStorage?.getItem("theme") ?? "";
let theme = "light"; let theme = "light";
if (["dark", "light"].includes(localStorageTheme)) { if (["dark", "light"].includes(localStorageTheme)) {
theme = localStorageTheme; theme = localStorageTheme;
} else if (window.matchMedia("(prefers-color-scheme: dark)").matches) { } else if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
theme = "dark"; theme = "dark";
}
document.documentElement.classList.toggle("dark", theme === "dark");
window.localStorage.setItem("theme", theme);
} }
document.documentElement.classList.toggle("dark", theme === "dark"); function bindThemeToggle() {
window.localStorage.setItem("theme", theme); const button = document.getElementById("themeToggle");
} if (!button) return;
function bindThemeToggle() { button.onclick = () => {
const button = document.getElementById("themeToggle"); const element = document.documentElement;
if (!button) return; element.classList.toggle("dark");
button.onclick = () => { const isDark = element.classList.contains("dark");
const element = document.documentElement; localStorage.setItem("theme", isDark ? "dark" : "light");
element.classList.toggle("dark"); };
}
const isDark = element.classList.contains("dark");
localStorage.setItem("theme", isDark ? "dark" : "light");
};
}
applyTheme();
bindThemeToggle();
document.addEventListener("astro:after-swap", () => {
applyTheme(); applyTheme();
bindThemeToggle(); bindThemeToggle();
});
document.addEventListener("astro:after-swap", () => {
applyTheme();
bindThemeToggle();
});
</script> </script>

View file

@ -1,10 +1,11 @@
--- ---
import BaseLayout from "./BaseLayout.astro"; import BaseLayout from "./BaseLayout.astro";
import Remark42Embed from "@/components/Remark42Embed.astro"; import Remark42Embed from "@/components/Remark42Embed.astro";
import { fade } from "astro:transitions";
import { getLangFromUrl, getTranslations } from "@/i18n"; import { getLangFromUrl, getTranslations } from "@/i18n";
import "@/styles/global.css"; import "@/styles/global.css";
const { frontmatter, lang, postId } = Astro.props; const { frontmatter, lang, slug, postId } = Astro.props;
const comments = lang === "zh" ? "评论区" : "comments"; const comments = lang === "zh" ? "评论区" : "comments";
const t = getTranslations(lang); const t = getTranslations(lang);
--- ---
@ -14,7 +15,7 @@ const t = getTranslations(lang);
description={frontmatter.description} description={frontmatter.description}
image={frontmatter.image?.url} image={frontmatter.image?.url}
> >
<div id="reading-progress" aria-hidden="true"></div> <div id="reading-progress" aria-hidden="true"></div>
<a <a
href="/" href="/"
class="back-button" class="back-button"
@ -39,14 +40,18 @@ const t = getTranslations(lang);
<article class="post-article"> <article class="post-article">
<div class="post-header"> <div class="post-header">
<div class="post-meta"> <div class="post-meta">
<h1 class="post-title" transition:name={`post-title-${postId}`} >{frontmatter.title}</h1> <h1 class="post-title" transition:name={`post-title-${postId}`}>
<p class="description"><em>{frontmatter.description}</em></p> {frontmatter.title}
</h1>
<p class="description">
<em>{frontmatter.description}</em>
</p>
<p class="meta-line"> <p class="meta-line">
{t.post.publishedOn}: {frontmatter.pubDate.toLocaleDateString()} {t.post.publishedOn}: {frontmatter.pubDate.toLocaleDateString()}
</p> </p>
<p class="meta-line">{t.post.writtenBy}: {frontmatter.author}</p> <p class="meta-line">{t.post.writtenBy}: {frontmatter.author}</p>
<div class="tags"> <div class="tags" transition:name={`post-tags-${postId}`}>
{ {
frontmatter.tags.map((tag: string) => ( frontmatter.tags.map((tag: string) => (
<p class="tag"> <p class="tag">
@ -61,17 +66,18 @@ const t = getTranslations(lang);
src={frontmatter.image.url} src={frontmatter.image.url}
alt={frontmatter.image.alt} alt={frontmatter.image.alt}
class="post-cover" class="post-cover"
transition:name={`post-image-${postId}`}
/> />
</div> </div>
<div class="post-divider"></div> <div class="post-divider"></div>
<div class="post-content"> <div class="post-content" transition:animate={fade({ duration: "0.2s" })}>
<slot /> <slot />
</div> </div>
<h2>{comments}</h2> <h2>{comments}</h2>
<Remark42Embed slug={postId} /> <Remark42Embed slug={slug} />
</article> </article>
</BaseLayout> </BaseLayout>
@ -131,7 +137,7 @@ const t = getTranslations(lang);
backButton.dataset.bound = "true"; backButton.dataset.bound = "true";
} }
}; };
const updateProgress = () => { const updateProgress = () => {
const doc = document.documentElement; const doc = document.documentElement;
const scrollTop = window.scrollY || doc.scrollTop; const scrollTop = window.scrollY || doc.scrollTop;
const scrollHeight = doc.scrollHeight - window.innerHeight; const scrollHeight = doc.scrollHeight - window.innerHeight;
@ -152,7 +158,7 @@ const t = getTranslations(lang);
</script> </script>
<style> <style>
#reading-progress { #reading-progress {
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
@ -186,8 +192,8 @@ const t = getTranslations(lang);
/* opacity: 0; */ /* opacity: 0; */
transition: transition:
opacity 0.2s ease, opacity 0.2s ease,
transform 0.27s ease, transform 0.27s ease,
visibility 0.2s ease; visibility 0.2s ease,
box-shadow 0.2s ease, box-shadow 0.2s ease,
background 0.2s ease, background 0.2s ease,
color 0.2s ease; color 0.2s ease;
@ -284,10 +290,11 @@ const t = getTranslations(lang);
.post-cover { .post-cover {
width: 300px; width: 300px;
height: auto; height: auto;
aspect-ratio: 16 / 9; aspect-ratio: 16 / 10;
object-fit: cover; object-fit: cover;
object-position: center; object-position: center;
border-radius: 0.4rem; /* border-radius: 0.4rem; */
border: 1.5px #94a0ab dashed;
display: block; display: block;
} }
@ -346,6 +353,7 @@ const t = getTranslations(lang);
.post-cover { .post-cover {
width: 100%; width: 100%;
max-width: 100%; max-width: 100%;
aspect-ratio: 16 / 9;
} }
} }
</style> </style>

View file

@ -28,6 +28,11 @@ const [postLang, ...slugParts] = post.id.split("/");
const slug = slugParts.join("/"); const slug = slugParts.join("/");
--- ---
<MarkdownPostLayout frontmatter={post.data} lang={lang} postId={slug}> <MarkdownPostLayout
frontmatter={post.data}
lang={lang}
slug={slug}
postId={post.id}
>
<Content /> <Content />
</MarkdownPostLayout> </MarkdownPostLayout>

View file

@ -34,7 +34,7 @@ const t = getTranslations(lang);
<BaseLayout pageTitle={String(tag)}> <BaseLayout pageTitle={String(tag)}>
<p class="tag-heading"> <p class="tag-heading">
{lang === "zh" ? "带有标签" : "Posts tagged with"}{" "} {lang === "zh" ? "带有标签" : "Posts tagged with"}{" "}
<span class="tag-chip">{tag}</span> <span class="tag-chip" transition:name={`post-tags-${tag}`}>{tag}</span>
{lang === "zh" ? "的文章" : ""} {lang === "zh" ? "的文章" : ""}
</p> </p>
<ul> <ul>
@ -54,6 +54,7 @@ const t = getTranslations(lang);
date={formattedDate} date={formattedDate}
img={post.data.image.url} img={post.data.image.url}
tags={post.data.tags} tags={post.data.tags}
postId={post.id}
/> />
); );
}) })

View file

@ -15,14 +15,14 @@ const tags = [...new Set(allPosts.map((post: any) => post.data.tags).flat())];
const pageTitle = lang === "zh" ? "标签索引" : "Tag Index"; const pageTitle = lang === "zh" ? "标签索引" : "Tag Index";
--- ---
<BaseLayout pageTitle=`${pageTitle} - ${t.banner.title}` `> <BaseLayout pageTitle=`${pageTitle} - ${t.banner.title}`>
<h1>{t.tags.title}</h1> <h1>{t.tags.title}</h1>
<p>{t.tags.description}</p> <p>{t.tags.description}</p>
<div class="tags"> <div class="tags">
{ {
tags.map((tag) => ( tags.map((tag) => (
<p class="tag"> <p class="tag" transition:name={`post-tags-${tag}`}>
<a href={`/${lang}/tags/${tag}`}>{tag}</a> <a href={`/${lang}/tags/${tag}`}>{tag}</a>
</p> </p>
)) ))