refactor(about): modernize and unify About pages with improved design and translations

- Replaced `.mdx` files for `about` pages with `.astro` format to streamline layout and enhance flexibility.
- Integrated `GlassHeader`, `HighlightBox`, and other reusable components for consistency.
- Enhanced design with dynamic backgrounds, gradients, and interactive hover effects.
- Updated i18n translations to support structured nested keys for improved localization and scalability.
- Refined contact and skills sections with responsive layouts and clearer organization.
This commit is contained in:
zguiyang
2026-03-14 12:05:23 +08:00
parent 8ff4074c1b
commit a8ab7e6811
6 changed files with 460 additions and 155 deletions

169
src/pages/about.astro Normal file
View File

@@ -0,0 +1,169 @@
---
import Layout from "@/layouts/Layout.astro";
import GlassHeader from "@/components/GlassHeader";
import Footer from "@/components/Footer";
import Container from "@/components/ui/Container.astro";
import HighlightBox from "@/components/markdown/HighlightBox.astro";
import { useTranslations } from "@/i18n/utils";
import type { Lang } from "@/types/i18n";
import { defaultLang } from "@/i18n/ui";
import { Sparkles, Heart, Zap, Mail, MessageSquare } from "lucide-react";
const lang = (Astro.currentLocale as Lang) || defaultLang;
const t = useTranslations(lang);
const pageTitle = t("about.title");
---
<Layout title={pageTitle}>
<GlassHeader client:only="react" lang={lang} />
<main class="min-h-screen relative overflow-hidden pt-16 sm:pt-20">
<!-- Background Decor -->
<div class="fixed inset-0 -z-10 h-full w-full bg-background">
<div class="absolute inset-0 bg-gradient-to-br from-primary/5 via-transparent to-primary/5 dark:from-primary/10 dark:via-transparent dark:to-primary/5"></div>
</div>
<!-- Hero Section -->
<section class="relative z-10 py-16 md:py-24">
<Container>
<div class="max-w-4xl mx-auto">
<div class="flex flex-col md:flex-row items-center gap-12 mb-16">
<div class="relative group">
<div class="absolute -inset-1 rounded-full bg-gradient-to-r from-primary to-purple-600 opacity-75 blur transition duration-1000 group-hover:opacity-100 group-hover:duration-200"></div>
<div class="relative h-48 w-48 rounded-full border-4 border-background overflow-hidden bg-muted">
<img
src="/avatar.png"
alt="Joy Zhao"
class="h-full w-full object-cover transition-transform duration-500 group-hover:scale-110"
onerror="this.src='https://ui-avatars.com/api/?name=Joy+Zhao&background=0D8ABC&color=fff&size=200'"
/>
</div>
</div>
<div class="text-center md:text-left space-y-6">
<h1 class="text-4xl md:text-6xl font-bold tracking-tight">
<span class="bg-gradient-to-r from-foreground to-foreground/70 bg-clip-text text-transparent">
{t('about.title')}
</span>
</h1>
<p class="text-xl text-muted-foreground leading-relaxed">
{t('about.description')}
</p>
</div>
</div>
<div class="grid gap-8">
<!-- Intro Box -->
<HighlightBox type="tip" title={t('about.intro.title')}>
<div class="space-y-4 py-2">
<p class="text-lg leading-relaxed whitespace-pre-line">{t('about.intro.content')}</p>
<div class="p-4 rounded-xl bg-primary/5 border border-primary/10 italic text-primary/80">
{t('about.intro.belief')}
</div>
</div>
</HighlightBox>
<!-- Self Intro -->
<div class="page-surface p-8 rounded-2xl border bg-card/40 backdrop-blur-md space-y-6">
<h2 class="text-2xl font-bold flex items-center gap-3">
<Sparkles className="w-6 h-6 text-primary" />
{t('about.me.title')}
</h2>
<div class="prose dark:prose-invert max-w-none">
<p class="text-lg leading-relaxed text-muted-foreground whitespace-pre-line">
{t('about.me.content')}
</p>
</div>
</div>
<!-- Skills Grid -->
<div class="grid md:grid-cols-2 gap-8">
<div class="page-surface p-8 rounded-2xl border bg-card/40 backdrop-blur-md space-y-6">
<h2 class="text-2xl font-bold flex items-center gap-3">
<Zap className="w-6 h-6 text-yellow-500" />
{t('about.skills.mastered.title')}
</h2>
<ul class="space-y-3">
{(t('about.skills.mastered.items') as unknown as string[]).map((item: string) => (
<li class="flex items-start gap-3 text-muted-foreground">
<span class="mt-1.5 h-1.5 w-1.5 shrink-0 rounded-full bg-primary"></span>
<span>{item}</span>
</li>
))}
</ul>
</div>
<div class="page-surface p-8 rounded-2xl border bg-card/40 backdrop-blur-md space-y-6">
<h2 class="text-2xl font-bold flex items-center gap-3">
<Heart className="w-6 h-6 text-red-500" />
{t('about.skills.learning.title')}
</h2>
<ul class="space-y-3">
{(t('about.skills.learning.items') as unknown as string[]).map((item: string) => (
<li class="flex items-start gap-3 text-muted-foreground">
<span class="mt-1.5 h-1.5 w-1.5 shrink-0 rounded-full bg-muted-foreground/30"></span>
<span>{item}</span>
</li>
))}
</ul>
</div>
</div>
<!-- Interests -->
<div class="page-surface p-8 rounded-2xl border bg-card/40 backdrop-blur-md space-y-8">
<h2 class="text-2xl font-bold">
{t('about.interests.title')}
</h2>
<div class="grid sm:grid-cols-2 gap-6">
{(t('about.interests.items') as unknown as any[]).map((item) => (
<div class="p-4 rounded-xl bg-muted/30 border border-border/50 transition-colors hover:bg-muted/50">
<h3 class="font-bold mb-2">{item.title}</h3>
<p class="text-sm text-muted-foreground leading-relaxed">{item.content}</p>
</div>
))}
</div>
</div>
<!-- Contact -->
<div class="page-surface p-8 rounded-2xl border bg-card/40 backdrop-blur-md space-y-8 overflow-hidden relative">
<div class="absolute top-0 right-0 p-8 opacity-5">
<Mail className="w-32 h-32" />
</div>
<div class="relative z-10 space-y-6">
<h2 class="text-2xl font-bold flex items-center gap-3">
<MessageSquare className="w-6 h-6 text-primary" />
{t('about.contact.title')}
</h2>
<HighlightBox type="warning" title={lang === 'zh' ? '注意' : 'Notice'}>
{t('about.contact.warning')}
</HighlightBox>
<div class="grid sm:grid-cols-3 gap-4 mt-8">
<div class="flex flex-col p-4 rounded-xl bg-muted/30 border border-border/50 items-center text-center gap-2">
<Mail className="w-5 h-5 text-primary" />
<span class="text-xs font-medium text-muted-foreground uppercase tracking-wider">Email</span>
<span class="text-sm font-semibold break-all">{(t('about.contact.methods.email') as string).split('')[1] || (t('about.contact.methods.email') as string).split(': ')[1]}</span>
</div>
<div class="flex flex-col p-4 rounded-xl bg-muted/30 border border-border/50 items-center text-center gap-2">
<span class="font-bold text-primary">QQ</span>
<span class="text-xs font-medium text-muted-foreground uppercase tracking-wider">QQ</span>
<span class="text-sm font-semibold">{(t('about.contact.methods.qq') as string).split('')[1] || (t('about.contact.methods.qq') as string).split(': ')[1]}</span>
</div>
<div class="flex flex-col p-4 rounded-xl bg-muted/30 border border-border/50 items-center text-center gap-2">
<MessageSquare className="w-5 h-5 text-primary" />
<span class="text-xs font-medium text-muted-foreground uppercase tracking-wider">WeChat</span>
<span class="text-sm font-semibold">{(t('about.contact.methods.wechat') as string).split('')[1] || (t('about.contact.methods.wechat') as string).split(': ')[1]}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</Container>
</section>
</main>
<Footer client:load lang={lang} />
</Layout>