Explain this metric Two people read the same tile and mean different things by it. The definition belongs next to the number, not in a wiki nobody opens, and it has to name who owns it so a disagreement has somewhere to go. npx shadcn@latest add popover button card npm i lucide-react Tokens this needs: --card, --card-foreground, --popover, --popover-foreground, --muted, --muted-foreground, --border ──────────────────────────────────────────────────────────────────────── // MetricDefinition.tsx ──────────────────────────────────────────────────────────────────────── import { useState } from "react"; import { Info } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card } from "@/components/ui/card"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; /** * Four fields, all required. A definition is not a sentence; it is what is * counted, over what window, with what left out, and who to argue with. Leave * any one out and two honest readers of the tile will still disagree. */ export type Definition = { /** In the reader's words, not the column name. */ counts: string; window: string; excludes: string; /** A team or a person. A definition nobody owns is one nobody can correct. */ owner: string; }; type Props = { label: string; value: string; /** The window the tile shows, which the definition should agree with. */ range: string; definition: Definition; onOwnerClick: (owner: string) => void; /** Start with the definition showing, as when the tile is the exhibit. */ defaultOpen?: boolean; }; export function MetricDefinition({ label, value, range, definition, onOwnerClick, defaultOpen = false }: Props) { const [open, setOpen] = useState(defaultOpen); const rows: [string, string][] = [ ["Counts", definition.counts], ["Window", definition.window], ["Excludes", definition.excludes], ]; return ( {/* A div, not a p: the popover renders inline here in the preview, and block content inside a paragraph splits it. */}
{label} {/* Non-modal: a definition should not lock the dashboard behind it. */}

{label}

{rows.map(([k, v]) => (
{k}
{v}
))}

Owned by

{value}

{range}

); } ──────────────────────────────────────────────────────────────────────── // demo.tsx ──────────────────────────────────────────────────────────────────────── import { MetricDefinition } from "./MetricDefinition"; /** * The tile with its definition already open, since the definition is the * thing being shown. The owner chip is where a disagreement goes. */ export default function Demo() { return (
{}} defaultOpen />
); }