feat(ui): add Container component and replace manual container divs

Implement a reusable Container component with size variants (sm, md, lg, xl, full) to standardize content width across the application. Replace all manual container divs with the new component for consistent styling and maintainability.
This commit is contained in:
joyzhao
2025-06-19 18:10:49 +08:00
parent b4a8d13cdd
commit 5fcf7a9d33
12 changed files with 97 additions and 46 deletions

View File

@@ -3,6 +3,7 @@ import BlogLayout from '../../layouts/BlogLayout.astro';
import BlogList from '../../components/blog/BlogList.astro';
import CategoryCard from '../../components/blog/CategoryCard.astro';
import TagCard from '../../components/blog/TagCard.astro';
import Container from '../../components/ui/Container';
import { type BlogPost } from '@/types';
import { type Lang } from '@/i18n/utils';
import { defaultLang } from '@/i18n/ui';
@@ -43,7 +44,7 @@ const sortedBlogPosts = sortPostsByDate(blogPosts);
<BlogLayout title="Blog - Joy Zhao" description="Dive into my thoughts on coding, tech trends, and developer life. Explore my latest posts below.">
<main class="min-h-screen">
<!-- Header Section -->
<div class="container mx-auto px-4 pt-24 pb-12">
<Container client:load size="md" className="pt-24 pb-12">
<div class="text-center mb-16">
<h1 class="text-5xl md:text-6xl font-bold bg-gradient-to-r from-foreground via-purple-600 to-purple-800 dark:from-foreground dark:via-purple-200 dark:to-purple-300 bg-clip-text text-transparent mb-6">
Our <span class="text-purple-500">Latest</span> Blog
@@ -52,10 +53,10 @@ const sortedBlogPosts = sortPostsByDate(blogPosts);
Dive into my thoughts on coding, tech trends, and developer life. Explore my latest posts below.
</p>
</div>
</div>
</Container>
<!-- Main Content -->
<div class="container mx-auto px-4 pb-20">
<Container client:load size="md" className="pb-20">
<div class="grid grid-cols-1 lg:grid-cols-4 gap-8">
<!-- 侧边栏 -->
<div class="lg:col-span-1 space-y-8">

View File

