M
MetricUI
Guide

Interactions

Visual coordination between dashboard components. Linked hover syncs crosshairs across charts. Value flash highlights data changes in real time. For click-based filtering, see Cross-Filtering in the Filtering guide.

Overview

MetricUI provides two visual interaction primitives, each opt-in and independent:

FeatureWhat It DoesTrigger
Linked HoverHover a data point → crosshairs sync across all chartsHover
Value FlashData changes → brief highlight animation on the valueData update

Both are purely visual — they coordinate what users see across components without touching your data. Wrap in a Provider, and the components handle the rest.

Linked Hover

Linked hover syncs hover state across all charts in a provider. Hover over “March” in an area chart, and the bar chart, line chart, and any other sibling highlights March too — synced crosshairs, synced tooltips, synced emphasis.

Try It

Hover over any chart — the other follows your cursor.

Revenue
Orders
<LinkedHoverProvider>
  <AreaChart
    title="Revenue"
    data={monthlyData}
    index="month"
    categories={[{ key: "revenue", format: "currency" }]}
  />
  <BarChart
    title="Orders"
    data={monthlyData}
    index="month"
    categories={["orders"]}
  />
</LinkedHoverProvider>

Setup

Wrap in LinkedHoverProvider. Charts inside it automatically participate — no extra prop needed:

import {
  LinkedHoverProvider,
  AreaChart,
  BarChart,
  LineChart,
} from "metricui";

function Dashboard() {
  return (
    <LinkedHoverProvider>
      <AreaChart
        title="Revenue"
        data={data}
        index="month"
        categories={["revenue"]}
      />
      <BarChart
        title="Orders"
        data={data}
        index="month"
        categories={["orders"]}
      />
    </LinkedHoverProvider>
  );
}

Hover over any chart and the others follow. The charts share the same indexvalues (“Jan”, “Feb”, etc.), so linked hover matches by index.

Reading Hover State

Use useLinkedHover() to read hover state in custom components:

import { useLinkedHover } from "metricui";

function HoverDebug() {
  const lh = useLinkedHover();

  if (!lh?.hoveredIndex) return null;

  return (
    <div>
      Hovering: {lh.hoveredIndex}
      {lh.hoveredSeries && <> / Series: {lh.hoveredSeries}</>}
    </div>
  );
}
PropertyTypeDescription
hoveredIndexstring | number | nullThe x-axis value being hovered (e.g. "Mar")
hoveredSeriesstring | nullThe series/category being hovered (e.g. "revenue")
sourceIdstring | undefinedWhich component emitted the hover event
setHoveredIndex(index, sourceId?) => voidProgrammatically set the hovered index
setHoveredSeries(seriesId, sourceId?) => voidProgrammatically set the hovered series

Value Flash

Value flash is a hook that adds a brief highlight animation when watched data changes. You choose which components flash and what data to watch — it's not automatic. Useful for real-time dashboards where individual values update via polling or websockets.

Try It

These KPI cards update every 2.5 seconds. Watch for the flash when values change.

Revenue
$0
Customers
0
function LiveKpi({ value, ...props }) {
  const flashClass = useValueFlash(value);
  return (
    <div className={flashClass}>
      <KpiCard value={value} {...props} />
    </div>
  );
}

Usage

useValueFlash is a hook that returns a CSS class name. Apply it to the container you want to flash:

import { useValueFlash } from "metricui";

function LiveMetric({ value }: { value: number }) {
  const flashClass = useValueFlash(value);

  return (
    <div className={flashClass}>
      {value.toLocaleString()}
    </div>
  );
}

The hook watches the value you pass. On the first render, nothing happens. When the value changes, it returns "mu-value-flash" for the duration of the animation, then reverts to an empty string.

It works with any data type — numbers, strings, arrays, objects. For complex values it uses deep comparison internally.

Options

const flashClass = useValueFlash(value, {
  duration: 800,    // Flash duration in ms (default: 600)
  disabled: false,  // Disable flash entirely
});

Value flash automatically respects:

  • MetricProvider's animate setting — if animations are off, no flash
  • prefers-reduced-motion — respects the user's OS preference
  • First render — no flash on mount, only on subsequent changes

Combining Both

The providers nest naturally. Linked hover and value flash work together:

import {
  MetricProvider,
  LinkedHoverProvider,
  MetricGrid,
  KpiCard,
  AreaChart,
  BarChart,
  useValueFlash,
} from "metricui";

function Dashboard({ data }) {
  return (
    <MetricProvider theme="indigo">
      <LinkedHoverProvider>
        <MetricGrid>
          {/* KPIs flash when data updates */}
          <LiveKpi title="Revenue" value={data.revenue} format="currency" />
          <LiveKpi title="Orders" value={data.orders} format="compact" />

          {/* Charts sync hover automatically */}
          <AreaChart
            title="Revenue Over Time"
            data={data.timeSeries}
            index="month"
            categories={["revenue"]}
          />
          <BarChart
            title="Orders by Month"
            data={data.timeSeries}
            index="month"
            categories={["orders"]}
          />
        </MetricGrid>
      </LinkedHoverProvider>
    </MetricProvider>
  );
}

function LiveKpi({ title, value, format }) {
  const flashClass = useValueFlash(value);
  return (
    <div className={flashClass}>
      <KpiCard title={title} value={value} format={format} />
    </div>
  );
}

Linked hover is visual coordination. Value flash is a CSS animation hook. For click-based filtering, see Cross-Filtering in the Filtering guide.