Axis
Ticks from the scale that placed the data.
Preview
Positions come from the same scale that places the data, so an axis cannot disagree with the marks it labels. drawAxis() paints the identical ticks onto a canvas.
About
An axis used to be a loop inlined into each viewer's draw — a third copy of the positioning arithmetic, after the one placing the data and the one hit-testing it, drifting from both. Those loops also produced a step of 0 when the max was under 5, hung at max 0, and labelled 2.5000000000000004 whenever the data wasn't integral. Here ticks come from scale.ticks() and positions from the scale itself, so an axis cannot disagree with the marks it labels. drawAxis() paints onto canvas, <Axis> renders SVG, and the two share one tick computation so a canvas plot stacked over an SVG one lines up.
Usage
import { drawAxis } from "@/components/ui/axis"
drawAxis(ctx, tokens, {
scale: frame.y,
side: "left",
rect: frame.inner,
title: "−log₁₀ p",
grid: true,
})components/ui/axis.tsx