@@ -3,6 +3,7 @@ import Layout from "@/layouts/Layout.astro";
import GlassHeader from "@/components/GlassHeader";
import SkillsMarquee from "@/components/SkillsMarquee";
import Footer from "@/components/Footer";
import Container from "@/components/ui/Container";
import { useTranslations, type Lang } from "@/i18n/utils";
import { defaultLang } from "@/i18n/ui";
import { personalInfo, services } from "@/lib/data";
@@ -14,14 +15,14 @@ const pageTitle = t('site.title');
---
<Layout title={pageTitle}>
<GlassHeader client:only="react" />
<GlassHeader client:only="react" lang={lang} />
<main class="min-h-screen">
<!-- Hero Section - Inlined Content -->
<section class="py-32 relative overflow-hidden min-h-screen flex items-center">
<section class="py-32 relative overflow-hidden min-h-screen flex flex-col justify-center">
<!-- Background gradient -->
<div class="absolute inset-0 bg-gradient-to-br from-purple-900/20 via-purple-800/10 to-purple-700/20 dark:from-purple-900/30 dark:via-purple-800/20 dark:to-purple-700/30"></div>
<div class="container max-w-6xl mx-auto px-6 md:px-4 relative z-10">
<Container client:load size="md" className="relative z-10">
<div class="text-center mb-16">
<!-- Greeting -->
<div class="flex items-center justify-center mb-6">
@@ -162,14 +163,14 @@ const pageTitle = t('site.title');
</div>
</div>
</div>
</div>
</Container>
</section>
<SkillsMarquee lang={lang} client:only="react" />
<!-- Services Section - Inlined Content -->
<section id="services" class="py-20 px-4 bg-gradient-to-br from-slate-50 to-blue-50 dark:from-slate-900 dark:to-slate-800">
<div class="max-w-6xl mx-auto">
<section id="services" class="py-20 bg-gradient-to-br from-slate-50 to-blue-50 dark:from-slate-900 dark:to-slate-800">
<Container client:load size="md">
<h2 class="text-4xl font-bold text-center mb-16 bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">
Services I Offer
</h2>
@@ -196,7 +197,7 @@ const pageTitle = t('site.title');
</div>
))}
</div>
</div>
</Container>
</section>
<!-- About Section - Inlined Content -->
@@ -204,7 +205,7 @@ const pageTitle = t('site.title');
<!-- Background gradient -->
<div class="absolute inset-0 bg-gradient-to-br from-blue-900/10 via-purple-800/5 to-indigo-700/10 dark:from-blue-900/20 dark:via-purple-800/10 dark:to-indigo-700/20"></div>
<div class="container max-w-6xl mx-auto px-6 md:px-4 relative z-10">
<Container client:load size="md" className="relative z-10">
<div class="text-center mb-16">
<!-- Section Title -->
<div class="flex items-center justify-center mb-6">
@@ -331,15 +332,15 @@ const pageTitle = t('site.title');
</div>
</div>
</div>
</div>
</Container>
</section>
<!-- Projects Section - Inlined Content -->
<section id="projects" class="py-20 relative">
<!-- Background gradient -->
<div class="absolute inset-0 bg-gradient-to-b from-transparent via-purple-900/5 to-transparent"></div>
<div class="container max-w-6xl mx-auto px-6 md:px-4 relative z-10">
<Container client:load size="md" className="relative z-10">
<div class="text-center mb-16">
<h2 class="text-4xl md:text-5xl font-bold mb-4 bg-gradient-to-r from-purple-400 to-purple-600 bg-clip-text text-transparent">
Latest Projects
@@ -547,7 +548,7 @@ const pageTitle = t('site.title');
</div>
</div>
</div>
</div>
</Container>
</section>
</main>
<Footer lang={lang} client:only="react" />

View File

