Gribouille 0.3.0: A Grammar of Graphics for Typst

mcanouil2 pts0 comments

Gribouille 0.3.0: Finer Guide Control and a Themed Compose – Mickaël CANOUIL

Skip to main content

Another week, another Gribouille release. Gribouille 0.3.0 is narrower in scope than 0.2, but it brings some wanted controls. The headline is guide control: a single argument now hides axis ticks and legends without touching the theme. Alongside that, compose() gains a theme: parameter, defer() replaces plot(..., defer: true), geom-area() stacks by default, and annotate() can let marks overflow the panel.

NoteAt a glance

Gribouille 0.3.0 on Typst Universe: #import "@preview/gribouille:0.3.0": *.

guides(x: none) / guides(y: none) hide tick marks and tick labels; the axis line, grid, and title stay. Remove the title separately with labs(x: none).

guides(default: none) hides every legend without its own override.

Under coord-radial, guides(theta: none) hides the full angular axis and guides(r: none) hides radial tick labels.

guides(none) replaces the removed guide-none(); guides(auto) restores the default.

compose() gains theme:, which styles the composition chrome and propagates into panels with no theme of their own.

Breaking change : plot(..., defer: true) is replaced by defer(plot, ...). Panels inside a compose() also no longer accept their own width/height.

geom-area() defaults to stat: "align" and position: "stack"; groups with mismatched x values are resampled automatically.

annotate() gains clip: (default true); clip: false lets a mark overflow the panel.

Every figure in this post is a real, freshly compiled plot.

1 Guide controls

The biggest visible change is a new layer of control over what guides draw.

Before 0.3.0, hiding an axis’s tick marks and labels meant reaching into theme() for the right element surface. Now, guides(x: none) does it directly. The axis line, the vertical grid lines, and the axis title all stay. To drop the title too, add labs(x: none) alongside it.

#plot(<br>data: penguins,<br>mapping: aes(x: "flipper-len", y: "body-mass", colour: "species"),<br>layers: (geom-point(size: 2pt, alpha: 0.7),),<br>1 guides: guides(x: none),<br>labs: labs(<br>title: "Ticks Off, Grid Stays",<br>x: "Flipper Length (mm)",<br>y: "Body Mass (g)",<br>),<br>theme: theme-minimal(),<br>width: 12cm,<br>height: 8cm,

guides(x: none) removes tick marks and labels. The line, grid, and title are untouched. guides(y: none) does the same for the y-axis.

The same syntax now controls legends too. guides(none) hides a legend; guides(auto) restores the default. Both replace the removed guide-none().

When you want all legends gone at once, guides(default: none) sets the fallback for every aesthetic without its own override.

#plot(<br>data: penguins,<br>mapping: aes(x: "flipper-len", y: "body-mass", colour: "species"),<br>layers: (geom-point(size: 2pt, alpha: 0.7),),<br>1 guides: guides(default: none),<br>labs: labs(<br>title: "No Legends",<br>x: "Flipper Length (mm)",<br>y: "Body Mass (g)",<br>),<br>theme: theme-minimal(),<br>width: 12cm,<br>height: 8cm,

Every aesthetic without an explicit guide inherits none; the colour legend disappears and the plot area fills the freed space.

2 Radial guide controls

The same guide syntax extends to coord-radial. guides(theta: none) hides the full angular axis, the arc, minor ticks, and tick labels together. guides(r: none) hides only the radial tick labels, leaving the spokes and circles in place.

#plot(<br>data: penguins,<br>mapping: aes(x: "species", fill: "species"),<br>layers: (geom-bar(),),<br>coord: coord-radial(),<br>1 guides: guides(theta: none, default: none),<br>labs: labs(<br>title: "Angular Axis Hidden",<br>x: none,<br>y: "Count",<br>),<br>theme: theme-minimal(),<br>width: 10cm,<br>height: 10cm,

theta: none removes the angular ring and labels. default: none also drops the fill legend, leaving the radial grid as the only scale reference.

3 Compose gets a theme

Two changes landed in compose() together.

The first is a theme: parameter. Pass a theme and it styles the composition chrome: the shared title, the hoisted legend, and the panel tags. It also propagates into any panel that has no theme of its own, so you can set one theme once and let it cascade instead of repeating it across every panel.

The second is the defer() helper.

WarningBreaking change

plot(..., defer: true) is removed. Replace plot(data: ..., ..., defer: true) with defer(plot, data: ..., ...). Panels inside a compose() also no longer accept their own width/height; the composition sizes each cell.

1#let panel(y, title) = defer(plot,<br>data: penguins,<br>mapping: aes(x: "flipper-len", y: y, colour: "species"),<br>layers: (geom-point(size: 2pt, alpha: 0.85),),<br>labs: labs(title: title, x: none, y: none),

#compose(<br>panel("body-mass", "Body Mass"),<br>panel("bill-len", "Bill Length"),<br>columns: 2,<br>tag-levels: "1",<br>tag-prefix: "(",<br>tag-suffix: ")",<br>guides: guides(default: guide-legend(position: "bottom")),<br>labs: labs(title: "One Theme, Two Panels"),<br>2 theme: theme-minimal(),<br>width: 18cm,<br>height: 8cm,

defer(plot, ...) replaces plot(..., defer: true). The panel no longer sets width/height.

theme:...

none guides theme plot title labs

Related Articles