Gribouille 0.3.0: A Grammar of Graphics for Typst
Gribouille 0.3.0: Enhancing Guide Control and Themed Compositions
Author: Mickaël CANOUIL, Ph.D.
Published: Monday, June 15, 2026
Tags: typst quarto grammar-of-graphics gribouille
Summary: Gribouille 0.3.0 provides a more precise "on/off" switch for axes and guides, introduces theme propagation within
compose(), and updatesgeom-area()to utilize stacking by default.
While the scope of version 0.3.0 is more focused than the previous 0.2 release, it delivers several highly requested control mechanisms.
🚀 At a Glance: What's New?
To get started with the latest version, use the following import:
#import "@preview/gribouille:0.3.0": *
- Guide Control: Hide ticks/labels without altering the global theme.
- Themed Compositions:
compose()now accepts athemeparameter. - API Update:
defer()replaces the oldplot(..., defer: true)syntax. - Area Defaults:
geom-area()now stacks by default. - Annotation Flexibility:
annotate()now supportsclip: false.
1. Refined Guide Controls
The most significant update is the introduction of a dedicated layer for managing guide visibility. Previously, removing axis tick marks or labels required navigating deep into the . Now, this is handled via a streamlined argument.theme() element surfaces
Axis and Legend Visibility
Using guides(x: none) or guides(y: none) will strip away the tick marks and their associated labels, while preserving the axis line, the grid, and the title.
Example Implementation:
# plot (
data : penguins,
mapping : aes ( x : "flipper-len", y : "body-mass", colour : "species" ),
layers : ( geom-point ( size : 2pt, alpha : 0.7 ),),
guides : guides ( x : none ),
labs : labs ( title : "Ticks Off, Grid Stays", x : "Flipper Length (mm)", y : "Body Mass (g)" ),
theme : theme-minimal (),
width : 12cm, height : 8cm,
)
In the above code, guides(x: none) specifically targets the x-axis ticks.
Global and Default Settings
guides(none): Replaces the deprecatedguide-none()function to hide a legend.guides(auto): Reverts the guide to its default state.guides(default: none): Acts as a catch-all, hiding every legend that hasn't been explicitly overridden.
2. Radial Guide Controls
The new guide syntax is fully compatible with coord-radial. The control is split between the angular and radial dimensions:
| Command | Effect |
|---|---|
guides(theta: none) | Hides the entire angular axis (arc, minor ticks, and labels). |
guides(r: none) | Hides only the radial tick labels (spokes and circles remain). |
Example: Using guides(theta: none, default: none) in a radial plot removes both the outer angular ring and the fill legend, leaving only the radial grid for reference.
3. Enhancements to compose()
The compose() function has received two major updates to improve workflow and styling.
Theme Propagation
You can now pass a theme directly to compose(). This serves two purposes:
- It styles the composition chrome (shared titles, hoisted legends, and panel tags).
- It cascades into any nested panels that do not have their own specific theme defined.
Breaking Changes & API Shifts
There are a few structural changes to be aware of:
- Deferring Plots: The syntax
plot(..., defer: true)is now deprecated.- Old:
plot(data: ..., defer: true)New:defer(plot, data: ...)
- Old:
- Sizing: Panels nested within a
compose()block no longer accept individualwidthorheightarguments; the composition now manages cell sizing automatically.
Code Example:
#let panel ( y , title ) = defer (
plot , data : penguins , mapping : aes ( x : "flipper-len" , y : y , colour : "species" ),
layers : ( geom-point ( size : 2pt , alpha : 0.85 ),),
labs : labs ( title : title , x : none , y : none ),
)
# compose (
panel ( "body-mass" , "Body Mass" ),
panel ( "bill-len" , "Bill Length" ),
columns : 2 ,
tag-levels : "1" ,
tag-prefix : "(" ,
tag-suffix : ")" ,
guides : guides ( default : guide-legend ( position : "bottom" )),
labs : labs ( title : "One Theme, Two Panels" ),
theme : theme-minimal (),
width : 18cm , height : 8cm ,
)
4. Area Chart Defaults
geom-area() has been updated to be more intuitive for multi-group data. It now defaults to:
stat: "align"position: "stack"
Previously, these had to be manually specified to achieve a stacked area chart.
Automatic Resampling
The stat: "align" setting is particularly powerful because it handles groups with mismatched values. It performs a resampling process:
This ensures that different groups can be stacked even if their original coordinates do not align perfectly.
5. Annotation Clipping
Finally, annotate() now includes a clip parameter (which defaults to true). By setting clip: false, you can allow marks to extend beyond the boundaries of the panel, providing more freedom for custom labeling and callouts.