@@ -2,6 +2,7 @@
import Layout from "@/layouts/Layout.astro";
import GlassHeader from "@/components/GlassHeader";
import Footer from "@/components/Footer";
import Container from "@/components/ui/Container";
import { useTranslations, type Lang } from "@/i18n/utils";
import { defaultLang } from "@/i18n/ui";
import { projects } from "@/lib/data";
@@ -23,7 +24,7 @@ const currentProjects = projects[lang as keyof typeof projects] || projects.en;
<!-- Background gradient -->
<div class="absolute inset-0 bg-gradient-to-br from-purple-900/20 via-purple-800/10 to-purple-700/20 dark:from-purple-900/30 dark:via-purple-800/20 dark:to-purple-700/30"></div>
<div class="container max-w-6xl mx-auto px-6 md:px-4 relative z-10">
<Container client:load size="md" className="relative z-10">
<div class="text-center mb-16">
<!-- Main title -->
<h1 class="text-5xl md:text-6xl font-bold mb-6 bg-gradient-to-r from-gray-900 via-purple-600 to-purple-800 dark:from-white dark:via-purple-200 dark:to-purple-300 bg-clip-text text-transparent">
@@ -35,7 +36,7 @@ const currentProjects = projects[lang as keyof typeof projects] || projects.en;
{t('projects.description')}
</p>
</div>
</div>
</Container>
</section>
<!-- Projects Grid Section -->
@@ -43,7 +44,7 @@ const currentProjects = projects[lang as keyof typeof projects] || projects.en;
<!-- Background gradient -->
<div class="absolute inset-0 bg-gradient-to-b from-transparent via-purple-900/5 to-transparent"></div>
<div class="container max-w-6xl mx-auto px-6 md:px-4 relative z-10">
<Container client:load size="md" className="relative z-10">
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8 items-stretch">
{currentProjects.map((project) => (
<div class={`group overflow-hidden border border-${project.color}-500/20 hover:border-${project.color}-500/40 h-full flex flex-col transition-all duration-500 hover:scale-105 bg-white/10 dark:bg-gray-800/50 backdrop-blur-sm rounded-xl relative`}>

View File

@@ -3,6 +3,7 @@ import BlogLayout from '../../../layouts/BlogLayout.astro';
import BlogList from '../../../components/blog/BlogList.astro';
import CategoryCard from '../../../components/blog/CategoryCard.astro';
import TagCard from '../../../components/blog/TagCard.astro';
import Container from '../../../components/ui/Container';
import { type BlogPost } from '@/types';
import { type Lang } from '@/i18n/utils';
import { defaultLang } from '@/i18n/ui';
@@ -55,19 +56,19 @@ const tags = extractTags(allPostsArray);
<BlogLayout title="博客 - 赵桂阳" description="深入我对编程、技术趋势和开发者生活的思考。探索我的最新文章。">
<main class="min-h-screen">
<!-- 头部区域 -->
<div class="container mx-auto px-4 pt-24 pb-12">
<Container client:load size="md" className="pt-24 pb-12">
<div class="text-center mb-16">
<h1 class="text-5xl md:text-6xl font-bold bg-gradient-to-r from-foreground via-purple-600 to-purple-800 dark:from-foreground dark:via-purple-200 dark:to-purple-300 bg-clip-text text-transparent mb-6">
我的 <span class="text-purple-500">最新</span> 博客
我的<span class="text-purple-500">博客</span>
</h1>
<p class="text-xl text-muted-foreground max-w-3xl mx-auto">
深入我对编程、技术趋势和开发者生活的思考。探索我的最新文章。
</p>
</div>
</div>
</Container>
<!-- 主要内容 -->
<div class="container mx-auto px-4 pb-20">
<Container client:load size="md" className="pb-20">
<div class="grid grid-cols-1 lg:grid-cols-4 gap-8">
<!-- 侧边栏 -->
<div class="lg:col-span-1 space-y-8">

View File

@@ -3,6 +3,7 @@ import Layout from "@/layouts/Layout.astro";
import GlassHeader from "@/components/GlassHeader";
import SkillsMarquee from "@/components/SkillsMarquee";
import Footer from "@/components/Footer";
import Container from "@/components/ui/Container";
import { useTranslations, type Lang } from "@/i18n/utils";
import { defaultLang } from "@/i18n/ui";
import { personalInfo, services } from "@/lib/data";
@@ -14,14 +15,14 @@ const pageTitle = t('site.title');
---
<Layout title={pageTitle}>
<GlassHeader client:only="react" />
<GlassHeader client:only="react" lang={lang} />
<main class="min-h-screen">
<!-- Hero Section - Inlined Content -->
<section class="py-32 relative overflow-hidden min-h-screen flex items-center">
<section class="py-32 relative overflow-hidden min-h-screen flex flex-col justify-center">
<!-- Background gradient -->
<div class="absolute inset-0 bg-gradient-to-br from-purple-900/20 via-purple-800/10 to-purple-700/20 dark:from-purple-900/30 dark:via-purple-800/20 dark:to-purple-700/30"></div>
<div class="container max-w-6xl mx-auto px-6 md:px-4 relative z-10">
<Container client:load size="md" className="relative z-10">
<div class="text-center mb-16">
<!-- Greeting -->
<div class="flex items-center justify-center mb-6">
@@ -106,6 +107,7 @@ const pageTitle = t('site.title');
</a>
</div>
</div>
</Container>
<!-- Terminal mockup -->
<div class="max-w-4xl mx-auto">
@@ -162,14 +164,14 @@ const pageTitle = t('site.title');
</div>
</div>
</div>
</div>
</Container>
</section>
<SkillsMarquee lang={lang} client:only="react" />
<!-- Services Section - Inlined Content -->
<section id="services" class="py-20 px-4 bg-gradient-to-br from-slate-50 to-blue-50 dark:from-slate-900 dark:to-slate-800">
<div class="max-w-6xl mx-auto">
<Container client:load size="md">
<h2 class="text-4xl font-bold text-center mb-16 bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">
我提供的服务
</h2>
@@ -196,7 +198,7 @@ const pageTitle = t('site.title');
</div>
))}
</div>
</div>
</Container>
</section>
<!-- About Section - Inlined Content -->
@@ -204,7 +206,7 @@ const pageTitle = t('site.title');
<!-- Background gradient -->
<div class="absolute inset-0 bg-gradient-to-br from-blue-900/10 via-purple-800/5 to-indigo-700/10 dark:from-blue-900/20 dark:via-purple-800/10 dark:to-indigo-700/20"></div>
<div class="container max-w-6xl mx-auto px-6 md:px-4 relative z-10">
<Container client:load size="md" className="relative z-10">
<div class="text-center mb-16">
<!-- Section Title -->
<div class="flex items-center justify-center mb-6">
@@ -331,7 +333,7 @@ const pageTitle = t('site.title');
</div>
</div>
</div>
</div>
</Container>
</section>
<!-- Projects Section - Inlined Content -->
@@ -339,7 +341,7 @@ const pageTitle = t('site.title');
<!-- Background gradient -->
<div class="absolute inset-0 bg-gradient-to-b from-transparent via-purple-900/5 to-transparent"></div>
<div class="container max-w-6xl mx-auto px-6 md:px-4 relative z-10">
<Container client:load size="md" className="relative z-10">
<div class="text-center mb-16">
<h2 class="text-4xl md:text-5xl font-bold mb-4 bg-gradient-to-r from-purple-400 to-purple-600 bg-clip-text text-transparent">
我的项目
@@ -539,7 +541,7 @@ const pageTitle = t('site.title');
</div>
</div>
</div>
</div>
</Container>
</section>
</main>
<Footer lang={lang} client:load />

