Hero Metric
render_hero_metricRender a hero metric widget with variants to answer key business questions: big number, progress ring, status, comparison, rank, countdown, threshold, breakdown, NPS, orb, and gem.
Instructions
Render a purpose-driven hero metric widget. Pick the variant that answers your question:
big_number: 'How much? Which direction?' Default hero metric - clean, professional, works in any context. Large value + trend arrow + optional sparkline. Params: value, unit, change, changePeriod, sparkline[]
progress_ring: 'How close to goal?' Animated ring or half-gauge. Params: value, unit, label, progress (0-100), style ('ring'|'gauge'), size, color
status: 'Good or bad?' Pulsing dot + subsystem badges. Params: label, statusLevel ('good'|'warn'|'bad'), subsystems[{name,status}], count, peak
comparison: 'How do we compare?' Before/after + improvement. Params: before, after, improvement, beforeLabel, afterLabel
rank: 'Where do I stand?' Badge + percentile. Params: rank, total, percentile, rankChange
countdown: 'How long left?' Time segment boxes. Params: segments[{value,label}] OR deadline (ISO date)
threshold: 'Above or below limit?' Gradient bar + marker. Params: value, max, threshold, unit, zones[{label,from,to,color}]
breakdown: 'What is the split?' Stacked bar + legend. Params: items[{label,value,color?}]
nps: 'How satisfied?' Score + rating scale. Params: value, max (default 100), rating ('good'|'neutral'|'bad')
orb: 'What is the headline?' Dramatic glowing sphere. Use golden orb for resumes/portfolios. For tech meetings use only black, white, or crystal-colored orbs as subtle flair. Best with dark themes (tokyo-midnight, ops-control, startup). Avoid for formal contexts (boardroom, clinical, consultant). Params: value, unit, label, color
gem: 'Premium gem metric' Faceted/spherical gem - for wealth, fintech, trading, crypto, luxury contexts ONLY. Best with golden-treasury, tokyo-midnight themes. Do NOT use for corporate, clinical, consultant, or boardroom dashboards - use big_number instead. Params: value, unit, label, gemType. gemTypes: crystal='Future' (forecasts, projections) | black_pearl='Rare find' (alt investments, crypto) | golden_pearl='Treasure' (gold, commodities) | white_pearl='Clean total' (savings) diamond='Crown number' (net worth, total revenue) | ruby='What's critical' (urgent, burn rate) | sapphire='Foundation' (stability, uptime) | emerald='Growth' (YoY, appreciation)
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| title | Yes | Chart title | |
| variant | No | Widget variant (default: big_number) | |
| value | No | Main metric value | |
| unit | No | Unit label (e.g. 'grams', '%', 'USD') | |
| label | No | Sub-label | |
| color | No | Override accent color (hex) | |
| progress | No | Ring fill 0-100 | |
| size | No | Size: sm/md/lg/xl | |
| style | No | progress_ring style | |
| change | No | Percentage change | |
| changePeriod | No | Period label for change (e.g. 'vs last month') | |
| sparkline | No | Mini bar sparkline data | |
| statusLevel | No | Status level | |
| subsystems | No | Subsystem badges | |
| count | No | Live count | |
| peak | No | Peak count | |
| before | No | Before value | |
| after | No | After value | |
| improvement | No | Improvement label | |
| beforeLabel | No | Before column label | |
| afterLabel | No | After column label | |
| rank | No | Current rank | |
| total | No | Total in ranking | |
| percentile | No | Percentile | |
| rankChange | No | Positions moved | |
| segments | No | Time segments | |
| deadline | No | ISO deadline date | |
| max | No | Maximum value for threshold/nps | |
| threshold | No | Threshold limit line | |
| zones | No | Color zones | |
| items | No | Breakdown items | |
| rating | No | NPS rating override | |
| gemType | No | Gem type for variant=gem: diamond, ruby, sapphire, emerald, golden_pearl, white_pearl, black_pearl, crystal | |
| theme | No | Theme preset: boardroom, corporate, sales-floor, golden-treasury, clinical, startup, ops-control, tokyo-midnight, zen-garden, consultant, black-tron, black-elegance, black-matrix, forest-amber, forest-earth, sky-light, sky-ocean, sky-twilight, gray-hf, gray-copilot | |
| palette | No | Override palette only (mix-and-match) | |
| typography | No | Override typography: professional, luxury, cyberpunk, editorial, mono, bold, system, techno | |
| effects | No | Override effects: none, subtle, shimmer, neon, energetic |
Implementation Reference
- src/charts/hero.ts:575-603 (handler)Main handler function for the render_hero_metric tool. Renders a hero metric card with theme support and delegates to renderHeroWidget for variant-specific content (big_number, progress_ring, status, comparison, rank, countdown, threshold, breakdown, nps, orb, gem). Also adds HTML export and refresh buttons.
export function renderHeroMetric(container: HTMLElement, payload: HeroPayload): void { const theme = resolveTheme(payload.theme, { palette: payload.palette, typography: payload.typography, effects: payload.effects, }); if (theme) applyTheme(container, theme); container.className = "chart-view"; container.innerHTML = ` <div class="card chart-card hero-metric"> <div class="chart-card__header"> <div> <div class="chart-card__title${theme?.effects.shimmerTitle ? " shimmer-text" : ""}">${escapeHtml(payload.title || "Metric")}</div> </div> </div> <div class="hero-metric__body"></div> </div> `; const body = container.querySelector<HTMLElement>(".hero-metric__body")!; renderHeroWidget(body, payload); const card = container.querySelector<HTMLElement>(".chart-card")!; addHtmlExportButton(card, payload.title || "hero-metric"); addRefreshButton(card, () => { (window as any).__mcpRefresh?.(); }); } - src/charts/hero.ts:8-69 (schema)HeroPayload interface defining the full input schema for render_hero_metric. Supports multiple variants: big_number, progress_ring, status, comparison, rank, countdown, threshold, breakdown, nps, orb, gem.
interface HeroPayload { type: "hero_metric"; variant?: HeroVariant; title?: string; theme?: string; palette?: string; typography?: string; effects?: string; // big_number value?: string | number; unit?: string; label?: string; change?: number; changePeriod?: string; sparkline?: number[]; // progress_ring (absorbed speedometer) progress?: number; color?: string; size?: "sm" | "md" | "lg" | "xl"; style?: "ring" | "gauge"; // status (absorbed live_counter) statusLevel?: "good" | "warn" | "bad"; subsystems?: Array<{ name: string; status: "good" | "warn" | "bad" }>; count?: number; peak?: number; // comparison before?: number | string; after?: number | string; improvement?: number | string; beforeLabel?: string; afterLabel?: string; // rank rank?: number; total?: number; percentile?: number; rankChange?: number; // countdown segments?: Array<{ value: number; label: string }>; deadline?: string; // threshold max?: number; threshold?: number; zones?: Array<{ label: string; from: number; to: number; color: string }>; // breakdown items?: Array<{ label: string; value: number; color?: string }>; // nps rating?: "good" | "neutral" | "bad"; // orb (uses value, label, color) // events (for ticker - not used, kept for future) events?: Array<{ text: string; time?: string; type?: string }>; } - src/charts/shared.ts:188-193 (registration)registerChart function that registers chart types with their tool names and render functions into a central registry.
export function registerChart( type: string, toolName: string, render: (root: HTMLElement, data: any) => void, ): void { CHART_REGISTRY[type] = { toolName, render }; - src/charts/hero.ts:605-605 (registration)Registration call linking the chart type 'hero_metric' to the tool name 'render_hero_metric' and the renderHeroMetric handler function.
registerChart("hero_metric", "render_hero_metric", renderHeroMetric); - src/charts/hero.ts:524-571 (helper)renderHeroWidget helper function that routes to the correct variant renderer based on the payload variant field (big_number, progress_ring, status, comparison, rank, countdown, threshold, breakdown, nps, orb, gem).
export function renderHeroWidget(body: HTMLElement, p: any): void { const variant = p.variant || "big_number"; switch (variant) { case "big_number": renderBigNumber(body, p); break; case "progress_ring": renderHeroRing(body, { value: p.value ?? "", unit: p.unit, label: p.label, progress: p.progress, color: p.color, size: p.size, style: p.style, }); break; case "status": renderStatus(body, p); break; case "comparison": renderComparison(body, p); break; case "rank": renderRank(body, p); break; case "countdown": renderCountdown(body, p); break; case "threshold": renderThreshold(body, p); break; case "breakdown": renderBreakdown(body, p); break; case "nps": renderNps(body, p); break; case "orb": renderOrb(body, p); break; case "gem": renderGem(body, p); break; default: renderBigNumber(body, p); } }