← Back to news

Gribouille 0.3.0: A Grammar of Graphics for Typst

mickael.canouil.fr|179 points|64 comments|by mcanouil|Jun 15, 2026

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 updates geom-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 a theme parameter.
  • API Update: defer() replaces the old plot(..., defer: true) syntax.
  • Area Defaults: geom-area() now stacks by default.
  • Annotation Flexibility: annotate() now supports clip: 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 theme() element surfaces. Now, this is handled via a streamlined argument.

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 deprecated guide-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:

CommandEffect
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:

  1. It styles the composition chrome (shared titles, hoisted legends, and panel tags).
  2. 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:

  1. Deferring Plots: The syntax plot(..., defer: true) is now deprecated.
    • Old: plot(data: ..., defer: true) \rightarrow New: defer(plot, data: ...)
  2. Sizing: Panels nested within a compose() block no longer accept individual width or height arguments; 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 xx values. It performs a resampling process: Groupn(x)Shared Grid(x)\text{Group}_n(x) \approx \text{Shared Grid}(x) This ensures that different groups can be stacked even if their original xx coordinates do not align perfectly.

Area Chart Placeholder


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.