From 575dee0580a9ac153f75b9304f9da4d5080e76b0 Mon Sep 17 00:00:00 2001 From: Bjorn Lammers Date: Sun, 27 Apr 2025 22:57:56 +0200 Subject: [PATCH] feat(icons/[id]): Refine related icons relevance, display limits, and styling --- web/src/components/icon-details.tsx | 78 +++++++++++++++++++---------- 1 file changed, 52 insertions(+), 26 deletions(-) diff --git a/web/src/components/icon-details.tsx b/web/src/components/icon-details.tsx index 59a4a121..f0dae881 100644 --- a/web/src/components/icon-details.tsx +++ b/web/src/components/icon-details.tsx @@ -10,7 +10,7 @@ import { formatIconName } from "@/lib/utils" import type { AuthorData, Icon, IconFile } from "@/types/icons" import confetti from "canvas-confetti" import { motion } from "framer-motion" -import { Check, Copy, Download, FileType, Github, Moon, PaletteIcon, Sun } from "lucide-react" +import { Check, Copy, Download, FileType, Github, Moon, PaletteIcon, Sun, ArrowRight } from "lucide-react" import dynamic from "next/dynamic" import Image from "next/image" import Link from "next/link" @@ -479,31 +479,57 @@ export function IconDetails({ icon, iconData, authorData, allIcons }: IconDetail - {iconData.categories && iconData.categories.length > 0 && ( -
- - - - - - - Other icons from {iconData.categories.map((cat) => cat.replace(/-/g, " ")).join(", ")} categories - - - - { - if (name === icon) return false - return data.categories?.some((cat) => iconData.categories?.includes(cat)) - }) - .map(([name, data]) => ({ name, data }))} - matchedAliases={{}} - /> - - -
- )} + {iconData.categories && iconData.categories.length > 0 && (() => { + const MAX_RELATED_ICONS = 16 + const currentCategories = iconData.categories || [] + + const relatedIconsWithScore = Object.entries(allIcons) + .map(([name, data]) => { + if (name === icon) return null // Exclude the current icon + + const otherCategories = data.categories || [] + const commonCategories = currentCategories.filter((cat) => otherCategories.includes(cat)) + const score = commonCategories.length + + return score > 0 ? { name, data, score } : null + }) + .filter((item): item is { name: string; data: Icon; score: number } => item !== null) // Type guard + .sort((a, b) => b.score - a.score) // Sort by score DESC + + const topRelatedIcons = relatedIconsWithScore.slice(0, MAX_RELATED_ICONS) + + const viewMoreUrl = `/icons?${currentCategories.map((cat) => `category=${encodeURIComponent(cat)}`).join("&")}` + + if (topRelatedIcons.length === 0) return null + + return ( +
+ + + + + + + Other icons from {currentCategories.map((cat) => cat.replace(/-/g, " ")).join(", ")} categories + + + + + {relatedIconsWithScore.length > MAX_RELATED_ICONS && ( +
+ +
+ )} +
+
+
+ ) + })()} ) }