View File

@@ -2,6 +2,7 @@
import Layout from "@/layouts/Layout.astro";
import GlassHeader from "@/components/GlassHeader";
import Footer from "@/components/Footer";
import Container from "@/components/ui/Container";
import { useTranslations, type Lang } from "@/i18n/utils";
import { defaultLang } from "@/i18n/ui";
import { projects } from "@/lib/data";
@@ -16,14 +17,14 @@ const currentProjects = projects[lang as keyof typeof projects] || projects.en;
---
<Layout title={pageTitle}>
<GlassHeader client:only="react" />
<GlassHeader lang={lang} client:only="react" />
<main class="min-h-screen">
<!-- Projects Hero Section -->
<section class="py-24 relative overflow-hidden">
<!-- Background gradient -->
<div class="absolute inset-0 bg-gradient-to-br from-purple-900/20 via-purple-800/10 to-purple-700/20 dark:from-purple-900/30 dark:via-purple-800/20 dark:to-purple-700/30"></div>
<div class="container max-w-6xl mx-auto px-6 md:px-4 relative z-10">
<Container client:load size="md" className="relative z-10">
<div class="text-center mb-16">
<!-- Main title -->
<h1 class="text-5xl md:text-6xl font-bold mb-6 bg-gradient-to-r from-gray-900 via-purple-600 to-purple-800 dark:from-white dark:via-purple-200 dark:to-purple-300 bg-clip-text text-transparent">
@@ -35,7 +36,7 @@ const currentProjects = projects[lang as keyof typeof projects] || projects.en;
{t('projects.description')}
</p>
</div>
</div>
</Container>
</section>
<!-- Projects Grid Section -->
@@ -43,7 +44,7 @@ const currentProjects = projects[lang as keyof typeof projects] || projects.en;
<!-- Background gradient -->
<div class="absolute inset-0 bg-gradient-to-b from-transparent via-purple-900/5 to-transparent"></div>
<div class="container max-w-6xl mx-auto px-6 md:px-4 relative z-10">
<Container client:load size="md" className="relative z-10">
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8 items-stretch">
{currentProjects.map((project) => (
<div class={`group overflow-hidden border border-${project.color}-500/20 hover:border-${project.color}-500/40 h-full flex flex-col transition-all duration-500 hover:scale-105 bg-white/10 dark:bg-gray-800/50 backdrop-blur-sm rounded-xl relative`}>