UNPKG

@tanstack/charts

Version:

A chart grammar for TypeScript and JavaScript. Marks consume your data directly, channels describe visual encodings, and the engine compiles them into a renderer-neutral keyed scene. TanStack's compact scales cover common numeric and categorical mappings.

229 lines (182 loc) 10.9 kB
--- title: Text, Frame, and Facet Marks description: Reference for data labels, chart frames, responsive small multiples, shared or per-cell axes, labels, and facet constraints. --- `text` annotates scaled positions, `frame` paints the resolved inner chart bounds, and `facet` composes complete child specs into responsive small multiples. ```ts import { facet, facetChart, frame, lineY, text } from '@tanstack/charts' ``` ## `text` ```ts text(rows, { x: 'date', y: 'value', text: 'label', z: 'series', dy: -8, }) ``` ```ts function text<TDatum>( source: Iterable<TDatum>, options?: TextOptions<TDatum>, ): ChartMark<TDatum, InferredX, InferredY> ``` ### Options | Option | Type | Default | Meaning | | ------------ | ------------------------------------ | ---------------------------------- | ------------------------------------------------- | | `id` | `string` | Layer-derived | Stable mark ID | | `x` | `Channel<TDatum, ChartValue?>` | Row index | Horizontal anchor | | `y` | `Channel<TDatum, ChartValue?>` | Numeric datum | Vertical anchor | | `text` | `Channel<TDatum, string \| number?>` | String form of datum | Label content | | `z` | `Channel<TDatum, ChartKey?>` | No group | Interaction group | | `color` | `Channel<TDatum, ChartKey?>` | `z` | Value sent to the chart color scale | | `key` | `Channel<TDatum, ChartKey>` | ID, x, y, x/y, index | Stable identity | | `fill` | `VisualChannel<TDatum, string>` | Theme foreground or resolved color | Final label paint override | | `fontSize` | `number` | Inherited SVG font size | Font size | | `fontWeight` | `number` | Inherited weight | Numeric font weight | | `anchor` | `VisualChannel<TDatum, TextAnchor>` | `'middle'` | `'start'`, `'middle'`, or `'end'` | | `rotate` | `VisualChannel<TDatum, number>` | No transform | Rotation in degrees around the final label origin | | `dx` | `VisualChannel<TDatum, number>` | `0` | Horizontal pixel offset | | `dy` | `VisualChannel<TDatum, number>` | `0` | Vertical pixel offset | | `states` | `readonly ChartMarkState[]` | None | Focus-driven presentation overrides | Labels use a middle baseline. Null or undefined text skips the row; the default for a null datum is an empty string. Invalid x/y values also skip the row. The interaction point is at the offset label origin. Its semantic values remain the original x/y channels. Without an explicit key, `text` tries a unique top-level or nested `data.id`, then x, y, and the x/y tuple. Supply `key` when positions can change while the same label should reconcile across updates. ## `frame` `frame` draws a background, border, or both around the final inner chart bounds: ```ts frame({ fill: 'color-mix(in srgb, currentColor 3%, transparent)', strokeOpacity: 0.25, radius: 8, }) ``` ```ts function frame(options?: FrameOptions): ChartMark<never, never, never> ``` | Option | Type | Default | Meaning | | --------------- | -------- | ---------------- | ------------------------------------------------------------------- | | `id` | `string` | Layer-derived | Stable mark ID | | `fill` | `string` | `'none'` | Constant fill | | `fillOpacity` | `number` | SVG default | Fill opacity | | `stroke` | `string` | Theme foreground | Constant stroke | | `strokeOpacity` | `number` | `0.35` | Stroke opacity | | `strokeWidth` | `number` | `1` | Stroke width | | `inset` | `number` | `0` | Pixels removed from all chart-bound edges; clamped to at least zero | | `radius` | `number` | None | Corner radius | `frame` materializes no scale channels and emits no interaction points. Put it before data marks when it should paint behind them. ## `facet` `facet` groups source rows by a key and renders one complete child chart spec per group inside the parent chart bounds. ```ts facet(rows, { by: 'region', columns: 3, minWidth: 220, gap: 16, label: (region) => `Region: ${region}`, chart(groupRows) { return { marks: [lineY(groupRows, { x: 'date', y: 'value' })], x: { scale: makeXScale(groupRows) }, y: { scale: makeYScale(groupRows), grid: true }, } }, }) ``` ```ts function facet<TDatum, TChildSpec extends ChartSpec>( source: Iterable<TDatum>, options: FacetOptions<TDatum, TChildSpec>, ): ChartMark<ChartSpecDatum<TChildSpec>> ``` ### Options | Option | Type | Default | Meaning | | ---------- | ---------------------------------------------------------------------------------- | ------------------------- | -------------------------------------------------------------- | | `id` | `string` | Layer-derived | Stable outer mark ID | | `by` | `Channel<TDatum, ChartKey>` | Required | String or number grouping key | | `chart` | `(data: readonly [TDatum, ...TDatum[]], context: FacetChartContext) => TChildSpec` | Required | Builds one static child spec from a nonempty group | | `columns` | `number` | Automatic | Requested column count, floored and clamped to `1..groupCount` | | `minWidth` | `number` | `220` | Target minimum cell width used for automatic columns | | `gap` | `number` | `16` | Gap between rows and columns, clamped to at least zero | | `label` | `boolean \| ((key) => string)` | `true` | Shows default key labels, formats them, or disables labels | | `axes` | `'outer' \| 'cell'` | `'outer'` where shareable | Shared outside axes or independent axes in every cell | | `motion` | `ChartMotionDefinition<ChartSpecDatum<TChildSpec>>` | None | Motion policy over child-mark data | `FacetChartContext.key` is the materialized value for the current group. Facet preserves first-seen group order and original row order within each group. Non-string and non-number `by` results are skipped. Automatic columns are: ```text floor((availableWidth + gap) / (minWidth + gap)) ``` with a minimum of one. Rows are then derived from group count. Visible facet labels reserve 22 pixels above every child plot. ### Outer axes With more than one child and guides enabled, the default `axes: 'outer'` renders y ticks on the first column, x ticks on the final occupied row, and one shared title per dimension. Outer axes require compatible cells: - x and y resolved scale types, domains, ticks, labels, and direction match - axis label, label offset, and tick rotation match - foreground and muted theme tokens match - no child provides its own `margin` - no child provides a color legend - no child sets `guides: false` An incompatible facet throws with guidance to use `axes: 'cell'`. This fail-fast behavior prevents a shared axis from implying a comparison the child scales do not support. When every child sets `guides: false`, or there is only one child, facet uses the cell rendering path even if `axes` is omitted. ### Cell axes Set `axes: 'cell'` when groups need independent scales, guide options, margins, or legends: ```ts facet(rows, { by: 'region', axes: 'cell', chart: (groupRows) => buildIndependentSpec(groupRows), }) ``` Every child compiles at its own cell dimensions with the parent's text measurement. Compilation errors are wrapped with the facet and cell key. ### Interaction Child `ChartPoint` coordinates are offset into the parent scene. Point keys are prefixed with facet and group identity, so equal child keys remain unique across cells. Datum, semantic x/y values, group, group label, and paint are preserved. The facet's output datum type comes from the marks returned by `chart`; grouping rows do not replace a child point's original datum. Motion callbacks receive that same child datum type. The facet mark itself has intentionally opaque positional types because each child may return a different mark composition. Its child scale domains do not participate in the parent x/y scales. ## `facetChart` `facetChart` wraps a facet mark in a complete static definition: ```ts const definition = facetChart(rows, { by: 'region', chart: (groupRows) => buildSpec(groupRows), }) ``` ```ts function facetChart<TDatum, TChildSpec extends ChartSpec>( source: Iterable<TDatum>, options: FacetOptions<TDatum, TChildSpec>, ): StaticChartDefinition<ChartSpecDatum<TChildSpec>> ``` The wrapper sets: ```ts const specification = { marks: [facet(source, options)], margin: 0, } ``` Use `facet` directly when the small multiples must be layered with other parent-scene marks. Use `facetChart` for the usual standalone chart.