Changelog
Version history.
Unreleased
- fix: numeric values on a discrete scale (a polygon vertex set between level centres, a jittered point) are kept as fractional level positions instead of being dropped when the scale carries explicit
limits. (#151GitHub) - docs: a Benchmarks guide measures how compile time and output size grow with element count, drawn from a committed dataset with Gribouille itself, and shows where per-row geoms become impractical for large data. (#149GitHub)
0
0.4
0.4.1 (2026-06-23)
- fix:
position: "dodge"now shifts point-based geoms (text, label, point, linerange, etc.) on continuous x-axes by inferring the slot width from the minimum gap between unique positions. (#145GitHub) - fix: string values such as
"0"are no longer inferred as numeric for scale type; only Typstint/floatvalues produce a continuous scale. CSV users relying on string-numeric x-columns being treated as continuous must callas-numeric(data, "col")first. (#145GitHub) - docs: the News page links the Gribouille 0.4 release announcement and shows a featured image for each release. (#141GitHub)
0.4.0 (2026-06-22)
Breaking changes
- feat!:
coord-cartesian()andcoord-radial()takeclipas a boolean (true/false) instead of the strings"on"/"off". (#134GitHub) - feat!:
labs()is renamed tolabels(), and theplot()/compose()labs:argument tolabels:; there is nolabsalias. (#131GitHub) - feat!:
coord-cartesian(),stat-function(), andgeom-function()rename thexlim/ylimarguments tox-limits/y-limits. (#131GitHub) - feat!: the
col-mix()colour helper is renamed tocolour-mix(), with argumentscolour1/colour2. (#131GitHub) - feat!:
geom-text,geom-label, andgeom-typstdrop thedx/dyparameters; offsets now use thenudge-x/nudge-yaesthetics, where a number shifts in data units and a Typst length shifts in canvas units. (#131GitHub)
Changes
- feat: continuous scale
limitsandgeom-ablineintercepts accept ISO-8601 date/datetime/time strings under a temporal scale, completing the temporal-string contract. (#137GitHub) - feat:
geom-vline/geom-hlineintercepts and continuous scalebreaksaccept ISO-8601 date/datetime/time strings under a temporal scale, matching how geom data is already parsed. (#136GitHub) - feat:
geom-area()accepts adirectionparameter ("hv"or"vh") that steps the filled top edge likegeom-step();none(default) keeps the smooth area. (#135GitHub) - feat:
element-text()/element-typst()angleis now honoured on axis titles, strip text, and legend title and entry labels (previously only tick labels and the plot title, subtitle, and caption); axis titles default to 0deg (x) / 90deg (y) and reserve the correct space at any angle. (#134GitHub) - feat:
geom-text(),geom-label(), andgeom-typst()accept anangleparameter (a Typst angle, default0deg) rotating each label. (#134GitHub) - feat: every aesthetic key can be pinned as a constant directly on any geom, e.g.,
geom-label(nudge-x: 0.5), not only throughaes(); declared parameters still bind first and unknown or positional arguments are rejected. (#133GitHub) - feat: scale
expandacceptsautoon one side, e.g.,expand: (0%, auto), keeping the per-scale default for that side. (#132GitHub) - feat:
geom-vline,geom-hline, andgeom-ablineread their intercept channels fromaes(); bindingxintercept/yintercept/slope/intercepttogether withdatadraws one line per row with per-rowcolour/alpha/linewidth/linetype, and a mappedxintercept/yinterceptextends the panel to keep the lines in view; the scalar/array parameter still draws shared lines when nothing is mapped. (#129GitHub) - feat: a font set in
theme(text: ...)now reaches literal-glyph point markers (e.g.,shape: sym.star) for both plot markers and legend keys, instead of falling back to the document font. (#126GitHub) - feat:
geom-text,geom-label, andgeom-typstaccept afont:parameter;autouses the themetextfont, then the document font. (#126GitHub) - feat: panel gridlines split into a ggplot2-style cascade,
panel-grid->panel-grid-major/panel-grid-minor->-x/-y, so X/Y and major/minor lines are styled independently; minor defaults to half the major weight in the same colour and a blankpanel-gridblanks both weights. (#125GitHub) - feat: continuous axes draw minor gridlines (visible by default): midpoints between majors for linear/sqrt/reverse and sub-decade lines for log10;
scale-*-continuous(and log10/sqrt/reverse) acceptminor-breaksandn-minorto position them. (#125GitHub) - feat: the
legend-positiontheme entry sets a global side for every legend (theme(legend-position: "bottom"), also viatheme-sub-legend(position:)), accepting the same values asguide-legend(position:); any explicitguides()placement still wins. (#123GitHub) - feat: discrete (swatch) legend key glyphs are resizable via
guide-legend(key-size: <length>)per legend or thelegend-keytheme entry for every swatch legend; the row spacing and label offset grow with the glyph so enlarged keys do not overlap. (#122GitHub) - feat: the
shapeaesthetic accepts any character as the marker symbol; a value outside the eight built-in keywords renders as a literal glyph, so letters or emoji work as markers acrossscale-shape,scale-shape-manual,scale-shape-identity,scale-shape-binned, thegeom-point(shape: ...)pin, and legend keys. (#120GitHub) - feat: scale
limitsacceptautoon one side, e.g.,limits: (auto, 60), keeping the trained bound for the other side. (#116GitHub) - feat: binned position scales (
scale-x-binned/scale-y-binned) acceptbreaksas bin edges; ticks sit at interval midpoints andn-breaksis ignored whenbreaksis set. (#116GitHub) - feat: binned colour, fill, shape, linetype, size, linewidth, stroke, and alpha scales accept
breaksas bin edges; colour, fill, shape, and linetype bin per row by the edges, the others bin their legend. (#116GitHub) - feat: bundled datasets (
penguins,economics,mpg) ship as row-store arrays, sopenguins.filter(...)and.map(...)work directly;plot()still accepts them. (#116GitHub) - fix: scalar and Typst-length
nudge-x/nudge-yvalues now apply togeom-text/geom-label/geom-typst(previously a silent no-op). (#131GitHub) - fix: setting the base
line/rectstroke intheme()now cascades to every line and rect surface (panel grid, axis line, ticks, legend ticks, legend bar);element-line/element-rectstrokeaccepts a ratio (e.g.,80%) to scale the parent surface thickness, while an absolute length still pins a surface outright. (#124GitHub) - fix: setting the base
textsize intheme()now cascades to every text surface (axis titles, tick labels, legend, strip, plot title);element-text/element-typstsizeaccepts a ratio (e.g.,80%) to scale the parent surface size, while an absolute length still pins a surface outright. (#121GitHub) - fix:
position: "dodge"now shiftsgeom-text/geom-label/geom-typst,geom-point,geom-line/geom-path/geom-step,geom-pointrange, andgeom-linerangemarks side by side, matching the dodged bars instead of staying on the category centre. (#119GitHub) - fix:
theme-grey()matches ggplot2theme_grey()with white grid lines and no axis lines. (#116GitHub) - fix: explicit continuous
breaksexpand the axis range so requested ticks stay visible, unless a side is pinned by an explicitlimit. (#116GitHub) - docs: a News page lists the release announcement posts, and each changelog version links to its announcement. (#139GitHub)
0.3
0.3.0 (2026-06-14)
Breaking changes
- feat!:
compose()panels are now built with the newdefer()helper (defer(plot, ...), ordefer(compose, ...)to nest), replacingplot(..., defer: true); panels omit their ownwidth/heightand the composition sizes each cell. (#81GitHub)
Changes
- feat: the published package now ships Tinymist-friendly docstrings; hovering a gribouille function in an editor shows formatted parameters, returns, and examples instead of the raw
@-tag comments. Variadic sinks list their accepted keys:guides()its aesthetics, andtheme()and the theme presets their element surfaces. (#108GitHub) - feat: under
coord-radial,guides(theta: none)hides the angular axis (arc, minor ticks, and tick labels) andguides(r: none)hides the radial tick labels; the spokes and circles stay. Also fixesguides(theta: none)previously adding a theta arc instead of hiding the axis. (#106GitHub) - feat:
guides(x: none)/guides(y: none)hide that axis’s tick marks and tick labels (and any log minor ticks) and reclaim the freed space; the axis line, grid, and title stay (remove the title withlabs(x: none)). (#105GitHub) - feat:
guides()acceptsnoneto hide a guide andautofor the default;guides(default: none)hides every legend without its own override, and any other non-guide value fails with a clear message. Replaces the removedguide-none()(passnoneinstead). (#104GitHub) - feat:
annotate()gains aclipargument (defaulttrue); setclip: falseto let an annotation overflow the panel, e.g., a corner inset or a mark placed past the axis limits. (#93GitHub) - feat:
compose()acceptstheme:; an explicit theme styles the composition chrome (title, hoisted legend, panel tags) and propagates into panels with no theme of their own, otherwise a theme shared by every panel is used. (#82GitHub) - feat:
geom-area()defaults tostat: "align"andposition: "stack"; groups with mismatched x values are automatically resampled onto a shared grid and stacked without requiring explicitstat: stat-align(). (#77GitHub) - fix:
stat-bin-2dandstat-bin-hex_densityis now the cell’s fraction of the total count (count / sum(count)), matching ggplot2, instead of an undocumented count-per-cell-area value. (#109GitHub) - fix: data outside a
sqrtorlog10transform’s domain (negative, or zero/negative forlog10) now panics with a clear scale message instead of a raw Typst error, and the sqrt inverse clamps padded view bounds at zero so sqrt axes stay monotone and show the0break. (#109GitHub) - fix: a horizontal legend (
position: "top"/"bottom") withguide-legend(align: center)/align: rightnow centres or right-justifies its key graphic (colourbar bar, key row, or size band) under the title, instead of leaving the graphic pinned at the left edge while the title moved; a centred colourbar also keeps its end labels inside the legend block. (#103GitHub) - fix: the theme
legend-backgroundnow inherits the baserectelement like every other*-backgroundsurface, sotheme(rect: ...)cascades to it instead of being ignored. (#101GitHub) - fix:
guide-legend(nrow:)/guide-legend(ncolumn:)now lay a continuous size legend (scale-size-*) out in a grid, like the discrete swatch legend, instead of being ignored; a continuous colourbar stays a single bar and ignores them. (#99GitHub) - fix:
guide-legend(align:)now also aligns the legend title (not just the entry labels), and a string such asalign: "left"fails with a clear message instead of a vague panic or being silently ignored;alignis a Typst alignment (left,center,right). (#98GitHub) - fix:
annotate(clip: false)placed outside the scalelimitsnow draws instead of being dropped by the out-of-range pre-pass, so a corner inset or a mark parked past the axis range is kept. (#97GitHub) - fix: a left/right legend that would overrun the caption, or a hoisted
compose()legend that leaves no room for the panels, now fails with a clear layout hint instead of silently overprinting. (#96GitHub) - fix: continuous
scale-size-*legends reserve row height and stride for the resolved key glyph, so a wide sizerangeno longer overlaps the keys and labels. (#95GitHub) - fix: the out-of-range filter respects scale
expand, keeping points and annotations that sit inside the expansion headroom instead of dropping them; reversedlimits(a flipped axis) no longer drop every row. (#92GitHub) - fix:
geom-linerange()honours itsalphaparameter; the line was previously always drawn fully opaque. (#85GitHub) - fix:
geom-area(position: "stack")now stacks bands correctly; each polygon’s lower edge sits at the cumulated top of the group below rather than always closing aty = 0. (#77GitHub) - fix:
stat-align()expands its shared grid by a small offset on either side of every breakpoint, so a group that starts or ends mid-range steps cleanly down to the baseline instead of leaving a wedge below the neighbouring group. (#77GitHub) - docs: the theming guide notes relative (
%) versus absolute text sizing, andelement-textgains an example contrasting the two. (#121GitHub) - docs: the
guides()reference lists each accepted key (colour,fill,…) as a sub-list under the..argsparameter, sharing one description template. (#108GitHub) - docs: reference pages for forwarding functions such as the
scale-*colour wrappers now list their real parameters instead of an opaque..argsrow, and a mixed signature likeannotate(geom, ..fields)also listsclip. (#102GitHub) - docs: the
theme()reference table now lists every theme key, addingplot-tag,legend-ticks,legend-background,legend-bar, andgeom. (#100GitHub)
0.2
0.2.1 (2026-06-03)
- feat:
compose()gainsalign-panels(defaultfalse); whentrue, panels share margins grid-wise (left/right per column, top/bottom per row) so their plot areas line up across rows and columns, likepatchwork/cowplotpanel alignment. (#71GitHub) - fix:
compose()panel tags (tag-levels) reserve their own band so they no longer overlap the panel content. (#70GitHub) - fix:
geom-segment/geom-curve/geom-ribbon/geom-arearender on discrete scales instead of silently drawing nothing. (#69GitHub)
0.2.0 (2026-06-01)
- feat: a layer’s
dataaccepts a function applied to the plot data, returning that layer’s frame (e.g.,geom-point(data: rows => rows.filter(...))), for subsetting or per-layer transforms without a separate dataset. (#62GitHub) - feat:
facet-grid(scales:)supports free scales ("free_x"frees x per column,"free_y"frees y per row,"free"both); non-positional scales stay shared and panels keep equal size. (#60GitHub) - feat: legend entry labels honour the
legend-texttextalign, andguide-legend()gains analignargument; horizontal legends default to centred labels, vertical to left. (#34GitHub) - feat:
compose()acceptsdefer: trueto return a spec usable as a panel of anothercompose, enabling nested compositions;tag-levelsaccepts a per-depth array (withtag-sep) so nested panels continue the numbering (e.g.,B.1,B.2). (#24GitHub) - feat:
compose()can number panels with a tag pattern (tag-levels"A"/"a"/"1"/"I"/"i", plustag-prefix/tag-suffix/tag-corner), styled by the newplot-tagtheme element. (#23GitHub) - feat:
compose()accepts composition-levellabs(title/subtitle/caption) andalt, and now controls the collected legend’s side throughguides(e.g.,guides(default: guide-legend(position: "bottom"))); theguides-placementparameter is removed. (#22GitHub) - feat:
guides()accepts adefaultentry that sets fallback guide options (such as the legend side) inherited by every aesthetic without its own override, in bothplot()andcompose();guide-legend’spositionnow defaults toautoand inherits from it. (#21GitHub) - feat:
compose()gainswidth/height(filling a bounded container by default) and relativewidths/heightsto set panel proportions relative to one another. (#20GitHub) - feat:
element-text()/element-typst()gain analignparameter setting per-surface text alignment, independent of the container; title and subtitle default left, caption right, axis titles and strip text centred. (#13GitHub) - feat:
labs()fields default toauto; passnoneto suppress an axis or legend title and reclaim the space it reserved. (#12GitHub) - feat:
element-blank()on a text surface (axis, plot, or legend title) collapses the space the text would reserve. (#12GitHub) - feat:
width/heightacceptautoto fill the available space of a bounded container. (#10GitHub) - fix: a standalone plot no longer reserves a fixed empty margin on its top and right edges, letting the panel fill that space. (c9d53acGitHub)
- fix: a plot with no x-axis title reclaims the empty space the title would have reserved below the panel, matching the y-axis side. (#61GitHub)
- fix:
element-text(angle:)/element-typst(angle:)rotate axis tick labels (seeding theguide-axis(angle:)default) and the plot title, subtitle, and caption, instead of being ignored. (#59GitHub) - fix:
labs(tag:)draws the figure tag above the title on a standalone plot, styled by theplot-tagtheme element, instead of being ignored. (#58GitHub) - fix:
labs(alt:)fills in the figure’s accessibility alt text whenplot(alt:)is unset, instead of being stored and ignored. (#57GitHub) - fix:
geom-qq()/geom-qq-line()honour thedistributionargument (uniform/exponential) instead of always plotting against the normal reference. (#56GitHub) - fix: the
fontset onelement-text/element-typst/element-geomis applied to every text surface and to the text-drawing geoms, inheriting the basetextfont when unset. (#54GitHub) - fix: a
stage/after-scalechannel now trains its scale on the marker’s source column, so the closure receives the channel’s scale-resolved value as documented. (#52GitHub) - fix: grouped geoms (e.g.,
geom-smooth) no longer panic when a grouping aesthetic is mapped viaafter-scaleorstage. (#51GitHub) - fix: facet-grid legends reserve space for a secondary x-axis so a top legend no longer overlaps its ticks. (#46GitHub)
- fix:
geom-errorbar()/geom-errorbarh()/geom-rug()resolve anafter-scale/stagecolour mapping instead of panicking. (#45GitHub) - fix: continuous legends fall back to computed breaks when every user-supplied break falls outside the domain. (#44GitHub)
- fix:
coord-cartesian(xlim:/ylim:)zooms continuous axes instead of being ignored. (#43GitHub) - fix:
coord-flip(reverse: true)preserves alog10/sqrtaxis transform instead of overwriting it. (#42GitHub) - fix:
geom-col()on a continuous x with a single distinct value no longer panics when inferring the bar width. (#41GitHub) - fix:
log10/sqrtscales validate userlimitsand report a clear error for non-positive bounds. (#40GitHub) - fix:
geom-smooth()honours thelevelargument when sizing the confidence band instead of always using 95%. (#39GitHub) - fix: binning geoms reject a non-positive
binswith a clear error instead of dividing by zero. (#38GitHub) - fix: contour stats skip incomplete cells when the
(x, y, z)grid is sparse instead of panicking. (#37GitHub) - fix:
scale-*-manual()with an emptyvaluesarray reports a clear error instead of an opaque divide-by-zero. (#36GitHub) - fix: number formatters carry a fraction that rounds up to a whole unit (e.g.,
0.9999995no longer renders as0.1), andformat-scientifickeeps its mantissa in[1, 10). (#35GitHub) - fix: legend guides reserve space for multi-line labels, measuring the resolved custom
labels:for both width and line count across swatch, size-ladder, and colourbar guides, so two-line content no longer clips or overlaps. (#33GitHub) - fix: a column mapped to both a positional aesthetic (
x/y) and a grouping aesthetic (fill/colour/group/…), e.g.,aes(x: "class", fill: "class"), now resolves the grouping aesthetic across aggregating stats (boxplot,summary,count/sum, histograms) instead of drawing every mark in the ink colour with an empty guide. (#31GitHub) - fix: continuous scales honour an explicit
breaksargument for axis ticks and continuous legend guides instead of ignoring it; breaks outside the domain are dropped. (#30GitHub) - fix:
geom-ribbon()draws one band per discretefill/colour/groupinstead of merging every group into a single ribbon. (#29GitHub) - fix:
plot(width: auto, height: auto)is allowed on an unbounded page, falling back to the default10cmby7cminstead of panicking. (#27GitHub) - fix:
compose()panels fill their cells instead of being letterboxed; their ownwidth/heightare discarded once the composition has a size, and the composition size falls back to16cmby12cmwhen the container is unbounded. (#26GitHub) - fix: legend labels wider than 2 cm no longer overlap the next swatch; each legend column reserves the label’s full width, most visible in horizontal legends. (#25GitHub)
- fix: the
composecollected legend placed ontoporbottomno longer clips its first swatch and is centred under the panels. (#19GitHub) - fix:
width/heightnow bound the whole image, including title, subtitle, caption, and plot-background padding; the data panel shrinks to fit and long titles wrap. (b53fab2GitHub) - docs: callout headers now sit on the type tint as a distinct band while the body uses the plain surface, and caution gets its own deeper mustard so it no longer matches warning. (#16GitHub)
- docs: tabset (panel-tabset) labels now follow the light/dark theme; the active tab label uses the brand primary colour in both schemes. (#15GitHub)
- docs: the development version is now downloadable from the dev documentation site and installable as a local package; release, Typst Universe, and development archives share an identical payload. (#14GitHub)
0.1
0.1.1 (2026-05-22)
- fix: centre collected
composeside legends against the panel grid. (994c9e8GitHub) - fix: apply plot background inset/outset even without a fill. (2f24982GitHub)
- docs: enable llms.txt output for the documentation site. (6b05d6aGitHub)
- docs: add a navbar version switcher between the stable and development docs. (95c3d9bGitHub)
0.1.0 (2026-05-20)
- feat: initial version of Gribouille.
Looking for a specific change? Browse the full commit history or the list of releases on GitHub.