feat(blog): restore typography ratios and implement smooth filter animations
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 6s
Build & Deploy / 🧪 QA (push) Failing after 1m13s
Build & Deploy / 🏗️ Build (push) Failing after 10m57s
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🩺 Health Check (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 1s

This commit is contained in:
2026-02-17 22:52:53 +01:00
parent d41d4d3d89
commit 786d35010b
8 changed files with 152 additions and 114 deletions

View File

@@ -83,7 +83,7 @@ export default async function BlogPostPage({
/>
<Section containerVariant="wide" className="pt-0 md:pt-0">
<div className="max-w-3xl mx-auto px-5 md:px-0">
<div className="max-w-4xl mx-auto px-5 md:px-0">
<Reveal delay={0.4} width="100%">
{post.tags && post.tags.length > 0 && (
<div className="flex flex-wrap gap-2 mb-10 md:mb-12">
@@ -98,7 +98,7 @@ export default async function BlogPostPage({
</div>
)}
<div className="max-w-none">
<div className="article-content max-w-none">
<MDXRemote
source={post.body.raw.replace(/^---[\s\S]*?\n---\s*/, '')}
components={MDXComponents}

View File

@@ -11,6 +11,8 @@ import { Section } from "../../src/components/Section";
import { AbstractCircuit, GradientMesh } from "../../src/components/Effects";
import { useAnalytics } from "../../src/components/analytics/useAnalytics";
import { motion, AnimatePresence } from "framer-motion";
export default function BlogPage() {
const [searchQuery, setSearchQuery] = useState("");
const [activeTags, setActiveTags] = useState<string[]>([]);
@@ -133,35 +135,55 @@ export default function BlogPage() {
<div className="space-y-12 relative z-10 p-4 md:p-0">
{/* Posts List (Vertical & Minimal) */}
<div id="posts-container" className="space-y-12">
{postsToShow.length === 0 ? (
<div className="py-24 text-center border border-dashed border-slate-200 rounded-3xl bg-white/50">
<p className="text-slate-400 font-mono text-sm uppercase tracking-widest">
Keine Beiträge gefunden.
</p>
<button
onClick={() => {
setSearchQuery("");
setActiveTags([]);
}}
className="mt-4 text-xs font-bold text-slate-900 underline underline-offset-4 hover:text-slate-600"
<AnimatePresence mode="popLayout" initial={false}>
{postsToShow.length === 0 ? (
<motion.div
key="no-results"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, scale: 0.95 }}
className="py-24 text-center border border-dashed border-slate-200 rounded-3xl bg-white/50"
>
Filter zurücksetzen
</button>
</div>
) : (
<div className="grid grid-cols-1 gap-6 w-full">
{postsToShow.map((post, i) => (
<Reveal
key={post.slug}
delay={0.05 * i}
width="100%"
viewport={{ once: true, margin: "20% 0px" }} // Added more margin for better back-navigation detection
<p className="text-slate-400 font-mono text-sm uppercase tracking-widest">
Keine Beiträge gefunden.
</p>
<button
onClick={() => {
setSearchQuery("");
setActiveTags([]);
}}
className="mt-4 text-xs font-bold text-slate-900 underline underline-offset-4 hover:text-slate-600"
>
<MediumCard post={post} />
</Reveal>
))}
</div>
)}
Filter zurücksetzen
</button>
</motion.div>
) : (
<motion.div
key="post-grid"
layout
className="grid grid-cols-1 gap-6 w-full"
>
<AnimatePresence mode="popLayout">
{postsToShow.map((post, i) => (
<motion.div
key={post.slug}
layout
initial={{ opacity: 0, scale: 0.9 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.9 }}
transition={{
duration: 0.4,
delay: i < 8 ? i * 0.05 : 0,
ease: [0.16, 1, 0.3, 1]
}}
>
<MediumCard post={post} />
</motion.div>
))}
</AnimatePresence>
</motion.div>
)}
</AnimatePresence>
{/* Pagination */}
{hasMore && (