Kanzo UI
Hooks

useChartContext

The chart context — config, selections, coordinator, and the color / formatNumber helpers — for a DOM part of your own inside a ChartRoot.

The bars are one ChartBarY; everything under them is a component of our own, reading the same context ChartLegend reads. The colour beside each label is the literal color(key) returned — the very string the plot was handed — and the caption counts in the root's own number vocabulary.

Usage

import { useChartContext } from "@kanzo-tech/ui/analytics";

The /analytics peers are optional — nothing installs them unless you import this subpath.

function Total({ rows }: { rows: number }) {
  const { color, formatNumber } = useChartContext();
  return <p style={{ color: color("error") }}>{formatNumber(rows)} requests</p>;
}

It must be rendered inside a ChartRoot — it throws otherwise. Use useChartContextOptional for a part that also has to work standalone.

Why it exists

vgplot paints imperatively: ChartRoot mounts the SVG node it returns with host.replaceChildren(...). There is no element for a legend, a tooltip or a caption to hang off, so anything of that kind is your DOM sitting beside the plot — and it needs the plot's config, its selections and its number format to say anything true. That is the whole content of this context, and it is what makes a part writable without forking ChartLegend.

color(key)

color returns the series colour already resolved to rgb(...), which is what makes it dual-purpose: Observable Plot's isColor rejects var(--token), color-mix(), oklch() and color(srgb …) — hand it one and the string is read as a column name, killing the query with a binder error and leaving the plot on its previous render. The token is resolved against the element the chart lives in, so a scoped theme override on an ancestor wins.

Resolving is also what makes it a snapshot. Nothing re-calls color when the theme flips or the tenant's theme is swapped. If your sink is only a style, pass var(--chart-N) straight through and let the browser follow the theme for free — that is what ChartLegend does. Pair this with useThemeTick when you need the literal, which is to say when you are handing it to Plot or to a canvas.

Descriptors cannot use it

Marks, interactors and axes are inert descriptors: ChartRoot reads their props off the element before React ever renders them, so a mark cannot pull anything out of context. Pass the value down from the component that owns the ChartRoot instead.

API Reference

function useChartContext(): ChartContextValue;

Takes no arguments. Throws useChartContext must be used within a <ChartRoot>. outside one.

Returns

FieldTypeWhat it is
color(key: string) => string | undefinedthe series colour, resolved to rgb(...). undefined for a key the config does not name
formatNumber(value: number, options?: Intl.NumberFormatOptions) => stringthe chart's Intl.NumberFormat, from the root's locale / numberFormat
configChartConfigseries key → { label, color, icon }, as the root was given it
tablestring | undefinedthe relation the root reads
filterBySelection | nullwhat the marks filter by; null = the full relation
asSelectionwhere the interactors publish
coordinatorCoordinatorfor a part that queries alongside the plot — usually via useChartQuery

On this page