feat(redundancy): theme-aware badges + recommendation glow; fix nested nav active state

This commit is contained in:
opencode
2026-08-07 00:19:07 +02:00
parent 3e30246342
commit 9af83a8b1b
2 changed files with 24 additions and 7 deletions
+10 -1
View File
@@ -47,8 +47,17 @@ export function Layout({ children }: { children: React.ReactNode }) {
{ href: "/trash", label: t("nav.trash"), icon: Trash2 }, { href: "/trash", label: t("nav.trash"), icon: Trash2 },
]; ];
const navLinks = [...mainLinks, ...adminLinks];
function isActive(href: string) { function isActive(href: string) {
return location === href || (href !== "/" && location.startsWith(href)); if (href === "/") return location === "/";
if (!location.startsWith(href)) return false;
// Only the most specific active nav link should be highlighted, so a
// nested link (e.g. /admin/redundancy) wins over its parent (/admin).
const nestedActive = navLinks.some(
(l) => l.href !== href && l.href.startsWith(href) && location.startsWith(l.href),
);
return !nestedActive;
} }
return ( return (
+14 -6
View File
@@ -37,8 +37,16 @@ export default function RedundancyPage() {
} }
} }
function certaintyColor(c: string) { function certaintyBadge(c: string) {
return c === "high" ? "bg-green-100 text-green-800 border-green-300" : c === "medium" ? "bg-amber-100 text-amber-800 border-amber-300" : "bg-gray-100 text-gray-600 border-gray-300"; if (c === "high") return "default";
if (c === "medium") return "secondary";
return "outline";
}
function certaintyClass(c: string) {
if (c === "high") return "text-primary";
if (c === "medium") return "text-primary/70";
return "text-muted-foreground";
} }
return ( return (
@@ -118,12 +126,12 @@ export default function RedundancyPage() {
<div className="space-y-3"> <div className="space-y-3">
<h3 className="text-sm font-medium text-muted-foreground">{t("redundancy.comparisonsTitle")}</h3> <h3 className="text-sm font-medium text-muted-foreground">{t("redundancy.comparisonsTitle")}</h3>
{group.pairs.map((pair: any, i: number) => ( {group.pairs.map((pair: any, i: number) => (
<Card key={i} className={pair.recommendation.certainty === "high" ? "border-green-300" : pair.recommendation.certainty === "medium" ? "border-amber-200" : ""}> <Card key={i} className={pair.recommendation.certainty === "high" ? "neon-glow border-primary/40" : pair.recommendation.certainty === "medium" ? "border-primary/30" : ""}>
<CardContent className="p-4"> <CardContent className="p-4">
<div className="flex flex-col sm:flex-row sm:items-center gap-3"> <div className="flex flex-col sm:flex-row sm:items-center gap-3">
<div className="flex items-center gap-3 min-w-0 flex-1"> <div className="flex items-center gap-3 min-w-0 flex-1">
<div className="text-right min-w-0 flex-1"> <div className="text-right min-w-0 flex-1">
<span className={`font-medium text-sm block truncate ${pair.recommendation.betterToolId === pair.a.id ? "text-primary" : ""}`}> <span className={`font-medium text-sm block truncate ${pair.recommendation.betterToolId === pair.a.id ? "text-primary [filter:drop-shadow(0_0_6px_hsl(var(--primary)/0.4))]" : ""}`}>
{pair.a.name} {pair.a.name}
</span> </span>
<span className="text-[10px] text-muted-foreground"> <span className="text-[10px] text-muted-foreground">
@@ -139,7 +147,7 @@ export default function RedundancyPage() {
</div> </div>
</div> </div>
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<span className={`font-medium text-sm block truncate ${pair.recommendation.betterToolId === pair.b.id ? "text-primary" : ""}`}> <span className={`font-medium text-sm block truncate ${pair.recommendation.betterToolId === pair.b.id ? "text-primary [filter:drop-shadow(0_0_6px_hsl(var(--primary)/0.4))]" : ""}`}>
{pair.b.name} {pair.b.name}
</span> </span>
<span className="text-[10px] text-muted-foreground"> <span className="text-[10px] text-muted-foreground">
@@ -151,7 +159,7 @@ export default function RedundancyPage() {
<div className="flex items-center gap-2 shrink-0 justify-end"> <div className="flex items-center gap-2 shrink-0 justify-end">
{pair.recommendation.reason && ( {pair.recommendation.reason && (
<Badge variant="outline" className={`text-[10px] px-1.5 py-0 ${certaintyColor(pair.recommendation.certainty)}`}> <Badge variant={certaintyBadge(pair.recommendation.certainty) as "default" | "secondary" | "outline"} className={`text-[10px] px-1.5 py-0 ${certaintyClass(pair.recommendation.certainty)}`}>
<ThumbsUp className="w-2.5 h-2.5 mr-0.5" /> <ThumbsUp className="w-2.5 h-2.5 mr-0.5" />
{pair.recommendation.betterName} {pair.recommendation.betterName}
</Badge> </Badge>