refactor(styles): enhance glass effects, card designs, and transitions across components

- Replaced `client:only="react"` with `client:load transition:persist="header"` for `GlassHeader` to improve page transitions and header consistency.
- Updated card and surface designs with refined colors, borders, and shadows for a cleaner, modern look.
- Adjusted CSS variables for better contrast and distinct layers.
- Applied consistent blur and backdrop styles across components for visual cohesion.
This commit is contained in:
zguiyang
2026-03-14 12:43:11 +08:00
parent 56aac2f9f2
commit 043cdc6734
20 changed files with 49 additions and 47 deletions

View File

@@ -126,10 +126,10 @@ export default function GlassHeader({ lang: propLang }: GlassHeaderProps) {
<div className={`md:hidden overflow-hidden transition-all duration-300 ease-out ${
isMenuOpen ? 'max-h-80 opacity-100' : 'max-h-0 opacity-0'
}`}>
<div className={`py-4 px-4 border-t border-border/10 glass-effect ${
<div className={`py-4 px-4 border-t border-border/10 glass-effect shadow-xl ${
isScrolled
? 'bg-white/80 dark:bg-black/80 shadow-sm'
: 'bg-white/85 dark:bg-black/85'
? 'bg-white/90 dark:bg-black/80'
: 'bg-white/95 dark:bg-black/85'
}`}>
<nav className="flex flex-col space-y-3 text-sm font-medium">
{navItems.map((item) => {

View File

@@ -47,7 +47,7 @@ const statusColor = statusClassMap[project.status as keyof typeof statusClassMap
<article
data-project-card
data-type={project.type}
class="group flex flex-col overflow-hidden rounded-3xl border border-border/50 bg-card/50 backdrop-blur-sm transition-all duration-500 hover:-translate-y-2 hover:shadow-2xl hover:shadow-primary/5"
class="group flex flex-col overflow-hidden rounded-3xl border border-border/40 bg-card/60 backdrop-blur-md transition-all duration-500 hover:-translate-y-2 hover:shadow-2xl hover:shadow-primary/5"
>
{/* 顶部封面图区域 */}
<div class="relative aspect-[16/10] overflow-hidden">

View File

@@ -76,7 +76,7 @@ const readMoreText = lang === 'zh' ? '阅读更多' : 'Read More';
{posts.length > 0 ? (
posts.map((post, index) => (
<article class="group">
<div class="bg-card/50 backdrop-blur-sm rounded-2xl overflow-hidden border border-border hover:border-primary/50 transition-all duration-300 hover:transform hover:scale-[1.02]">
<div class="bg-card/60 backdrop-blur-md rounded-2xl overflow-hidden border border-border/40 hover:border-primary/50 transition-all duration-300 hover:transform hover:scale-[1.02] hover:shadow-xl hover:shadow-primary/5">
<div class="flex flex-col md:flex-row">
{/* Featured Image */}
<div class="relative overflow-hidden md:w-80 md:flex-shrink-0">

View File

@@ -41,7 +41,7 @@ const titles = {
const title = titles[lang] || titles[defaultLang];
---
<div class="bg-card/50 backdrop-blur-sm rounded-2xl p-6 border border-border">
<div class="bg-card/60 backdrop-blur-md rounded-2xl p-6 border border-border/40">
<h3 class="text-xl font-semibold text-card-foreground mb-4 flex items-center">
<Tag className="w-5 h-5 mr-2 text-primary" />
{title}
@@ -61,6 +61,6 @@ const title = titles[lang] || titles[defaultLang];
<div class="flex flex-col items-center justify-center py-6">
<p class="text-muted-foreground text-center">{lang === 'zh' ? '暂无分类' : 'No categories yet'}</p>
</div>
)
)}
</div>
</div>

View File

@@ -127,7 +127,7 @@ const getReadingTimeText = (minutes: number) => {
: tag.toLowerCase();
return (
<a href={`/${lang === 'en' ? '' : 'zh/'}blog/tags/${encodeURIComponent(tagRoute)}`} class="inline-flex items-center px-2.5 py-1 rounded-md text-xs font-medium bg-gray-100 text-gray-700 hover:bg-gray-200 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700 transition-colors border border-gray-200 dark:border-gray-600">
<a href={`/${lang === 'en' ? '' : 'zh/'}blog/tags/${encodeURIComponent(tagRoute)}`} class="inline-flex items-center px-2.5 py-1 rounded-md text-xs font-medium bg-muted text-muted-foreground hover:bg-accent hover:text-accent-foreground transition-colors border border-border">
# {tag}
</a>
);

View File

@@ -41,7 +41,7 @@ const titles = {
const title = titles[lang] || titles[defaultLang];
---
<div class="bg-card/50 backdrop-blur-sm rounded-2xl p-6 border border-border">
<div class="bg-card/60 backdrop-blur-md rounded-2xl p-6 border border-border/40">
<h3 class="text-xl font-semibold text-card-foreground mb-4 flex items-center">
<Hash className='w-5 h-5 mr-2 text-primary' />
{title}

View File

@@ -22,7 +22,7 @@ const lang = Astro.currentLocale as Lang || defaultLang;
</div>
<!-- Glass Header with navigation -->
<GlassHeader lang={lang} client:load />
<GlassHeader lang={lang} client:load transition:persist="header" />
<!-- Main content with proper spacing for fixed header -->
<div class="pt-16">

View File

@@ -43,7 +43,7 @@ const finalReadingTime = readTime ? parseInt(readTime.replace(/\D/g, '')) : unde
<Layout title={title} description={description}>
<!-- Glass Header with navigation -->
<GlassHeader lang={lang} client:load />
<GlassHeader lang={lang} client:load transition:persist="header" />
<!-- Main content with proper spacing for fixed header -->
<div class="pt-16 sm:pt-20">

View File

@@ -1,4 +1,5 @@
---
import { ClientRouter } from "astro:transitions";
import BackToTop from "@/components/ui/back-to-top";
import { useTranslations } from "@/i18n/utils";
import type { Lang } from "@/types/i18n";
@@ -26,6 +27,7 @@ const t = useTranslations(lang);
<meta name="description" content={description} />
<title>{title} | {t("site.title")}</title>
<!-- View Transitions for smooth page transitions -->
<ClientRouter />
<meta name="view-transition" content="same-origin" />
{
import.meta.env.MODE === 'production' && (

View File

@@ -37,7 +37,7 @@ const pageTitle = t("about.title");
---
<Layout title={pageTitle}>
<GlassHeader client:only="react" lang={lang} />
<GlassHeader client:load transition:persist="header" lang={lang} />
<main class="min-h-screen relative overflow-hidden pt-16 sm:pt-20">
<!-- Background Decor -->

View File

@@ -14,7 +14,7 @@ const pageTitle = lang === 'zh' ? '合作' : 'Hire Me';
---
<Layout title={pageTitle}>
<GlassHeader lang={lang} client:only="react" />
<GlassHeader lang={lang} client:load transition:persist="header" />
<main class="min-h-screen">
<!-- Hire Page Hero -->
<section class="py-24 relative overflow-hidden">

View File

@@ -43,7 +43,7 @@ const keyFacts = [
---
<Layout title={pageTitle}>
<GlassHeader client:only="react" lang={lang} />
<GlassHeader client:load transition:persist="header" lang={lang} />
<main class="min-h-screen">
<div class="relative overflow-hidden">

View File

@@ -14,7 +14,7 @@ const pageTitle = lang === 'zh' ? '现在' : 'Now';
---
<Layout title={pageTitle}>
<GlassHeader lang={lang} client:only="react" />
<GlassHeader lang={lang} client:load transition:persist="header" />
<main class="min-h-screen relative overflow-hidden">
<!-- 背景装饰 -->
<div class="absolute inset-0 -z-10">

View File

@@ -26,7 +26,7 @@ const filterOptions = [
---
<Layout title={pageTitle}>
<GlassHeader lang={lang} client:only="react" />
<GlassHeader lang={lang} client:load transition:persist="header" />
<main class="min-h-screen relative overflow-hidden">
<div
aria-hidden="true"

View File

@@ -37,7 +37,7 @@ const pageTitle = t("about.title");
---
<Layout title={pageTitle}>
<GlassHeader client:only="react" lang={lang} />
<GlassHeader client:load transition:persist="header" lang={lang} />
<main class="min-h-screen relative overflow-hidden pt-16 sm:pt-20">
<!-- Background Decor -->

View File

@@ -14,7 +14,7 @@ const pageTitle = lang === 'zh' ? '合作' : 'Hire Me';
---
<Layout title={pageTitle}>
<GlassHeader lang={lang} client:only="react" />
<GlassHeader lang={lang} client:load transition:persist="header" />
<main class="min-h-screen">
<!-- Hire Page Hero -->
<section class="py-24 relative overflow-hidden">

View File

@@ -42,7 +42,7 @@ const keyFacts = [
---
<Layout title={pageTitle}>
<GlassHeader client:only="react" lang={lang} />
<GlassHeader client:load transition:persist="header" lang={lang} />
<main class="min-h-screen">
<div class="relative overflow-hidden">

View File

@@ -14,7 +14,7 @@ const pageTitle = lang === 'zh' ? '现在' : 'Now';
---
<Layout title={pageTitle}>
<GlassHeader lang={lang} client:only="react" />
<GlassHeader lang={lang} client:load transition:persist="header" />
<main class="min-h-screen relative overflow-hidden">
<!-- 背景装饰 -->
<div class="absolute inset-0 -z-10">

View File

@@ -26,7 +26,7 @@ const filterOptions = [
---
<Layout title={pageTitle}>
<GlassHeader lang={lang} client:only="react" />
<GlassHeader lang={lang} client:load transition:persist="header" />
<main class="min-h-screen relative overflow-hidden">
<div
aria-hidden="true"

View File

@@ -44,23 +44,23 @@
:root {
--radius: 0.75rem;
--background: #F1F5F9; /* 更柔和的蓝灰色,不再是纯白或过于扎眼的浅色 */
--foreground: #1E293B;
--background: #F8FAFC; /* 稍微浅一点,增加与卡片的区分度 */
--foreground: #0F172A; /* 更深的颜色,提高对比度 */
--card: #FFFFFF;
--card-foreground: #1E293B;
--card-foreground: #0F172A;
--popover: #FFFFFF;
--popover-foreground: #1E293B;
--popover-foreground: #0F172A;
--primary: #2563EB;
--primary-foreground: #FFFFFF;
--secondary: #E4E4E7;
--secondary-foreground: #1E293B;
--muted: #F4F4F5;
--muted-foreground: #71717A;
--secondary: #F1F5F9;
--secondary-foreground: #0F172A;
--muted: #F1F5F9;
--muted-foreground: #64748B;
--accent: #F97316;
--accent-foreground: #FFFFFF;
--destructive: #EF4444;
--border: #E4E4E7;
--input: #E4E4E7;
--border: #E2E8F0;
--input: #E2E8F0;
--ring: #2563EB;
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
@@ -82,22 +82,22 @@
--gradient-primary: linear-gradient(135deg, #2563EB, #F97316);
--gradient-secondary: linear-gradient(135deg, #3B82F6, #10B981);
--gradient-accent: linear-gradient(135deg, #F97316, #FB923C);
--shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
--shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.12);
--shadow-xl: 0 12px 40px rgba(37, 99, 235, 0.15);
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
--animation-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);
--animation-smooth: cubic-bezier(0.65, 0, 0.35, 1);
--animation-spring: cubic-bezier(0.22, 1, 0.36, 1);
/* Global UI Design Tokens */
--ui-hero-overlay: linear-gradient(135deg, rgb(30 58 138 / 0.2), rgb(37 99 235 / 0.1), rgb(154 52 18 / 0.2));
--ui-title-gradient: linear-gradient(90deg, #111827 0%, var(--primary) 50%, #ea580c 100%);
--ui-surface-bg: rgb(248 250 252 / 0.75);
--ui-surface-border: rgb(228 228 231 / 0.7);
--ui-surface-shadow: var(--shadow-sm);
--ui-surface-blur: 10px;
--ui-section-soft-bg: rgb(37 99 235 / 0.05);
--ui-hero-overlay: linear-gradient(135deg, rgb(30 58 138 / 0.05), rgb(37 99 235 / 0.03), rgb(154 52 18 / 0.05));
--ui-title-gradient: linear-gradient(90deg, #0F172A 0%, #2563EB 50%, #ea580c 100%);
--ui-surface-bg: rgb(255 255 255 / 0.8);
--ui-surface-border: rgb(226 232 240 / 0.8);
--ui-surface-shadow: 0 4px 12px -2px rgb(0 0 0 / 0.05);
--ui-surface-blur: 12px;
--ui-section-soft-bg: rgb(37 99 235 / 0.03);
}
.dark {