feat(ui): improve blog list and terminal mockup responsiveness
- Make terminal mockup full width on all screen sizes - Add empty state handling for blog list with visual feedback - Maintain consistent styling across language versions
This commit is contained in:
@@ -72,80 +72,103 @@ const readMoreText = lang === 'zh' ? '阅读更多' : 'Read More';
|
|||||||
---
|
---
|
||||||
|
|
||||||
<div class="space-y-6">
|
<div class="space-y-6">
|
||||||
{posts.map((post, index) => (
|
{posts.length > 0 ? (
|
||||||
<article class="group">
|
posts.map((post, index) => (
|
||||||
<div class="bg-card/50 backdrop-blur-sm rounded-2xl overflow-hidden border border-border hover:border-purple-500/50 transition-all duration-300 hover:transform hover:scale-[1.02]">
|
<article class="group">
|
||||||
<div class="flex flex-col md:flex-row">
|
<div class="bg-card/50 backdrop-blur-sm rounded-2xl overflow-hidden border border-border hover:border-purple-500/50 transition-all duration-300 hover:transform hover:scale-[1.02]">
|
||||||
{/* Featured Image */}
|
<div class="flex flex-col md:flex-row">
|
||||||
<div class="relative overflow-hidden md:w-80 md:flex-shrink-0">
|
{/* Featured Image */}
|
||||||
<img
|
<div class="relative overflow-hidden md:w-80 md:flex-shrink-0">
|
||||||
src={post.image}
|
<img
|
||||||
alt={post.title}
|
src={post.image}
|
||||||
class="w-full h-48 md:h-full object-cover group-hover:scale-110 transition-transform duration-300"
|
alt={post.title}
|
||||||
/>
|
class="w-full h-48 md:h-full object-cover group-hover:scale-110 transition-transform duration-300"
|
||||||
<div class="absolute inset-0 bg-gradient-to-t md:bg-gradient-to-r from-background/50 to-transparent"></div>
|
/>
|
||||||
</div>
|
<div class="absolute inset-0 bg-gradient-to-t md:bg-gradient-to-r from-background/50 to-transparent"></div>
|
||||||
|
|
||||||
{/* Content */}
|
|
||||||
<div class="p-6 flex-1 flex flex-col justify-between">
|
|
||||||
<div>
|
|
||||||
<h2 class="text-xl font-bold text-card-foreground mb-3 group-hover:text-purple-500 transition-colors duration-200">
|
|
||||||
<a href={`${postBaseUrl}${post.slug}`}>
|
|
||||||
{post.title}
|
|
||||||
</a>
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p class="text-muted-foreground mb-4 line-clamp-3">
|
|
||||||
{post.description}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
{/* Tags */}
|
|
||||||
<div class="flex flex-wrap gap-2 mb-4">
|
|
||||||
{post.tags.map((tag, tagIndex) => {
|
|
||||||
// 使用 tagId 如果存在,否则使用 tag 本身
|
|
||||||
const tagRoute = post.tagId && Array.isArray(post.tagId) && tagIndex < post.tagId.length
|
|
||||||
? post.tagId[tagIndex]
|
|
||||||
: tag.toLowerCase();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<a
|
|
||||||
href={`/${lang === 'en' ? '' : 'zh/'}blog/tags/${encodeURIComponent(tagRoute)}`}
|
|
||||||
class="px-2 py-1 text-xs bg-muted text-muted-foreground rounded-full hover:bg-muted/80 transition-colors"
|
|
||||||
>
|
|
||||||
# {tag}
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Meta Info */}
|
{/* Content */}
|
||||||
<div class="flex items-center justify-between text-sm text-muted-foreground">
|
<div class="p-6 flex-1 flex flex-col justify-between">
|
||||||
<div class="flex items-center space-x-4">
|
<div>
|
||||||
<span class="flex items-center">
|
<h2 class="text-xl font-bold text-card-foreground mb-3 group-hover:text-purple-500 transition-colors duration-200">
|
||||||
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<a href={`${postBaseUrl}${post.slug}`}>
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 002 2v12a2 2 0 002 2z"></path>
|
{post.title}
|
||||||
</svg>
|
</a>
|
||||||
{post.date}
|
</h2>
|
||||||
</span>
|
|
||||||
<span>{post.readTime}</span>
|
<p class="text-muted-foreground mb-4 line-clamp-3">
|
||||||
|
{post.description}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Tags */}
|
||||||
|
<div class="flex flex-wrap gap-2 mb-4">
|
||||||
|
{post.tags.map((tag, tagIndex) => {
|
||||||
|
// 使用 tagId 如果存在,否则使用 tag 本身
|
||||||
|
const tagRoute = post.tagId && Array.isArray(post.tagId) && tagIndex < post.tagId.length
|
||||||
|
? post.tagId[tagIndex]
|
||||||
|
: tag.toLowerCase();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
href={`/${lang === 'en' ? '' : 'zh/'}blog/tags/${encodeURIComponent(tagRoute)}`}
|
||||||
|
class="px-2 py-1 text-xs bg-muted text-muted-foreground rounded-full hover:bg-muted/80 transition-colors"
|
||||||
|
>
|
||||||
|
# {tag}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a
|
{/* Meta Info */}
|
||||||
href={`${postBaseUrl}${post.slug}`}
|
<div class="flex items-center justify-between text-sm text-muted-foreground">
|
||||||
class="text-purple-500 hover:text-purple-400 font-medium flex items-center group"
|
<div class="flex items-center space-x-4">
|
||||||
>
|
<span class="flex items-center">
|
||||||
{readMoreText}
|
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<svg class="w-4 h-4 ml-1 group-hover:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 002 2v12a2 2 0 002 2z"></path>
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
</svg>
|
||||||
</svg>
|
{post.date}
|
||||||
</a>
|
</span>
|
||||||
|
<span>{post.readTime}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href={`${postBaseUrl}${post.slug}`}
|
||||||
|
class="text-purple-500 hover:text-purple-400 font-medium flex items-center group"
|
||||||
|
>
|
||||||
|
{readMoreText}
|
||||||
|
<svg class="w-4 h-4 ml-1 group-hover:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</article>
|
||||||
</article>
|
))
|
||||||
))}
|
) : (
|
||||||
|
<div class="flex flex-col items-center justify-center py-20 text-center bg-card/30 backdrop-blur-sm rounded-2xl border border-border p-8 min-h-[300px]">
|
||||||
|
<svg class="w-16 h-16 text-purple-500/70 mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"></path>
|
||||||
|
</svg>
|
||||||
|
<p class="text-xl text-muted-foreground mb-4">
|
||||||
|
{lang === 'zh' ? '暂无博客文章' : 'No blog posts yet'}
|
||||||
|
</p>
|
||||||
|
<p class="text-sm text-muted-foreground/70 mb-6 max-w-md">
|
||||||
|
{lang === 'zh' ? '我们正在努力创作新的内容,请稍后再来查看。' : 'We are working on creating new content. Please check back later.'}
|
||||||
|
</p>
|
||||||
|
<a
|
||||||
|
href={`/${lang === 'en' ? '' : 'zh/'}`}
|
||||||
|
class="px-4 py-2 bg-purple-500/10 hover:bg-purple-500/20 text-purple-500 rounded-full transition-colors duration-200 flex items-center"
|
||||||
|
>
|
||||||
|
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"></path>
|
||||||
|
</svg>
|
||||||
|
{lang === 'zh' ? '返回首页' : 'Back to Home'}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ const pageTitle = t('site.title');
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Terminal mockup -->
|
<!-- Terminal mockup -->
|
||||||
<div class="max-w-4xl mx-auto">
|
<div class="max-w-full mx-auto">
|
||||||
<div class="bg-gray-900/90 backdrop-blur-sm rounded-lg border border-gray-700/50 shadow-2xl overflow-hidden">
|
<div class="bg-gray-900/90 backdrop-blur-sm rounded-lg border border-gray-700/50 shadow-2xl overflow-hidden">
|
||||||
<!-- Terminal header -->
|
<!-- Terminal header -->
|
||||||
<div class="flex items-center justify-between px-4 py-3 bg-gray-800/50 border-b border-gray-700/50">
|
<div class="flex items-center justify-between px-4 py-3 bg-gray-800/50 border-b border-gray-700/50">
|
||||||
|
|||||||
@@ -107,10 +107,9 @@ const pageTitle = t('site.title');
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
|
||||||
|
|
||||||
<!-- Terminal mockup -->
|
<!-- Terminal mockup -->
|
||||||
<div class="max-w-4xl mx-auto">
|
<div class="max-w-full mx-auto">
|
||||||
<div class="bg-gray-900/90 backdrop-blur-sm rounded-lg border border-gray-700/50 shadow-2xl overflow-hidden">
|
<div class="bg-gray-900/90 backdrop-blur-sm rounded-lg border border-gray-700/50 shadow-2xl overflow-hidden">
|
||||||
<!-- Terminal header -->
|
<!-- Terminal header -->
|
||||||
<div class="flex items-center justify-between px-4 py-3 bg-gray-800/50 border-b border-gray-700/50">
|
<div class="flex items-center justify-between px-4 py-3 bg-gray-800/50 border-b border-gray-700/50">
|
||||||
|
|||||||
Reference in New Issue
Block a user