feat(projects): add project tags and improve project cards layout

- Add project type tags (business, opensource, personal) to project cards
- Update i18n translations for new project tags and visit/demo labels
- Improve tech stack indicators styling with unified gray theme
- Simplify project card footer links to use translation labels
- Update project descriptions and tech stack details
This commit is contained in:
joyzhao
2025-06-16 19:26:05 +08:00
parent 9ad2651dd2
commit f31fbb20a6
3 changed files with 126 additions and 120 deletions

View File

@@ -17,7 +17,12 @@ export const ui = {
'site.description': 'Full Stack Developer specializing in React, Node.js, and modern web technologies', 'site.description': 'Full Stack Developer specializing in React, Node.js, and modern web technologies',
'hero.githubLink': 'GitHub Profile', 'hero.githubLink': 'GitHub Profile',
'hero.linkedinLink': 'LinkedIn Profile', 'hero.linkedinLink': 'LinkedIn Profile',
'footer.rights': 'All rights reserved' 'footer.rights': 'All rights reserved',
'project.tag.business': 'Business Project',
'project.tag.opensource': 'Open Source',
'project.tag.personal': 'Personal Product',
'project.visit': 'Visit',
'project.demo': 'Live Demo'
// Projects and services content has been inlined into respective page files // Projects and services content has been inlined into respective page files
// to reduce reliance on the translation system and improve maintainability // to reduce reliance on the translation system and improve maintainability
}, },
@@ -31,7 +36,12 @@ export const ui = {
'site.description': '专注于 React、Node.js 和现代 Web 技术的全栈开发者', 'site.description': '专注于 React、Node.js 和现代 Web 技术的全栈开发者',
'hero.githubLink': 'GitHub 主页', 'hero.githubLink': 'GitHub 主页',
'hero.linkedinLink': 'LinkedIn 主页', 'hero.linkedinLink': 'LinkedIn 主页',
'footer.rights': '版权所有' 'footer.rights': '版权所有',
'project.tag.business': '商业项目',
'project.tag.opensource': '开源项目',
'project.tag.personal': '个人产品',
'project.visit': '访问',
'project.demo': '在线演示'
// Projects and services content has been inlined into respective page files // Projects and services content has been inlined into respective page files
// to reduce reliance on the translation system and improve maintainability // to reduce reliance on the translation system and improve maintainability
} }

View File

