)
}
diff --git a/src/components/project/ProjectSidebar.tsx b/src/components/project/ProjectSidebar.tsx
new file mode 100644
index 0000000..5981804
--- /dev/null
+++ b/src/components/project/ProjectSidebar.tsx
@@ -0,0 +1,156 @@
+import Link from 'next/link'
+
+interface ProjectSidebarProps {
+ project: {
+ id: string
+ name: string
+ nameEn?: string | null
+ slug: string
+ links: Array<{
+ id: string
+ type: string
+ url: string
+ title?: string | null
+ }>
+ }
+ locale: string
+}
+
+// Helper function to get icon and label for link type
+function getLinkInfo(type: string): { icon: string; label: string } {
+ switch (type.toUpperCase()) {
+ case 'WEBSITE':
+ return { icon: 'language', label: 'Official Website' }
+ case 'GITHUB':
+ return { icon: 'code', label: 'GitHub Repo' }
+ case 'HUGGINGFACE':
+ return { icon: 'model_training', label: 'Hugging Face' }
+ case 'PAPER':
+ return { icon: 'description', label: 'Paper' }
+ default:
+ return { icon: 'link', label: 'External Link' }
+ }
+}
+
+export function ProjectSidebar({ project, locale }: ProjectSidebarProps) {
+ const displayName = locale === 'en' && project.nameEn ? project.nameEn : project.name
+
+ return (
+
+ )
+}
diff --git a/src/components/project/RelatedProjects.tsx b/src/components/project/RelatedProjects.tsx
new file mode 100644
index 0000000..a265fc3
--- /dev/null
+++ b/src/components/project/RelatedProjects.tsx
@@ -0,0 +1,93 @@
+import Link from 'next/link'
+
+interface RelatedProjectsProps {
+ projects: Array<{
+ id: string
+ name: string
+ nameEn?: string | null
+ slug: string
+ description: string
+ descriptionEn?: string | null
+ tags: Array<{
+ id: string
+ name: string
+ nameEn?: string | null
+ slug: string
+ }>
+ }>
+ locale: string
+}
+
+// Icon mapping for projects
+function getProjectIcon(tags: Array<{ name: string }>): string {
+ const tagNames = tags.map((t) => t.name.toLowerCase())
+ if (tagNames.some((t) => t.includes('automation') || t.includes('workflow'))) return '⚙️'
+ if (tagNames.some((t) => t.includes('image') || t.includes('art'))) return '🎨'
+ if (tagNames.some((t) => t.includes('chat') || t.includes('assistant'))) return '💬'
+ if (tagNames.some((t) => t.includes('data') || t.includes('analysis'))) return '📊'
+ if (tagNames.some((t) => t.includes('llm') || t.includes('language'))) return '🧠'
+ return '✨'
+}
+
+export function RelatedProjects({ projects, locale }: RelatedProjectsProps) {
+ if (projects.length === 0) {
+ return null
+ }
+
+ return (
+
+ )
+}
diff --git a/src/components/project/TagCloud.tsx b/src/components/project/TagCloud.tsx
index 5d58c1c..ef47ed7 100644
--- a/src/components/project/TagCloud.tsx
+++ b/src/components/project/TagCloud.tsx
@@ -11,25 +11,40 @@ interface TagCloudProps {
}
}>
locale: string
+ activeTag?: string
}
-export function TagCloud({ tags, locale }: TagCloudProps) {
+export function TagCloud({ tags, locale, activeTag }: TagCloudProps) {
return (
-
- {tags.map((tag) => (
-
- {tag.name}
- {tag._count && tag._count.projects > 0 && (
-
- {tag._count.projects}
-
- )}
-
- ))}
+
+ {tags.map((tag) => {
+ const count = tag._count?.projects || 0
+ const isActive = activeTag === tag.slug
+ const displayName = locale === 'en' && tag.nameEn ? tag.nameEn : tag.name
+
+ return (
+
+ {displayName}
+ {count > 0 && (
+
+ {count}
+
+ )}
+
+ )
+ })}
)
}
diff --git a/src/components/search/SearchBar.tsx b/src/components/search/SearchBar.tsx
index fba2929..933a47f 100644
--- a/src/components/search/SearchBar.tsx
+++ b/src/components/search/SearchBar.tsx
@@ -20,14 +20,35 @@ export function SearchBar({ locale }: SearchBarProps) {
}
return (
-
)
}
diff --git a/tailwind.config.ts b/tailwind.config.ts
index 762d965..d6123c5 100644
--- a/tailwind.config.ts
+++ b/tailwind.config.ts
@@ -10,44 +10,55 @@ const config: Config = {
theme: {
extend: {
colors: {
- border: "hsl(var(--border))",
- input: "hsl(var(--input))",
- ring: "hsl(var(--ring))",
- background: "hsl(var(--background))",
- foreground: "hsl(var(--foreground))",
+ // Neo-brutalism color scheme from design
primary: {
- DEFAULT: "hsl(var(--primary))",
- foreground: "hsl(var(--primary-foreground))",
+ DEFAULT: "#FFD700", // Gold/Yellow from MotherDuck
+ dark: "#e5cb00",
},
- secondary: {
- DEFAULT: "hsl(var(--secondary))",
- foreground: "hsl(var(--secondary-foreground))",
+ secondary: "#ff6f00", // Orange accent
+ background: {
+ light: "#F5F2EB", // Warm off-white/beige
+ dark: "#121212", // Dark charcoal for dark mode
},
- destructive: {
- DEFAULT: "hsl(var(--destructive))",
- foreground: "hsl(var(--destructive-foreground))",
+ surface: {
+ light: "#FFFFFF",
+ dark: "#1E1E1E",
},
- muted: {
- DEFAULT: "hsl(var(--muted))",
- foreground: "hsl(var(--muted-foreground))",
+ border: {
+ light: "#000000",
+ dark: "#4a4a4a",
},
- accent: {
- DEFAULT: "hsl(var(--accent))",
- foreground: "hsl(var(--accent-foreground))",
- },
- popover: {
- DEFAULT: "hsl(var(--popover))",
- foreground: "hsl(var(--popover-foreground))",
- },
- card: {
- DEFAULT: "hsl(var(--card))",
- foreground: "hsl(var(--card-foreground))",
+ text: {
+ light: "#000000",
+ dark: "#F5F2EB",
},
},
+ fontFamily: {
+ display: ["'Space Mono'", "'Courier New'", "monospace"], // Space Mono for headings
+ sans: ["var(--font-inter)", "system-ui", "-apple-system", "sans-serif"], // Inter for body
+ },
+ boxShadow: {
+ // Neo-brutalism shadows
+ neo: "4px 4px 0px 0px rgba(0,0,0,1)",
+ "neo-sm": "2px 2px 0px 0px rgba(0,0,0,1)",
+ "neo-hover": "2px 2px 0px 0px rgba(0,0,0,1)",
+ "neo-dark": "4px 4px 0px 0px rgba(255,215,0,0.5)",
+ brutal: "4px 4px 0px 0px rgba(0,0,0,1)",
+ "brutal-hover": "2px 2px 0px 0px rgba(0,0,0,1)",
+ "brutal-dark": "4px 4px 0px 0px rgba(255,255,255,0.2)",
+ },
borderRadius: {
- lg: "var(--radius)",
- md: "calc(var(--radius) - 2px)",
- sm: "calc(var(--radius) - 4px)",
+ DEFAULT: "0px", // Sharp corners for neo-brutalism
+ md: "2px",
+ },
+ animation: {
+ float: "float 6s ease-in-out infinite",
+ },
+ keyframes: {
+ float: {
+ "0%, 100%": { transform: "translateY(0px) rotate(0deg)" },
+ "50%": { transform: "translateY(-10px) rotate(2deg)" },
+ },
},
},
},