From 1d2f27f9a3c185bef5b0f2aa0c5527fa04ad1d82 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 20 Feb 2026 07:50:20 +0000 Subject: [PATCH] feat: show metric type labels in trusted assertion feed view MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add Label components to the assertion feed renderer so you can see at a glance which metrics an assertion carries (Followers, Posts, Zaps, etc.) instead of just numeric values. Also swap Badge → Label for the kind indicator for visual consistency. Replace hardcoded green/yellow/red rank colors with theme variables (success/warning/destructive) in both feed and detail renderers so the rank bar works correctly across all themes. Add Label to CLAUDE.md shared components list (22 imports across the codebase). https://claude.ai/code/session_01XjwLaShFSVPR5gNA7iUjuB --- CLAUDE.md | 1 + .../kinds/TrustedAssertionDetailRenderer.tsx | 7 ++-- .../nostr/kinds/TrustedAssertionRenderer.tsx | 32 ++++++++++++------- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index cb356f2..cebb891 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -343,6 +343,7 @@ This allows `applyTheme()` to switch themes at runtime. - **Shared Components** — Use these instead of rolling your own: - **`UserName`** (`src/components/nostr/UserName.tsx`): Always use for displaying user pubkeys. Shows display name, Grimoire member badge, supporter flame. Clicking opens profile. Accepts optional `relayHints` prop for fetching profiles from specific relays. - **`RelayLink`** (`src/components/nostr/RelayLink.tsx`): Always use for displaying relay URLs. Shows relay favicon, insecure `ws://` warnings, read/write badges, and opens relay detail window on click. Never render raw relay URL strings. + - **`Label`** (`src/components/ui/label.tsx`): Dotted-border tag/badge for metadata labels (language, kind, status, metric type). Two sizes: `sm` (default) and `md`. Use instead of ad-hoc `` tags for tag-like indicators. - **`RichText`** (`src/components/nostr/RichText.tsx`): Universal Nostr content renderer. Parses mentions, hashtags, custom emoji, media embeds, and nostr: references. Use for any event body text — never render `event.content` as a raw string. - **`CustomEmoji`** (`src/components/nostr/CustomEmoji.tsx`): Renders NIP-30 custom emoji images inline. Shows shortcode tooltip, handles load errors gracefully. diff --git a/src/components/nostr/kinds/TrustedAssertionDetailRenderer.tsx b/src/components/nostr/kinds/TrustedAssertionDetailRenderer.tsx index 5fa5dd8..1d3c890 100644 --- a/src/components/nostr/kinds/TrustedAssertionDetailRenderer.tsx +++ b/src/components/nostr/kinds/TrustedAssertionDetailRenderer.tsx @@ -21,10 +21,9 @@ import { Progress } from "@/components/ui/progress"; import { cn } from "@/lib/utils"; function rankColor(rank: number) { - if (rank >= 70) return { indicator: "bg-green-600", text: "text-green-600" }; - if (rank >= 40) - return { indicator: "bg-yellow-600", text: "text-yellow-600" }; - return { indicator: "bg-red-600", text: "text-red-600" }; + if (rank >= 70) return { indicator: "bg-success", text: "text-success" }; + if (rank >= 40) return { indicator: "bg-warning", text: "text-warning" }; + return { indicator: "bg-destructive", text: "text-destructive" }; } /** diff --git a/src/components/nostr/kinds/TrustedAssertionRenderer.tsx b/src/components/nostr/kinds/TrustedAssertionRenderer.tsx index 011ea45..c61a8ab 100644 --- a/src/components/nostr/kinds/TrustedAssertionRenderer.tsx +++ b/src/components/nostr/kinds/TrustedAssertionRenderer.tsx @@ -3,7 +3,7 @@ import { BaseEventContainer, ClickableEventTitle, } from "./BaseEventRenderer"; -import { Badge } from "@/components/ui/badge"; +import { Label } from "@/components/ui/label"; import { UserName } from "../UserName"; import { ExternalIdentifierInline } from "../ExternalIdentifierDisplay"; import { @@ -20,10 +20,9 @@ import { Progress } from "@/components/ui/progress"; import { cn } from "@/lib/utils"; function rankColor(rank: number) { - if (rank >= 70) return { indicator: "bg-green-600", text: "text-green-600" }; - if (rank >= 40) - return { indicator: "bg-yellow-600", text: "text-yellow-600" }; - return { indicator: "bg-red-600", text: "text-red-600" }; + if (rank >= 70) return { indicator: "bg-success", text: "text-success" }; + if (rank >= 40) return { indicator: "bg-warning", text: "text-warning" }; + return { indicator: "bg-destructive", text: "text-destructive" }; } /** @@ -122,6 +121,11 @@ function MetricsPreview({ const tags = getAssertionTags(event); const rankTag = tags.find((t) => t.name === "rank"); + // Collect metric type labels for the tag row + const metricLabels = tags + .filter((t) => t.name !== "rank" && t.name !== "t") + .map((t) => ASSERTION_TAG_LABELS[t.name] || t.name); + let summaryMetrics: { label: string; value: string; unit?: string }[] = []; if (event.kind === 30382) { @@ -192,6 +196,15 @@ function MetricsPreview({ {/* Rank bar */} {rankTag && } + {/* Metric type labels */} + {metricLabels.length > 0 && ( +
+ {metricLabels.map((l) => ( + + ))} +
+ )} + {/* Summary metrics */} {summaryMetrics.length > 0 && (
@@ -221,14 +234,9 @@ export function TrustedAssertionRenderer({ event }: BaseEventProps) { return (
- {/* Kind badge + subject as title */} + {/* Kind label + subject as title */}
- - {kindLabel} - + {subject && }