"use client" /** * Extracted sparkline / micro-bar chart for KeyMetrics tiles. * Loaded lazily — only pulled when a metric has chart data. */ import * as React from "react" import { Area, AreaChart, Bar, BarChart, XAxis } from "recharts" import { ChartContainer, ChartTooltip, ChartTooltipContent, type ChartConfig, } from "./chart" import { cn } from "../../lib/utils" import type { MetricChart, MetricProgressTone } from "./key-metrics" import { normalizeMetricChartSeries } from "./key-metrics" function metricChartStroke(tone: MetricProgressTone = "brand"): string { switch (tone) { case "success": return "var(--chart-2)" case "warning": return "var(--chart-4)" case "danger": return "var(--destructive)" case "info": return "var(--primary)" case "auto": return "var(--primary)" case "brand": default: return "var(--brand-color)" } } export type MetricMiniChartProps = { chart: MetricChart height: number metricLabel: string className?: string } /** Breathing room between a mini chart's plot and its tooltip. */ const MINI_CHART_TOOLTIP_GAP = 8 const MINI_CHART_TOOLTIP_WRAPPER: React.CSSProperties = { zIndex: 70, outline: "none", pointerEvents: "none", } /** * Recharts sparkline / micro-bars (ChartContainer). * Uses the shared ChartTooltipContent popover on hover. * Keep overflow visible on ancestors so the tooltip is not clipped; clip only * the SVG surface for md/lg bottom radius. * `sm` height (~28px): thinner stroke, no idle dots (activeDot on hover only). */ export function MetricMiniChart({ chart, height, metricLabel, className }: MetricMiniChartProps) { const points = React.useMemo( () => normalizeMetricChartSeries(chart.series).slice(0, 12), [chart.series], ) const gradientId = React.useId().replace(/:/g, "") const stroke = metricChartStroke(chart.tone ?? "brand") const compact = height <= 32 const data = React.useMemo( () => points.map((point) => ({ label: point.label ?? "", value: point.value })), [points], ) const config = React.useMemo( () => ({ value: { label: metricLabel, color: stroke }, }), [metricLabel, stroke], ) if (points.length < 2) return null const margin = compact ? { top: 2, right: 1, left: 1, bottom: 1 } : { top: 4, right: 0, left: 0, bottom: 0 } const tooltip = ( } /> ) return (
{chart.kind === "sparkline" ? ( {tooltip} ) : ( {tooltip} )}
) }