Axes and ticks

Axis titles, tick positions, tick label text, and tick collision policy come from three cooperating surfaces: labs (plot-level titles), scales (where ticks fall and how they format), and guides (whether the axis draws ticks/labels and how crowded labels behave). Grid lines are theme chrome, not axis-guide options.

Who owns what

Labs
Human titles for the plot and each aesthetic (x/y/legends). Defaults humanize mapped field names.
Scales
breaks, minorBreaks, labels (format string), temporal dateBreaks / dateLabels / locale, and scale-local guide (including band-axis layout).
GuideAxis
Per-channel axis presentation: optional title override, show/hide ticks and labels, collision policy, and bounded guide theme overrides.
Theme
Panel grid color, width, dasharray, and gridX/gridY toggles — not fields on GuideAxis.

GuideAxis

Declaration-only child. Keys an axis guide by positional channel: <GuideAxis channel="x" showTicks={false}/> assembles guides: { x: { type: "axis", showTicks: false } }. Prefer the shell when the shape is fixed; use <Guides value={…} /> for multi-channel bags.

channel
Required. "x" or "y" only — other aesthetics use legend, colorbar, or colorsteps guides.
title
Optional axis title string (max 256). Overrides the title from Labs / humanized field defaults for this guide.
showTicks
When false, omit tick marks.
showLabels
When false, omit tick labels (ticks may still draw).
collision
"auto" (default layout), "preserve" (keep full labels even when crowded), or "ellipsis" (truncate with ellipsis under pressure).
theme
Bounded presentation overrides for this guide block (titleSize, labelSize, gaps, colorbar sizes).
import { GeomPoint, GGPlot, GuideAxis, Labs } from "@ggsvelte/svelte";

<GGPlot data={rows} aes={{ x: "hour", y: "pm25" }}>
  <Labs x="Hour of day" y="PM2.5" />
  <GuideAxis channel="x" showTicks={false} collision="ellipsis" />
  <GuideAxis channel="y" title="µg/m³" />
  <GeomPoint />
</GGPlot>

Scale breaks and label formats

Scales choose which ticks exist and how each tick’s text is formatted. Guides only decide whether those labels draw and how collisions resolve.

  • breaks — explicit major tick positions in semantic source units (numbers, or ISO date strings on time scales). Omit for automatic ticks.
  • minorBreaks — explicit minor gridline positions. A value that coincides with a major break draws only the major tick. Time scales use dateMinorBreaks instead.
  • labels — format string, not a parallel array. Numeric: ",d", ".1f", ".0%", "~s". Time: strftime-style such as "%Y-%m" or "%b %d". Temporal authors usually prefer dateLabels + locale over the soft-fallback labels field — see Dates without preprocessing.
<GGPlot data={rows} aes={{ x: "weight", y: "economy" }}>
  <Scale
    value={{
      x: {
        type: "linear",
        breaks: [2000, 3000, 4000],
        labels: ",d",
        minorBreaks: [2500, 3500],
      },
      y: { type: "linear", labels: ".1f" },
    }}
  />
  <GeomPoint />
</GGPlot>

Explicit breaks outside the trained domain are omitted with scale-break-outside-domain. Major breaks win when major and minor coincide. reverse flips pixel direction without reordering semantic ticks.

Band axis label layout

Discrete (band) position scales accept a scale-local guide object with band layout fields retained separately from axis appearance:

  • mode: "auto" | "single" | "wrap" | "rotate" | "off"
  • angle — degrees when mode is "rotate"
  • wrap — max wrapped lines (1–8) when mode is "wrap"
<GGPlot data={rows} aes={{ x: "category", y: "count" }}>
  <Scale
    value={{
      x: {
        type: "band",
        guide: { mode: "rotate", angle: -35 },
      },
    }}
  />
  <GeomCol />
</GGPlot>

Top-level guide children still replace a scale-local guide on the same channel whole. The shells carry no scale knowledge: wrong guide types fail loudly rather than degrading.

Builder and JSON

Portable helpers from @ggsvelte/spec match the Svelte shells:

import { guideAxis, guideNone } from "@ggsvelte/spec";

const guides = {
  x: guideAxis({ title: "Hour", showTicks: false }),
  y: guideAxis({ showLabels: true, collision: "preserve" }),
  color: guideNone(),
};

Attach with fluent .guides(guides) or a <Guides value={guides} /> child. Top-level guides win over scale-local guide entries. Two guide children on one channel emit DUPLICATE_MERGE_KEY; the later child wins.

Grid lines

Major/minor positions come from scale breaks; whether and how grid lines paint is theme: grid color, gridWidth, gridDasharray, and boolean gridX / gridY. Open the chart themes surface for named bases and role overrides.