Skip to content

Axis titles and units

Read as Markdown

AxisTitle(props: AxisTitleProps) from @pibbl/core/viz paints one title using an ancestor scale. It owns no layout or margin, modifies no ticks or marks, and creates no hit target. Place it inside the same translated plot composition as its Axis, reserving enough space outside that composition for the title.

Required properties are scale: ScaleId, position: "top" | "bottom" | "left" | "right", and label: SignalValue<string>. unit?: SignalValue<string> appends a nonempty unit as label (unit); omitted or empty units append nothing. There is no conversion of data or tick values. Format tick units separately with Axis/formatNumber.

The title centers on the scale’s pixel-range midpoint, including descending ranges. Top/bottom text is horizontal. Left text rotates −90 degrees and right text +90 degrees. offset?: SignalValue<number> is the distance from the plot edge to the text center in logical pixels, default 40. Edges use the scale’s allocation frame: left/top are zero, right/bottom are frame width/height. All scale families work, including empty point/band domains with a valid range.

Optional signal-valued style accepts signal-valued font (default 12px sans-serif), fill (default #617783), and opacity (default 1). Labels/units must be single-line strings; text is neither shortened nor wrapped. The caller chooses responsive wording and offsets and may use allocation-relative style.when on the owning Group to change presentation. The component does not measure neighboring labels or automatically reserve space.

Missing/unknown scale IDs, invalid positions, or non-string/multiline label/unit values throw TypeError. Negative/nonfinite offsets and opacity outside 0–1 throw RangeError. Core Text font/paint semantics apply. Signals and changes in the provider’s allocation update placement/text on the scheduled render; subscriptions detach on removal or disposal.

import { Group, pibbl } from "@pibbl/core";
import { Axis, AxisTitle, LinearScale } from "@pibbl/core/viz";
export default function mount(canvas: HTMLCanvasElement) {
return pibbl(
canvas,
<Group style={{ translateX: 80, translateY: 30 }}>
<LinearScale id="y" domain={[0, 100]} range={[150, 0]}>
<Axis scale="y" position="left" />
<AxisTitle
scale="y"
position="left"
label="Mass"
unit="kg"
offset={55}
/>
</LinearScale>
</Group>,
);
}

The population example labels its vertical axis with people, keeping the unit visible even when the heading is hidden in a shallow embed.

Use core Text for chart prose. It already measures and wraps text within an explicit box, with lineHeight and fit policies. No visualization-specific text wrapper is needed. Parent layouts or Groups own placement and reserve space for both the text and plot. For example:

import { Group, Text, pibbl } from "@pibbl/core";
export default function mount(canvas: HTMLCanvasElement) {
return pibbl(
canvas,
<>
<Text
style={{
left: 20,
top: 20,
width: 280,
font: "600 24px sans-serif",
fill: "#172f3d",
}}
>
Population change
</Text>
<Group style={{ translateX: 20, translateY: 80 }}>
<Text
style={{
width: 280,
height: 48,
wrap: true,
lineHeight: 16,
fit: "ellipsis",
font: "12px sans-serif",
fill: "#617783",
}}
>
Source: US Census Bureau, Vintage 2023. July 2022–July 2023; people.
</Text>
</Group>
</>,
);
}

Use style.when width/height queries on core Text and its owning layout to adapt captions and headings to their allocation. Keep essential units and attribution visible in shallow embeds, and explicitly budget sufficient height for wrapped text. See the core Text reference for fitting and signal behavior.

Simple legend keys likewise need only core shapes and Text: compose a Rectangle or Line using the same paint as the marks, followed by its label. Keep data visibility controls explicit. A separate viz component is useful only when it adds scale/data behavior beyond that core composition.

AxisTitle is intended as a sibling companion to Axis under the same scale and plot transform. Sharing scale and position keeps their geometry aligned as the allocation changes: Axis paints ticks at that edge, while AxisTitle tracks the range midpoint and applies its outward offset. It does not infer an Axis from the tree or require one to be mounted. The added value over core Text is this scale/frame-derived placement and edge-dependent rotation, not text layout. Increase the explicit offset and parent margin when tick labels need more room.

Paint an axis title with optional units, without allocating margins or changing ticks.

AxisTitle: (props: AxisTitleProps) => JSX.Element

Related API: AxisTitle, AxisTitleProps, JSX.

Decorative chart content in the caller’s coordinate space.

View source — packages/core/src/features/viz/lib/axis-title.tsx:25

Scale-aligned axis text; callers reserve the margin outside the plot. See AxisTitle.

interface AxisTitleProps

Related API: AxisTitleProps.

View source — packages/core/src/features/viz/lib/axis-title.tsx:7

scale
readonly scale: ScaleId

Related API: ScaleId.

Ancestor scale whose range supplies the title midpoint.

View source — packages/core/src/features/viz/lib/axis-title.tsx:9

position
readonly position: "bottom" | "left" | "right" | "top"

Plot edge; left/right titles rotate along the axis.

View source — packages/core/src/features/viz/lib/axis-title.tsx:11

label
readonly label: SignalValue<string>

Related API: SignalValue.

Single-line title.

View source — packages/core/src/features/viz/lib/axis-title.tsx:13

unit (optional)
readonly unit?: SignalValue<string> | undefined

Related API: SignalValue.

Optional unit appended in parentheses; empty string omits it.

View source — packages/core/src/features/viz/lib/axis-title.tsx:15

offset (optional)
readonly offset?: SignalValue<number> | undefined

Related API: SignalValue.

Nonnegative finite distance outside the plot edge, default 40 pixels.

View source — packages/core/src/features/viz/lib/axis-title.tsx:17

style (optional)
readonly style?: SignalValue<Readonly<{ readonly fill?: SignalValue<FillStyle | undefined>; readonly font?: SignalValue<string | undefined>; readonly opacity?: SignalValue<number | undefined>; }>> | undefined

Related API: SignalValue, FillStyle, opacity.

Font defaults to 12px sans-serif, fill to #617783, opacity to 1.

View source — packages/core/src/features/viz/lib/axis-title.tsx:19

Read the Data visualization companion for ownership, adaptation, failure modes, and verification. Agent start provides the version-selection workflow.

Documentation built with @pibbl/core 0.0.2, revision 272a94a. ALPHA — NOT FOR PRODUCTION USE.