+
{recipe.tags.slice(0, 3).map((tag) => (
{tag}
))}
+
+ {/* Arrow indicator */}
+
);
}
diff --git a/lib/community/leaderboard.ts b/lib/community/leaderboard.ts
index f2c159f3..e62acfa1 100644
--- a/lib/community/leaderboard.ts
+++ b/lib/community/leaderboard.ts
@@ -1,45 +1,47 @@
-import {
- TrendingUp,
- Clock,
- Heart,
- Zap,
- Sparkles,
- BarChart3,
-} from "lucide-react";
-
export type SortMethod = "trending" | "recent" | "popular" | "hot";
-export interface SortOption {
+export interface SortOptionDef {
value: SortMethod;
- label: string;
- icon: React.ReactNode;
- description: string;
+ labelEn: string;
+ labelZh: string;
+ iconName: "TrendingUp" | "Clock" | "Heart" | "Zap";
+ descriptionEn: string;
+ descriptionZh: string;
}
-export const SORT_OPTIONS: SortOption[] = [
+// 纯数据定义,不包含 React 组件,适合 Server Component
+export const SORT_OPTIONS_DEF: SortOptionDef[] = [
{
value: "trending",
- label: "Trending",
- icon:
,
- description: "Most engagement this week",
+ labelEn: "Trending",
+ labelZh: "热门趋势",
+ iconName: "TrendingUp",
+ descriptionEn: "Most engagement this week",
+ descriptionZh: "本周互动最多",
},
{
value: "recent",
- label: "Recent",
- icon:
,
- description: "Newest submissions first",
+ labelEn: "Recent",
+ labelZh: "最新发布",
+ iconName: "Clock",
+ descriptionEn: "Newest submissions first",
+ descriptionZh: "按时间倒序",
},
{
value: "popular",
- label: "Popular",
- icon:
,
- description: "Most liked all-time",
+ labelEn: "Popular",
+ labelZh: "最受欢迎",
+ iconName: "Heart",
+ descriptionEn: "Most liked all-time",
+ descriptionZh: "累计点赞最多",
},
{
value: "hot",
- label: "Hot",
- icon:
,
- description: "Rapid growth momentum",
+ labelEn: "Hot",
+ labelZh: "火速增长",
+ iconName: "Zap",
+ descriptionEn: "Rapid growth momentum",
+ descriptionZh: "增长势头最猛",
},
];
@@ -128,36 +130,53 @@ export function sortCommunityStyles(
}
}
+export type BadgeType = "hot" | "rising" | "viral" | null;
+
+export interface EngagementBadge {
+ type: BadgeType;
+ labelEn: string;
+ labelZh: string;
+ color: string;
+ iconName: "Zap" | "TrendingUp" | "Sparkles";
+}
+
/**
* Calculate engagement metrics for display
+ * Returns pure data without React components for Server Component compatibility
*/
export function calculateEngagementBadge(
style: CommunityStyleWithStats
-): { label: string; color: string; icon: React.ReactNode } | null {
+): EngagementBadge | null {
const totalEngagement = style.likes + style.shares * 2;
const engagementRate = totalEngagement / Math.max(style.views, 1);
if (style.trend > 50) {
return {
- label: "🔥 Hot",
+ type: "hot",
+ labelEn: "Hot",
+ labelZh: "火热",
color: "bg-red-500/20 text-red-600 dark:text-red-400",
- icon:
,
+ iconName: "Zap",
};
}
if (style.trend > 25) {
return {
- label: "📈 Rising",
+ type: "rising",
+ labelEn: "Rising",
+ labelZh: "上升中",
color: "bg-orange-500/20 text-orange-600 dark:text-orange-400",
- icon:
,
+ iconName: "TrendingUp",
};
}
if (engagementRate > 0.05 && style.likes > 10) {
return {
- label: "⭐ Viral",
+ type: "viral",
+ labelEn: "Viral",
+ labelZh: "爆款",
color: "bg-yellow-500/20 text-yellow-600 dark:text-yellow-400",
- icon:
,
+ iconName: "Sparkles",
};
}
diff --git a/lib/seo/style-guides.ts b/lib/seo/style-guides.ts
index f205ad5e..3ea32fc5 100644
--- a/lib/seo/style-guides.ts
+++ b/lib/seo/style-guides.ts
@@ -118,6 +118,170 @@ export const styleGuides: Record
= {
influencedBy: ["Swiss Style", "Bauhaus"],
influenced: ["Neo-Brutalism", "Glassmorphism"],
},
+ glassmorphism: {
+ name: "玻璃拟态设计",
+ nameEn: "Glassmorphism",
+ slug: "glassmorphism",
+ description: "通过模糊透明效果和多层次叠加创造现代感的界面设计风格",
+ descriptionEn: "A modern UI style that creates depth through frosted glass effects, transparency, and layered elements.",
+ history: "玻璃拟态在 2020-2021 年随着 macOS Big Sur 的发布而流行。它源于 Windows Vista 的 Aero Glass 和 iOS 7 的设计,并发展成为独立的设计趋势。",
+ historyEn: "Glassmorphism became popular in 2020-2021 with the release of macOS Big Sur. It evolved from Windows Vista's Aero Glass and iOS 7's design, developing into an independent design trend.",
+ philosophy: "通过透明度和模糊效果创造深度和层次感,同时保持界面的现代感和轻盈感。强调背景内容与前景元素的视觉关系。",
+ philosophyEn: "Create depth and hierarchy through transparency and blur effects while maintaining a modern, lightweight feel. Emphasizes the visual relationship between background content and foreground elements.",
+ useCases: [
+ {
+ title: "SaaS 产品界面",
+ titleEn: "SaaS Product Interfaces",
+ description: "创造高端、现代感的产品体验",
+ descriptionEn: "Creating premium, modern product experiences",
+ industry: "SaaS",
+ },
+ {
+ title: "AI 和科技产品",
+ titleEn: "AI & Tech Products",
+ description: "传达创新和前沿技术的感觉",
+ descriptionEn: "Conveying innovation and cutting-edge technology",
+ industry: "Technology",
+ },
+ ],
+ references: [
+ {
+ title: "Apple Human Interface Guidelines",
+ url: "https://developer.apple.com/design/human-interface-guidelines/",
+ type: "website",
+ },
+ {
+ title: "Glassmorphism CSS Generator",
+ url: "https://css.glass",
+ type: "website",
+ },
+ ],
+ influencedBy: ["Neumorphism", "Material Design"],
+ influenced: ["Liquid Glass"],
+ },
+ "neo-brutalism": {
+ name: "新野兽派设计",
+ nameEn: "Neo-Brutalism",
+ slug: "neo-brutalism",
+ description: "大胆的颜色、粗犷的边框和不对称布局,挑战传统设计规范",
+ descriptionEn: "Bold colors, raw borders, and asymmetric layouts that challenge traditional design conventions.",
+ history: "新野兽派设计于 2020 年代初兴起,受建筑野兽派运动启发。它是对过度精致的 UI 设计的一种反叛,强调原始、大胆和诚实的视觉表达。",
+ historyEn: "Neo-brutalism emerged in the early 2020s, inspired by the architectural Brutalist movement. It's a rebellion against over-polished UI design, emphasizing raw, bold, and honest visual expression.",
+ philosophy: "设计应该是诚实和大胆的,不需要隐藏或美化。通过打破常规的视觉元素创造独特的品牌识别和用户记忆点。",
+ philosophyEn: "Design should be honest and bold without hiding or beautifying. Create unique brand identity and memorable user experiences through unconventional visual elements.",
+ useCases: [
+ {
+ title: "创意工作室和代理商",
+ titleEn: "Creative Studios & Agencies",
+ description: "展示大胆的创意能力和独特视角",
+ descriptionEn: "Showcasing bold creative capabilities and unique perspectives",
+ industry: "Creative",
+ },
+ {
+ title: "独立产品和初创公司",
+ titleEn: "Indie Products & Startups",
+ description: "在拥挤的市场中脱颖而出",
+ descriptionEn: "Standing out in crowded markets",
+ industry: "Startup",
+ },
+ ],
+ references: [
+ {
+ title: "Brutalist Websites",
+ url: "https://brutalistwebsites.com",
+ type: "website",
+ },
+ {
+ title: "Why Brutalism is Making a Comeback",
+ url: "https://www.designweek.co.uk",
+ type: "article",
+ },
+ ],
+ influencedBy: ["Brutalist Architecture", "Punk Design"],
+ influenced: ["Anti-Design Movement"],
+ },
+ editorial: {
+ name: "编辑风格设计",
+ nameEn: "Editorial Design",
+ slug: "editorial",
+ description: "受杂志和出版物启发的排版和布局,强调可读性和内容层次",
+ descriptionEn: "Typography and layout inspired by magazines and publications, emphasizing readability and content hierarchy.",
+ history: "编辑风格设计源于印刷媒体的悠久传统,特别是 20 世纪的杂志设计。数字时代使这种风格适应了网页,保留了其对排版和留白的重视。",
+ historyEn: "Editorial design originates from the long tradition of print media, particularly 20th-century magazine design. The digital age adapted this style for the web while retaining its emphasis on typography and whitespace.",
+ philosophy: "内容为王,设计服务于阅读。通过精心的排版、适当的留白和清晰的视觉层次引导读者注意力。",
+ philosophyEn: "Content is king, design serves reading. Guide reader attention through careful typography, appropriate whitespace, and clear visual hierarchy.",
+ useCases: [
+ {
+ title: "博客和在线杂志",
+ titleEn: "Blogs & Online Magazines",
+ description: "提供优质的长篇阅读体验",
+ descriptionEn: "Providing premium long-form reading experiences",
+ industry: "Media",
+ },
+ {
+ title: "品牌故事和案例研究",
+ titleEn: "Brand Stories & Case Studies",
+ description: "通过叙事设计建立品牌连接",
+ descriptionEn: "Building brand connection through narrative design",
+ industry: "Marketing",
+ },
+ ],
+ references: [
+ {
+ title: "Typewolf - Typography Inspiration",
+ url: "https://www.typewolf.com",
+ type: "website",
+ },
+ {
+ title: "The Elements of Typographic Style",
+ url: "https://en.wikipedia.org/wiki/The_Elements_of_Typographic_Style",
+ type: "book",
+ },
+ ],
+ influencedBy: ["Swiss Typography", "Magazine Design"],
+ influenced: ["Content-First Design"],
+ },
+ "cyber-wafuu": {
+ name: "赛博和风设计",
+ nameEn: "Cyber Wafuu",
+ slug: "cyber-wafuu",
+ description: "融合日本传统美学与赛博朋克元素的独特视觉风格",
+ descriptionEn: "A unique visual style blending Japanese traditional aesthetics with cyberpunk elements.",
+ history: "赛博和风是 21 世纪互联网文化的产物,融合了日本传统文化元素与科幻未来主义视觉。它反映了全球化时代中东西方文化的碰撞与融合。",
+ historyEn: "Cyber Wafuu is a product of 21st-century internet culture, blending Japanese traditional cultural elements with sci-fi futuristic visuals. It reflects the collision and fusion of Eastern and Western cultures in the era of globalization.",
+ philosophy: "在传统与未来之间寻找平衡。通过将古老的美学元素(如樱花、灯笼、书法)与霓虹灯、故障效果、赛博格元素结合,创造出独特的文化身份。",
+ philosophyEn: "Finding balance between tradition and future. By combining ancient aesthetic elements (like cherry blossoms, lanterns, calligraphy) with neon lights, glitch effects, and cyborg elements, create a unique cultural identity.",
+ useCases: [
+ {
+ title: "游戏和娱乐",
+ titleEn: "Gaming & Entertainment",
+ description: "创造独特的世界观和视觉识别",
+ descriptionEn: "Creating unique worldviews and visual identity",
+ industry: "Gaming",
+ },
+ {
+ title: "潮牌和街头文化",
+ titleEn: "Streetwear & Urban Culture",
+ description: "吸引年轻、前卫的目标受众",
+ descriptionEn: "Attracting young, avant-garde target audiences",
+ industry: "Fashion",
+ },
+ ],
+ references: [
+ {
+ title: "Ghost in the Shell Aesthetics",
+ url: "https://www.imdb.com/title/tt0113568/",
+ type: "website",
+ },
+ {
+ title: "Japanese Cyberpunk Art Movement",
+ url: "https://www.artstation.com",
+ type: "website",
+ },
+ ],
+ influencedBy: ["Cyberpunk", "Japanese Traditional Art"],
+ influenced: ["Modern Anime Aesthetics"],
+ },
};
/**
diff --git a/lib/styles/recipes.ts b/lib/styles/recipes.ts
index cfc3bec5..68e86573 100644
--- a/lib/styles/recipes.ts
+++ b/lib/styles/recipes.ts
@@ -453,6 +453,39 @@ export function resolveRecipeStyles(recipe: StyleRecipe): {
};
}
+/**
+ * Validate that a recipe's referenced styles exist
+ */
+export function validateRecipe(recipe: StyleRecipe): {
+ valid: boolean;
+ missingVisual: boolean;
+ missingLayout: boolean;
+ missingAnimations: string[];
+} {
+ const visualExists = styles.some((s) => s.slug === recipe.visualStyle);
+ const layoutExists = styles.some((s) => s.slug === recipe.layout);
+ const missingAnimations = (recipe.animations || []).filter(
+ (anim) => !styles.some((s) => s.slug === anim)
+ );
+
+ return {
+ valid: visualExists && layoutExists && missingAnimations.length === 0,
+ missingVisual: !visualExists,
+ missingLayout: !layoutExists,
+ missingAnimations,
+ };
+}
+
+/**
+ * Get only valid recipes (with existing style references)
+ */
+export function getValidRecipes(): StyleRecipe[] {
+ return styleRecipes.filter((recipe) => {
+ const validation = validateRecipe(recipe);
+ return validation.valid || (!validation.missingVisual && !validation.missingLayout);
+ });
+}
+
/**
* Search recipes by query
*/