Skip to main content
Slots replace how a single region of the chart renders while the spec still owns whether that region exists and what data it receives. Your override gets the same render-ready props the default would. Pass them through the slots prop.

Regions

EditorSurface defaults to a no-op, so a read-only embed bundles no editing code; @graphysdk/react-renderer/editable is what fills it. A chart that only paints leaves it alone.
Custom Footer / Header slots receive a brandMark visual ('full' | 'mini' | 'hidden'), resolved from config.content.brandMark and the frame size. That prop is not the visibility toggle; the toggle is brandMark.enabled (or legacy isBrandMarkVisible). source remains your data-source attribution. The default badge paints inside the matching region when placement matches.

Three kinds of slot

How a region earns its space decides what you hand the slot. The type reflects it: layout-safe slots (the first two kinds) are bare components, layout-coupled slots are a SlotOverride object.

Box-filling — Tooltip, Grid, Swatch, EditorSurface

These paint inside a box the layout already sized, or float free of it. Provide a component and nothing else:
The tooltip’s positioning stays built in — you own the body, not the anchor. These reserve their own space, and the layout measures the rendered DOM to find out how much. Both prop types carry a ref: forward it to your outer element, or the region reserves zero height and the plot paints over it.

Layout-coupled — Legend, Headline, AxisTicks, AxisLabel

These reserve an edge band the layout sizes up front, so they’re a SlotOverride: a render component and a measure that reports the region’s size. Paint and reserved space must agree, so the layout asks measure how much room to leave:
Legend, AxisTicks and AxisLabel take a (region, ctx) => number — the band’s thickness in pixels, a height on the top and bottom edges and a width on the left and right. Headline takes a HeadlineMeasurer instead: an object with measureHeadline(headline, size) returning a { width, height } box and measureHeadlineItemWidths(headline, size) returning each strip item’s width.
The second argument to the function-shaped measures is a SlotMeasureContext: measureText(text, { family, size }) — the same Canvas-backed measurer the built-in regions use, taking a final pixel size — and the active textScale to multiply an em size by. Sizing from those keeps your reserved band matched to what actually paints.
Give a layout-coupled slot’s measure a stable reference (define it outside render or memoize it). The layout reads overrides through a ref so an inline measure still takes effect on the next paint — but that paint doesn’t retrigger layout, so paint and reserved space drift apart.
Two of the measures are skipped where the band is empty: AxisTicks’s reserves 0 for an axis with no tick band, and Legend’s reserves 0 for an empty legend — your override isn’t consulted in those cases. AxisLabel’s has no such gate.

Slot props

Every props type is exported from @graphysdk/react-renderer, along with DefaultHeader, DefaultFooter, DefaultTooltip, DefaultGrid and DefaultSwatch to wrap or delegate to. The rects a slot receives are SVG-local for the in-panel regions (Grid, AxisTicks, AxisLabel) and layout rects for the rest.
A slot’s measure lands on the layout measurer under its own name: AxisTicks.measure becomes measureAxis, AxisLabel.measure becomes measureAxisLabel, and Headline.measure’s two methods keep theirs. That’s the SlotMeasureOverrides shape you’ll see in the layout types.
  • Geom renderers — replace a whole geom’s paint, not just a region
  • Interactivity — the Tooltip slot in context
  • Theming — restyle regions with tokens before reaching for a slot