@@ -400,9 +400,14 @@ const pageTitle = t('site.title');
</p> </p>
</div> </div>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8"> <div class="grid grid-cols-1 lg:grid-cols-3 gap-8 items-stretch">
<!-- Taskify App Project --> <!-- Taskify App Project -->
<div class="group overflow-hidden border border-purple-500/20 hover:border-purple-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"> <div class="group overflow-hidden border border-purple-500/20 hover:border-purple-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">
<!-- Project tag - positioned at top right -->
<div class="absolute top-4 right-4 z-10">
<span class="px-3 py-1 bg-blue-100 dark:bg-blue-800 text-blue-800 dark:text-blue-200 text-xs rounded-full font-medium border border-blue-200 dark:border-blue-700">{t('project.tag.business')}</span>
</div>
<!-- Project image placeholder --> <!-- Project image placeholder -->
<div class="h-48 bg-gradient-to-br from-purple-500/20 to-purple-600/20 relative overflow-hidden"> <div class="h-48 bg-gradient-to-br from-purple-500/20 to-purple-600/20 relative overflow-hidden">
<div class="absolute inset-0 bg-gradient-to-br from-purple-500/10 to-purple-600/10 group-hover:from-purple-500/20 group-hover:to-purple-600/20 transition-all duration-500"></div> <div class="absolute inset-0 bg-gradient-to-br from-purple-500/10 to-purple-600/10 group-hover:from-purple-500/20 group-hover:to-purple-600/20 transition-all duration-500"></div>
@@ -424,7 +429,11 @@ const pageTitle = t('site.title');
<div class="space-y-3"> <div class="space-y-3">
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300"> <div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
<span class="text-purple-500 mt-1">•</span> <span class="text-purple-500 mt-1">•</span>
<span>A task management app with real-time collaboration, built using React, Node.js, and MongoDB.</span> <span>A comprehensive task management application with drag-and-drop functionality.</span>
</div>
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
<span class="text-purple-500 mt-1">•</span>
<span>Built with React, TypeScript, and Tailwind CSS for modern development.</span>
</div> </div>
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300"> <div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
<span class="text-purple-500 mt-1">•</span> <span class="text-purple-500 mt-1">•</span>
@@ -436,38 +445,36 @@ const pageTitle = t('site.title');
</div> </div>
</div> </div>
<!-- Tech stack indicators --> <!-- Tech stack indicators with unified gray styling -->
<div class="mt-6 flex flex-wrap gap-2"> <div class="mt-6 mb-4 flex flex-wrap gap-2">
<span class="px-2 py-1 bg-blue-500/20 text-blue-400 text-xs rounded-full">React</span> <span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">React</span>
<span class="px-2 py-1 bg-green-500/20 text-green-400 text-xs rounded-full">Node.js</span> <span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Node.js</span>
<span class="px-2 py-1 bg-purple-500/20 text-purple-400 text-xs rounded-full">MongoDB</span> <span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">MongoDB</span>
</div> </div>
</div> </div>
<div class="p-6 pt-4 border-t border-border/30"> <div class="p-6 pt-4 border-t border-border/30">
<div class="flex items-center justify-between w-full"> <div class="flex justify-center">
<a <a
href="https://github.com/joyzhao/taskify-app" href="https://github.com/zhaoguiyang/taskify-app"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="flex items-center gap-2 text-sm text-muted-foreground hover:text-purple-400 transition-colors group/link" class="flex items-center gap-2 text-sm text-purple-400 hover:text-purple-300 transition-colors group/link"
> >
<svg class="h-4 w-4 group-hover/link:rotate-12 transition-transform duration-300" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
</svg>
View on GitHub
</a>
<button class="flex items-center gap-2 text-sm text-purple-400 hover:text-purple-300 transition-colors">
<span>🔗</span> <span>🔗</span>
Live Demo {t('project.visit')}
</button> </a>
</div> </div>
</div> </div>
</div> </div>
<!-- E-Shop Platform Project --> <!-- E-Shop Platform Project -->
<div class="group overflow-hidden border border-purple-500/20 hover:border-purple-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"> <div class="group overflow-hidden border border-purple-500/20 hover:border-purple-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">
<!-- Project tag - positioned at top right -->
<div class="absolute top-4 right-4 z-10">
<span class="px-3 py-1 bg-green-100 dark:bg-green-800 text-green-800 dark:text-green-200 text-xs rounded-full font-medium border border-green-200 dark:border-green-700">{t('project.tag.opensource')}</span>
</div>
<!-- Project image placeholder --> <!-- Project image placeholder -->
<div class="h-48 bg-gradient-to-br from-purple-500/20 to-purple-600/20 relative overflow-hidden"> <div class="h-48 bg-gradient-to-br from-purple-500/20 to-purple-600/20 relative overflow-hidden">
<div class="absolute inset-0 bg-gradient-to-br from-purple-500/10 to-purple-600/10 group-hover:from-purple-500/20 group-hover:to-purple-600/20 transition-all duration-500"></div> <div class="absolute inset-0 bg-gradient-to-br from-purple-500/10 to-purple-600/10 group-hover:from-purple-500/20 group-hover:to-purple-600/20 transition-all duration-500"></div>
@@ -480,7 +487,7 @@ const pageTitle = t('site.title');
<div class="p-6 pb-4"> <div class="p-6 pb-4">
<h3 class="text-xl group-hover:text-purple-400 transition-colors duration-300 flex items-center gap-2 font-bold mb-4"> <h3 class="text-xl group-hover:text-purple-400 transition-colors duration-300 flex items-center gap-2 font-bold mb-4">
<span class="text-purple-500">📱</span> <span class="text-purple-500">🛒</span>
E-Shop Platform E-Shop Platform
</h3> </h3>
</div> </div>
@@ -489,50 +496,52 @@ const pageTitle = t('site.title');
<div class="space-y-3"> <div class="space-y-3">
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300"> <div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
<span class="text-purple-500 mt-1">•</span> <span class="text-purple-500 mt-1">•</span>
<span>A scalable e-commerce platform with Next.js, Stripe payments, and TailwindCSS.</span> <span>Modern e-commerce solution with comprehensive features for online retail.</span>
</div> </div>
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300"> <div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
<span class="text-purple-500 mt-1">•</span> <span class="text-purple-500 mt-1">•</span>
<span>Integrated Stripe payment processing for secure transactions.</span> <span>Built with Next.js, Prisma, and Stripe for seamless payment processing.</span>
</div> </div>
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300"> <div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
<span class="text-purple-500 mt-1">•</span> <span class="text-purple-500 mt-1">•</span>
<span>Advanced product catalog with search, filtering, and recommendation features.</span> <span>Features shopping cart, payment integration, and admin dashboard.</span>
</div>
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
<span class="text-purple-500 mt-1">•</span>
<span>Responsive design with optimized performance and SEO capabilities.</span>
</div> </div>
</div> </div>
<!-- Tech stack indicators --> <!-- Tech stack indicators with unified gray styling -->
<div class="mt-6 flex flex-wrap gap-2"> <div class="mt-6 mb-4 flex flex-wrap gap-2">
<span class="px-2 py-1 bg-blue-500/20 text-blue-400 text-xs rounded-full">Next.js</span> <span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Next.js</span>
<span class="px-2 py-1 bg-yellow-500/20 text-yellow-400 text-xs rounded-full">Stripe</span> <span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Stripe</span>
<span class="px-2 py-1 bg-cyan-500/20 text-cyan-400 text-xs rounded-full">TailwindCSS</span> <span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">TailwindCSS</span>
</div> </div>
</div> </div>
<div class="p-6 pt-4 border-t border-border/30"> <div class="p-6 pt-4 border-t border-border/30">
<div class="flex items-center justify-between w-full"> <div class="flex justify-center">
<a <a
href="https://github.com/joyzhao/e-commerce-platform" href="https://github.com/zhaoguiyang/e-shop-platform"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="flex items-center gap-2 text-sm text-muted-foreground hover:text-purple-400 transition-colors group/link" class="flex items-center gap-2 text-sm text-green-400 hover:text-green-300 transition-colors group/link"
> >
<svg class="h-4 w-4 group-hover/link:rotate-12 transition-transform duration-300" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
</svg>
View on GitHub
</a>
<button class="flex items-center gap-2 text-sm text-purple-400 hover:text-purple-300 transition-colors">
<span>🔗</span> <span>🔗</span>
Live Demo {t('project.visit')}
</button> </a>
</div> </div>
</div> </div>
</div> </div>
<!-- Portfolio Site Project --> <!-- Portfolio Site Project -->
<div class="group overflow-hidden border border-purple-500/20 hover:border-purple-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"> <div class="group overflow-hidden border border-purple-500/20 hover:border-purple-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">
<!-- Project tag - positioned at top right -->
<div class="absolute top-4 right-4 z-10">
<span class="px-3 py-1 bg-amber-100 dark:bg-amber-800 text-amber-800 dark:text-amber-200 text-xs rounded-full font-medium border border-amber-200 dark:border-amber-700">{t('project.tag.personal')}</span>
</div>
<!-- Project image placeholder --> <!-- Project image placeholder -->
<div class="h-48 bg-gradient-to-br from-purple-500/20 to-purple-600/20 relative overflow-hidden"> <div class="h-48 bg-gradient-to-br from-purple-500/20 to-purple-600/20 relative overflow-hidden">
<div class="absolute inset-0 bg-gradient-to-br from-purple-500/10 to-purple-600/10 group-hover:from-purple-500/20 group-hover:to-purple-600/20 transition-all duration-500"></div> <div class="absolute inset-0 bg-gradient-to-br from-purple-500/10 to-purple-600/10 group-hover:from-purple-500/20 group-hover:to-purple-600/20 transition-all duration-500"></div>
@@ -545,7 +554,7 @@ const pageTitle = t('site.title');
<div class="p-6 pb-4"> <div class="p-6 pb-4">
<h3 class="text-xl group-hover:text-purple-400 transition-colors duration-300 flex items-center gap-2 font-bold mb-4"> <h3 class="text-xl group-hover:text-purple-400 transition-colors duration-300 flex items-center gap-2 font-bold mb-4">
<span class="text-purple-500">📱</span> <span class="text-purple-500">🎨</span>
Portfolio Site Portfolio Site
</h3> </h3>
</div> </div>
@@ -554,44 +563,37 @@ const pageTitle = t('site.title');
<div class="space-y-3"> <div class="space-y-3">
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300"> <div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
<span class="text-purple-500 mt-1">•</span> <span class="text-purple-500 mt-1">•</span>
<span>My personal portfolio showcasing my work, built with HTML, TailwindCSS, and Alpine.js.</span> <span>Responsive personal portfolio website showcasing creative work and projects.</span>
</div> </div>
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300"> <div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
<span class="text-purple-500 mt-1">•</span> <span class="text-purple-500 mt-1">•</span>
<span>Modern glassmorphism design with smooth animations and transitions.</span> <span>Built with Astro, React, and Tailwind CSS for optimal performance.</span>
</div> </div>
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300"> <div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
<span class="text-purple-500 mt-1">•</span> <span class="text-purple-500 mt-1">•</span>
<span>Fully responsive layout optimized for all device sizes.</span> <span>Features dark mode support and smooth animations for enhanced UX.</span>
</div> </div>
</div> </div>
<!-- Tech stack indicators --> <!-- Tech stack indicators with unified gray styling -->
<div class="mt-6 flex flex-wrap gap-2"> <div class="mt-6 mb-4 flex flex-wrap gap-2">
<span class="px-2 py-1 bg-orange-500/20 text-orange-400 text-xs rounded-full">HTML</span> <span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">HTML</span>
<span class="px-2 py-1 bg-cyan-500/20 text-cyan-400 text-xs rounded-full">TailwindCSS</span> <span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">TailwindCSS</span>
<span class="px-2 py-1 bg-green-500/20 text-green-400 text-xs rounded-full">Alpine.js</span> <span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Animate</span>
</div> </div>
</div> </div>
<div class="p-6 pt-4 border-t border-border/30"> <div class="p-6 pt-4 border-t border-border/30">
<div class="flex items-center justify-between w-full"> <div class="flex justify-center">
<a <a
href="https://github.com/joyzhao/portfolio-site" href="https://zhaoguiyang.site"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="flex items-center gap-2 text-sm text-muted-foreground hover:text-purple-400 transition-colors group/link" class="flex items-center gap-2 text-sm text-amber-400 hover:text-amber-300 transition-colors group/link"
> >
<svg class="h-4 w-4 group-hover/link:rotate-12 transition-transform duration-300" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
</svg>
View on GitHub
</a>
<button class="flex items-center gap-2 text-sm text-purple-400 hover:text-purple-300 transition-colors">
<span>🔗</span> <span>🔗</span>
Live Demo {t('project.visit')}
</button> </a>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -399,9 +399,14 @@ const pageTitle = t('site.title');
</p> </p>
</div> </div>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8"> <div class="grid grid-cols-1 lg:grid-cols-3 gap-8 items-stretch">
<!-- Taskify App --> <!-- Taskify App -->
<div class="group overflow-hidden border border-purple-500/20 hover:border-purple-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"> <div class="group overflow-hidden border border-purple-500/20 hover:border-purple-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">
<!-- Project tag - positioned at top right -->
<div class="absolute top-4 right-4 z-10">
<span class="px-3 py-1 bg-blue-100 dark:bg-blue-800 text-blue-800 dark:text-blue-200 text-xs rounded-full font-medium border border-blue-200 dark:border-blue-700">{t('project.tag.business')}</span>
</div>
<!-- Project image placeholder --> <!-- Project image placeholder -->
<div class="h-48 bg-gradient-to-br from-purple-500/20 to-purple-600/20 relative overflow-hidden"> <div class="h-48 bg-gradient-to-br from-purple-500/20 to-purple-600/20 relative overflow-hidden">
<div class="absolute inset-0 bg-gradient-to-br from-purple-500/10 to-purple-600/10 group-hover:from-purple-500/20 group-hover:to-purple-600/20 transition-all duration-500"></div> <div class="absolute inset-0 bg-gradient-to-br from-purple-500/10 to-purple-600/10 group-hover:from-purple-500/20 group-hover:to-purple-600/20 transition-all duration-500"></div>
@@ -423,7 +428,7 @@ const pageTitle = t('site.title');
<div class="space-y-3"> <div class="space-y-3">
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300"> <div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
<span class="text-purple-500 mt-1">•</span> <span class="text-purple-500 mt-1">•</span>
<span>一个功能齐全的任务管理应用程序</span> <span>一个功能完整的任务管理应用程序</span>
</div> </div>
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300"> <div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
<span class="text-purple-500 mt-1">•</span> <span class="text-purple-500 mt-1">•</span>
@@ -435,38 +440,36 @@ const pageTitle = t('site.title');
</div> </div>
</div> </div>
<!-- Tech stack indicators --> <!-- Tech stack indicators with unified gray styling -->
<div class="mt-6 flex flex-wrap gap-2"> <div class="mt-6 mb-4 flex flex-wrap gap-2">
<span class="px-2 py-1 bg-blue-500/20 text-blue-400 text-xs rounded-full">React</span> <span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">React</span>
<span class="px-2 py-1 bg-green-500/20 text-green-400 text-xs rounded-full">Node.js</span> <span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Node.js</span>
<span class="px-2 py-1 bg-purple-500/20 text-purple-400 text-xs rounded-full">MongoDB</span> <span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">MongoDB</span>
</div> </div>
</div> </div>
<div class="p-6 pt-4 border-t border-border/30"> <div class="p-6 pt-4 border-t border-border/30">
<div class="flex items-center justify-between w-full"> <div class="flex justify-center">
<a <a
href="https://github.com/zhaoguiyang/taskify-app" href="https://github.com/zhaoguiyang/taskify-app"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="flex items-center gap-2 text-sm text-muted-foreground hover:text-purple-400 transition-colors group/link" class="flex items-center gap-2 text-sm text-purple-400 hover:text-purple-300 transition-colors group/link"
> >
<svg class="h-4 w-4 group-hover/link:rotate-12 transition-transform duration-300" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
</svg>
在 GitHub 上查看
</a>
<button class="flex items-center gap-2 text-sm text-purple-400 hover:text-purple-300 transition-colors">
<span>🔗</span> <span>🔗</span>
在线演示 {t('project.visit')}
</button> </a>
</div> </div>
</div> </div>
</div> </div>
<!-- E-Shop Platform --> <!-- E-Shop Platform -->
<div class="group overflow-hidden border border-purple-500/20 hover:border-purple-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"> <div class="group overflow-hidden border border-purple-500/20 hover:border-purple-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">
<!-- Project tag - positioned at top right -->
<div class="absolute top-4 right-4 z-10">
<span class="px-3 py-1 bg-green-100 dark:bg-green-800 text-green-800 dark:text-green-200 text-xs rounded-full font-medium border border-green-200 dark:border-green-700">{t('project.tag.opensource')}</span>
</div>
<!-- Project image placeholder --> <!-- Project image placeholder -->
<div class="h-48 bg-gradient-to-br from-purple-500/20 to-purple-600/20 relative overflow-hidden"> <div class="h-48 bg-gradient-to-br from-purple-500/20 to-purple-600/20 relative overflow-hidden">
<div class="absolute inset-0 bg-gradient-to-br from-purple-500/10 to-purple-600/10 group-hover:from-purple-500/20 group-hover:to-purple-600/20 transition-all duration-500"></div> <div class="absolute inset-0 bg-gradient-to-br from-purple-500/10 to-purple-600/10 group-hover:from-purple-500/20 group-hover:to-purple-600/20 transition-all duration-500"></div>
@@ -500,38 +503,36 @@ const pageTitle = t('site.title');
</div> </div>
</div> </div>
<!-- Tech stack indicators --> <!-- Tech stack indicators with unified gray styling -->
<div class="mt-6 flex flex-wrap gap-2"> <div class="mt-6 mb-4 flex flex-wrap gap-2">
<span class="px-2 py-1 bg-blue-500/20 text-blue-400 text-xs rounded-full">Next.js</span> <span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Next.js</span>
<span class="px-2 py-1 bg-yellow-500/20 text-yellow-400 text-xs rounded-full">Stripe</span> <span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Stripe</span>
<span class="px-2 py-1 bg-cyan-500/20 text-cyan-400 text-xs rounded-full">TailwindCSS</span> <span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">TailwindCSS</span>
</div> </div>
</div> </div>
<div class="p-6 pt-4 border-t border-border/30"> <div class="p-6 pt-4 border-t border-border/30">
<div class="flex items-center justify-between w-full"> <div class="flex justify-center">
<a <a
href="https://github.com/zhaoguiyang/e-shop-platform" href="https://github.com/zhaoguiyang/e-shop-platform"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="flex items-center gap-2 text-sm text-muted-foreground hover:text-purple-400 transition-colors group/link" class="flex items-center gap-2 text-sm text-green-400 hover:text-green-300 transition-colors group/link"
> >
<svg class="h-4 w-4 group-hover/link:rotate-12 transition-transform duration-300" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
</svg>
在 GitHub 上查看
</a>
<button class="flex items-center gap-2 text-sm text-purple-400 hover:text-purple-300 transition-colors">
<span>🔗</span> <span>🔗</span>
在线演示 {t('project.visit')}
</button> </a>
</div> </div>
</div> </div>
</div> </div>
<!-- Portfolio Site --> <!-- Portfolio Site -->
<div class="group overflow-hidden border border-purple-500/20 hover:border-purple-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"> <div class="group overflow-hidden border border-purple-500/20 hover:border-purple-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">
<!-- Project tag - positioned at top right -->
<div class="absolute top-4 right-4 z-10">
<span class="px-3 py-1 bg-amber-100 dark:bg-amber-800 text-amber-800 dark:text-amber-200 text-xs rounded-full font-medium border border-amber-200 dark:border-amber-700">{t('project.tag.personal')}</span>
</div>
<!-- Project image placeholder --> <!-- Project image placeholder -->
<div class="h-48 bg-gradient-to-br from-purple-500/20 to-purple-600/20 relative overflow-hidden"> <div class="h-48 bg-gradient-to-br from-purple-500/20 to-purple-600/20 relative overflow-hidden">
<div class="absolute inset-0 bg-gradient-to-br from-purple-500/10 to-purple-600/10 group-hover:from-purple-500/20 group-hover:to-purple-600/20 transition-all duration-500"></div> <div class="absolute inset-0 bg-gradient-to-br from-purple-500/10 to-purple-600/10 group-hover:from-purple-500/20 group-hover:to-purple-600/20 transition-all duration-500"></div>
@@ -565,32 +566,25 @@ const pageTitle = t('site.title');
</div> </div>
</div> </div>
<!-- Tech stack indicators --> <!-- Tech stack indicators with unified gray styling -->
<div class="mt-6 flex flex-wrap gap-2"> <div class="mt-6 mb-4 flex flex-wrap gap-2">
<span class="px-2 py-1 bg-orange-500/20 text-orange-400 text-xs rounded-full">HTML</span> <span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">HTML</span>
<span class="px-2 py-1 bg-cyan-500/20 text-cyan-400 text-xs rounded-full">TailwindCSS</span> <span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">TailwindCSS</span>
<span class="px-2 py-1 bg-green-500/20 text-green-400 text-xs rounded-full">Alpine.js</span> <span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Animate</span>
</div> </div>
</div> </div>
<div class="p-6 pt-4 border-t border-border/30"> <div class="p-6 pt-4 border-t border-border/30">
<div class="flex items-center justify-between w-full"> <div class="flex justify-center">
<a <a
href="https://github.com/zhaoguiyang/portfolio-site" href="https://zhaoguiyang.site"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="flex items-center gap-2 text-sm text-muted-foreground hover:text-purple-400 transition-colors group/link" class="flex items-center gap-2 text-sm text-amber-400 hover:text-amber-300 transition-colors group/link"
> >
<svg class="h-4 w-4 group-hover/link:rotate-12 transition-transform duration-300" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
</svg>
在 GitHub 上查看
</a>
<button class="flex items-center gap-2 text-sm text-purple-400 hover:text-purple-300 transition-colors">
<span>🔗</span> <span>🔗</span>
在线演示 {t('project.visit')}
</button> </a>
</div> </div>
</div> </div>
</div> </div>