Changelog
Version history.
0
0.7
0.7.0 (2026-08-24)
Breaking changes
- feat!:
geom-text,geom-label, andgeom-typsttake anarrow()specification onarrowin place of a boolean, and theirarrow-lengthparameter is gone.arrow: truebecomesarrow: arrow(), andarrow-length: 6ptbecomesarrow: arrow(length: 6pt). (#249GitHub) - feat!:
guide-axis(angle:),guide-axis-logticks(angle:), and theangleof anaxis-texttheme element are bounded to -90 to 90 degrees and fail outside it. Past a quarter turn the tick labels read upside down and ran off the canvas. (#238GitHub) - fix!:
guide-axis-theta(angle:)is bounded to -90 to 90 degrees and fails outside it, as every other tick-label rotation already is. Past a quarter turn the labels read upside down. (#286GitHub) - fix!: the theta axis of a
coord-radial()plot reads its tick marks and its arc off the scale that carries the sweep,yon a pie in place ofx. The minor ticks ofguide-axis-theta(minor-ticks: true)move from theaxis-linesurface toaxis-ticks-minor, so a theme that styled the angular axis throughaxis-linealone must now setaxis-tickstoo. (#270GitHub) - fix!: a faceted plot whose strip label holds a word wider than its panel now fails with the room that word needs. Shorten the level names with a
labeller, break the word with\, or give the plot more room withwidth/height. (#262GitHub) - fix!: a plot whose tick labels cannot fit the canvas fails with the room they need instead of drawing past its edge. Give the plot more room, rotate the labels with
guides(x: guide-axis(angle: 45)), shorten them with alabels:function on the scale, or shrink them withtheme(axis-text: element-text(size: ...)). (#259GitHub) - fix!: a legend placed on a plot side, or one
compose()hoists out of its panels, fits thewidth/heightit was asked for, and fails with the room it needs when it cannot. Give the plot more room, move the legend to a shorter side, or shrink it withguide-legend(nrow:/ncolumn:). (#255GitHub)
Changes
- feat:
breaks-log(n:, base:)places the breaks of a log scale on powers of the base. When too few powers fall inside the data range, sub-decade steps fill in, the wayscales::breaks_log()fills them in. The base is independent of the scale transform, sobase: 2places powers of two. (#272GitHub) - feat:
format-log(base:, digits:)writes a tick label as a power with a real superscript, for example10^3. A break that is not an exact power keeps a mantissa, because an automatic log axis breaks on one, two, and five times a power. (#272GitHub) - feat:
guide-axis-logticks()draws two tick tiers below the labelled decades. The tick at five times a power moves to the newaxis-ticks-midtheme surface and is longer than the other sub-decade ticks. Setaxis-ticks-mid: (length: 50%)for the previous look. (#272GitHub) - feat: a
coord-radial()plot draws major tick marks on its angular axis, from theaxis-tickstheme surface, as a cartesian axis does. The circle gives up the radius they need, so the figure still fits thewidth/heightit was asked for. (#270GitHub) - feat: a plot draws at any size that leaves it room to draw, so a figure can be small enough to sit in a table cell or a line of prose. Only an empty or inverted canvas fails now. (#252GitHub)
- feat:
theme-brand()builds a theme from a parsed_brand.yml, so a document’s plots follow the same brand as its prose. brand.yml is a tool-independent standard, read by Quarto and by Shiny for R and Python, not a Quarto feature. It takes the dictionaryyaml()produces rather than a path, mapsforeground,background, andprimaryontoink,paper, andaccent, and turns the remaining data-ink roles into a discrete palette, withmode: "light"ormode: "dark"choosing the variant. (#250GitHub) - feat: a theme carries a
paletteof colours that discrete colour and fill scales fall back to, so a whole document can be recoloured without repeatingscale-colour-manual()on every plot. A scale’s ownpalette:still wins, continuous scales keep viridis, andautouses the Okabe-Ito palette as before. (#250GitHub) - feat: the line geoms draw arrowheads.
geom-segment,geom-curve,geom-spoke,geom-path,geom-line, andgeom-steptake anarrowspecification built with the newarrow()helper, which sets the head length, its half-opening angle, which end carries it, and whether it is an open V or a filled triangle. (#249GitHub) - fix: the band a horizontal colour bar reserves below its strip is the lead the renderer draws plus the row its labels are measured to occupy. It was one fixed 0.45 cm covering both, which is about 0.03 cm more than the default theme draws. (#301GitHub)
- fix: a vertical colour bar reserves the room its turned break labels need. A
theme(legend-text: element-text(angle: ...))turned each label into a box the flank never measured, so the labels drew past the width the legend was given. (#300GitHub) - fix: a discrete scale censors a level whose name looks like a number. A scale limited to
("10", "20")withoob: "drop"used to keep a"90"row and place it at position 90, far outside the panel. (#297GitHub) - fix: a vertical colour bar reserves the gap it draws between its strip and its tick labels. It reserved 0.3 cm and drew 0.18 cm, so a plot whose bar labels set the legend width gains up to 0.12 cm of panel back. (#296GitHub)
- fix: a discrete scale with no levels draws no legend. It used to reserve a box beside the panel that held its title and no keys, which took width from the plot. A scale has no levels when
limits: ()pins it empty, or when the column it reads holds nothing but empty values. (#292GitHub) - fix: a discrete scale says what is wrong with numeric
limits, such asscale-discrete(limits: (1, 2, 3)). It used to fail with a raw Typst error saying a string was expected. A discrete scale reads a bare number as a position rather than as a level, so the levels must be quoted. (#291GitHub) - fix: a radial panel gives up radius only for the tick marks it draws. An angular axis with no breaks used to shrink the circle by the themed tick length all the same. (#286GitHub)
- fix: each label row of a
guide-axis-stack()clears the row above it. A row started a fixed step out, which crowded a row under turned labels and left a gap under short ones. (#285GitHub) - fix: an axis reserves the tick weights it draws. A theme that lengthens
axis-ticks-midno longer takes that room on an axis with no sub-decade ticks, which gives the panel the difference back. (#285GitHub) - fix: a legend that does not fit names what the guide at fault can change. A colour bar and a
guide-custom()block were told to useguide-legend(nrow:/ncolumn:), which neither one takes. (#285GitHub) - fix: a
guide-custom()block sits on the side aguides(default: ...)entry or atheme(legend-position:)sets, as every other guide does. It stayed on the right whatever those asked for, andposition: autofailed with a raw error instead of inheriting a side. A theme or adefault:entry that hides its legends now hides a custom block with them; give the block its ownpositionto keep it. (#278GitHub) - fix: an
orderset on aguides(default: ...)entry reaches the guides that inherit from it. A placement built from a side alone carries no order, and spreading it over the entry dropped the one the entry set. (#278GitHub) - fix: a log axis draws one minor gridline between adjacent decades. It drew a line at every sub-decade position, which banded the panel grey.
n-minorsets that count on a log axis, as it does on every other continuous axis, andn-minor: 0removes the lines. The sub-decade positions stay on the tick marks ofguide-axis-logticks(). (#272GitHub) - fix: an axis reserves the depth of its longest tick tier. A theme that made a sub-decade tick longer than the major tick used to draw it past the axis band. (#272GitHub)
- fix: the log tick tiers of
guide-axis-logticks()read the visible domain. A log scale that carries no view expansion used to place its sub-decade ticks against the transformed domain, which put them outside the panel. (#272GitHub) - fix: every panel of a faceted
coord-radial()plot keeps its own angular and radial tick labels. A radial panel rings them inside its own circle rather than on an edge it shares with a neighbour, so an interior panel used to be left with no scale to read against, and acoord-radial(theta: "y")pie lost the wrong set. (#271GitHub) - fix: a discrete axis draws the gridlines a theme asks for. It still draws none from
panel-gridalone, because its ticks already mark every level, and now draws them when the theme setspanel-grid-major,panel-grid-major-x, orpanel-grid-major-y. The grid circles of acoord-radial()plot follow the same rule, but readpanel-grid-majoronly, since a radial panel draws one grid weight for both its circles and its spokes. (#268GitHub) - fix: a geom hides the seam between its marks only where they touch, so the whitespace it was asked for survives. A
geom-tilegrid below its full slot, a bar that neither stacks nor fills, and an unstackedgeom-ribbonnow paint at exactly the size they were given, where each used to spread half the seam width past it. A waffle chart gains back most of its grid gap. Stacked bars and areas, tiles at their full slot, hexes, and iso-band cells keep their seams sealed. (#266GitHub) - fix: dodged marks keep a gap between them, so a bar no longer paints over the one to its left.
position-dodge(padding:)sets that gap and now applies when every mark shares a width, where it was accepted and then ignored. Bars, boxes, violins, crossbars, and error bars all narrow by the padding, and their centres do not move. (#265GitHub) - fix:
compose()builds the legend it hoists out of its panels under the composition theme. Its key size, its side, and its text all follow the composition, and a panel theme now styles that panel alone. (#260GitHub, #261GitHub) - fix: a plot fits the
width/heightit was asked for when its outermost tick label reaches past the panel edge. The panel shrinks by the reach, most visibly underexpand: false, where a break sits flush on the panel edge. (#258GitHub) - fix: a faceted plot fits the
width/heightit was asked for. Strip bands are budgeted against the panel grid, a label too wide for the panel it names wraps into it, and labels that cannot fit at all fail with the room they need. (#256GitHub) - fix: a stripped axis reserves no room outside the panel, so a
theme-void()figure gives its panel the whole canvas. Acoord-radial()panel still reserves the gap, since its theta labels ring the inside of the panel edge. (#252GitHub) - fix: a
coord-radial()plot reserves the room its theta tick labels need per angle instead of insetting all four sides of the circle by the widest one, so radial plots draw larger in the same canvas. (#248GitHub) - fix: a legend reserves the box its title and entry labels are drawn in, measured on their resolved surfaces rather than estimated from a character count. Measured labels are tighter than the old estimate, so legends give a little width back to the panel. (#247GitHub)
- fix: a legend reserves the width its title needs, measured at the
legend-titlesize rather than thelegend-textsize the entry labels use. Aguide-customblock now reserves room for its own title too. (#245GitHub) - fix: a legend reserves the title band it draws, resolved from the
legend-titlesurface instead of estimated fromlegend-text, so a scaledlegend-titleno longer crops the last key and alegend-titlemarginoverride is honoured. (#244GitHub) - fix: a legend placed on a plot side fits the
width/heightit was asked for. The painted backdrop, rather than the guide stack, sits alegend-gapoff the panel, and a left or bottom legend honours itsoutsetas canvas-edge whitespace. (#243GitHub) - fix: the shared legend
compose()hoists out of its panels shows itslegend-backgroundwhole, border, stroke, andoutsetincluded, instead of having them clipped away. (#242GitHub) - fix: a
coord-radial()plot whose sweep wraps fits thewidth/heightit was asked for, reserving the width of the merged first-and-last label such asHour-24/Hour-0. Alabelscallback returningnonefor a break no longer reserves a band for a label it hides. (#241GitHub) - fix: a faceted plot places its shared axis titles at the band the chrome reserved, so a title cannot land outside its own margin and stretch the figure past the requested
width/height. (#241GitHub) - fix: a faceted plot draws its secondary axis ticks and labels where they can be read, reserving the axis depth between the panel and its strip band. This covers the secondary x under
facet-gridandfacet-wrap, and the secondary y against afacet-gridrow strip. (#239GitHub) - fix: a
coord-radial()plot fits thewidth/heightit was asked for, the circle shrinking by the band its theta tick labels need.guides(theta: none)and a blankaxis-textgive that room back. (#237GitHub) - fix: a
coord-radial()plot whose scale carries asecondary:spec keeps the panel area the secondary axis used to be given. A radial panel draws no secondary axis, so nothing is reserved for one. (#236GitHub) - fix: a faceted plot names its secondary axes once for the whole panel grid, the way it already does for the primary axes, and wraps those titles to the room the plot leaves them. (#235GitHub)
- fix: the axis titles a faceted plot draws once for the whole grid follow the themed
axis-titlealign, pinning to the ends of the panel grid rather than staying centred over it. (#235GitHub) - fix: an axis title longer than the panel it labels wraps onto further lines instead of stretching the canvas past the requested
width/height. A title that still cannot fit fails with the room it needs. (#234GitHub) - fix: an inside-panel legend background keeps its painted
insetinside the panel at an edge-flush alignment, andlegend-background’soutsetnow spaces the backdrop off the panel edge instead of being silently ignored. (#232GitHub) - perf: a faceted plot resolves each limited scale once for the whole render. A plot with twenty panels used to resolve it twenty-one times, because the out-of-range pre-pass rebuilt its plans on every panel. (#298GitHub)
- perf: a binned plot no longer collects the values of each group for a bin grid the panel has already computed. (#291GitHub)
- perf: a plot whose discrete scale carries user
limitsdrops its out-of-range rows in time that no longer grows with the number of levels. At two thousand levels the pre-pass is about three times faster. (#291GitHub) - perf: a plot that groups its rows builds those groups in linear time, where the cost used to grow with the square of the row count. A boxplot of thirty thousand rows draws about seven times faster. (#289GitHub)
- perf: a plot with many rows draws in near-linear time, where the cost used to grow with the square of the row count. At ten thousand points the draw is about three times faster, and at thirty thousand about seven. (#288GitHub)
- perf: a plot lays its chrome out faster. Each axis title, tick label, and legend title is measured once per pass, and a
compose()panel is probed for its guides and its shared margin without drawing a canvas that is then thrown away. (#260GitHub) - docs: the benchmarks page plots against the row count, and attributes compile cost to the number of marks a chart draws, which is what the refreshed measurements show. It states that a line or a polygon carrying one hundred thousand points compiles inside the budget, where the same number of separate markers does not, and both figures and their alt text describe the eight cases now measured. The
guide-custom()row of the feature matrix no longer claims right-side placement only, which #278GitHub made false. (#295GitHub) - docs: the benchmarks page reports the library as it stands. Its dataset was measured before the two quadratic defects closed, so every figure on it described those defects. The sweep also gains a polygon case, which carries many vertices on few marks, the shape a boundary layer has and the one no case covered. (#294GitHub)
- docs: the gallery hub cards show a focus ring for keyboard users, and their text can be selected under the whole-card link. The hub also states that the per-example anchors of the old
/examples/page are gone, and sends readers to the intent pages instead. (#269GitHub) - docs: the Typst-markup examples on
typst()andelement-typst()write a mean as$macron(x)$. They used$bar(x)$, the vertical-bar symbol rather than the overbar their alt text described. (#253GitHub) - docs: a reference page no longer opens with the release that introduced the function. The version was typed by hand and drifted, and the changelog already records when a function landed. (#251GitHub)
- docs: docs site footer links read as ink rather than the muted grey Quarto paints them, and pick up the site-wide hover colour. (#246GitHub)
- docs:
sec-axisanddup-axissay that a secondary axis degrades to a no-op undercoord-radial, and the feature matrix lists it alongsidegeom-rugamong the combinations that do not translate to polar. (#236GitHub) - docs: the examples are organised by what a reader wants to show rather than by which part of the API they exercise, replacing the single feature-ordered page. A card hub routes to six story pages and six feature pages, each card carries a data-shape badge, and eighteen new plots on the bundled datasets demonstrate the practice. (#201GitHub)
- docs: tighten prose and apply consistent British spelling across the README, contributor docs, docs site guides, and the AI-assistant skill. (ba66650GitHub)
- build: the package compiles against Typst 0.15.0. Use Typst 0.15.0 or newer. (#282GitHub)
0.6
0.6.0 (2026-07-28)
Breaking changes
- feat!: axis ticks are themed through the single
axis-ticksfamily, where the newelement-tick(colour:, stroke:, length:)carries the mark length.tick-lengthand its per-axis and per-side variants are removed,tick-labelsgives way to hiding labels per side withaxis-text: element-blank(), andaxis-ticks: element-blank()is the one switch that turns marks off, reserving no depth either. (#150GitHub) - feat!: the summary-dispatch kernel
summarise(name, values)leaves the public API as the internal_apply-summary, freeing thesummarisename for the new wrangle verb. Thefun:argument ofstat-summaryandstat-summary-bin, a name string or callable, is unchanged. (#198GitHub)
Changes
- feat: automatic continuous breaks come from the extended Wilkinson search (Talbot, Lin, and Hanrahan 2010), which scores candidate tick sequences on simplicity, coverage of the data, and tick count, replacing the fixed 1/2/5 ladder on axes and continuous guides. Most plots gain rounder ticks that sit closer to the data, and
breaks-extended(n:)exposes the search for a different target count. (#217GitHub) - feat:
breaks:andminor-breaks:on a continuous scale accept a closure called with the vector of values the scale trained on, once per panel, so free-scale facets each get their own. Unlike an explicit array, closure breaks are clipped to the trained domain rather than widening it. (#216GitHub) - feat:
breaks-width(width, offset:),breaks-pretty(n:), andbreaks-quantile(probs:)build that closure for the common placements: a fixed step, round positions at a target count, and sample quantiles of the data. (#216GitHub) - feat:
summarise(data, ..aggregations, by:)andcount(data, ..cols, sort:)bring grouped aggregation to the row-store data model: one output row per group, namedrows => valueaggregation closures, and first-appearance group order. Both accept column-store input and feed#plotdirectly. (#198GitHub) - feat:
as-numeric(data, col, na:)takes a list of sentinel values, or a bare value. Cells equal to a sentinel, string cells compared trimmed, becomenonebefore parsing, so missing-value placeholders such as"NA"or"-99"do not survive as spurious numbers. (#198GitHub) - feat: column and row selection verbs
select(data, ..names),rename(data, ..renames),relocate(data, ..cols, before:, after:),drop-na(data, ..cols),distinct(data, ..cols), andslice-max/slice-min(data, col, n: 1, by:)reshape, dedup, and rank a row-store, sorting non-numeric or missing values last. They accept column-store input and feed#plotdirectly. (#198GitHub) - feat: reshaping verbs
pivot-longer(data, cols, names-to:, values-to:)andpivot-wider(data, names-from:, values-from:)melt columns into a name/value pair and spread them back, round-tripping modulo column order. Absent combinations are filled withnone, an ambiguous duplicate spread fails, and theas-factortag is carried on surviving identifier columns. (#198GitHub) - feat: join verbs
left-join/inner-join/full-join/semi-join/anti-join(x, y, by:)combine two row-stores on shared key columns, taking a natural join on the common columns whenby: noneand failing on a non-key column present in both.bind-rows(..datasets)andbind-cols(..datasets)stack or glue datasets, unioning columns withnone-fill or zipping them by row position. (#198GitHub) - feat: the bundled
mpgdataset carries adrvcolumn ("4","f","r"), so drive train can be faceted, coloured, or grouped on without substitutingcyl. (#226GitHub) - feat: minor tick marks are themable through
axis-ticks-minorand its per-axis variants, replacing the hardcoded half-length, major-stroke sub-decade ticks drawn byguide-axis-logticks(). They inherit the major tick record, so the default rendering is unchanged. (#150GitHub) - fix: a numeric
nudge-x/nudge-yongeom-text,geom-label, andgeom-typstno longer fails the compile when a positional scale is discrete. The offset shifts in level units there, matchingposition-nudge, and a nudge on the continuous axis of such a plot now applies instead of erroring. (#225GitHub) - fix:
dup-axis(breaks:, labels:)andsec-axis(breaks:, labels:)are honoured. The secondary axis drew the primary grid with the primary formatting whatever these were set to. (#216GitHub) - fix: a continuous scale trained on whole numbers only (years, counts, epoch days) keeps whole automatic breaks on axes and on continuous legends, so a narrow range such as 2020 to 2023 no longer labels half-steps. (#213GitHub)
- fix: legend entry labels, vertical colourbar tick labels, and y-axis tick labels centre on the cap-height/baseline band instead of the glyph bounds, so a label carrying a descender (
Chinstrap) no longer sits higher than one without (Adelie). (#208GitHub, #209GitHub) - docs: footer links are legible in light mode, where they were painted the page colour, and the footer top rule reads in dark mode instead of being 8% black on dark paper. The copy-to-clipboard button no longer hangs past the bottom border of a one-line code block. (#222GitHub)
- docs: the theming guide gains a “Ticks and their labels” section showing
element-tick, ratio lengths, minor marks, and per-side label hiding. (#219GitHub) - docs: reference pages link every cross-reference instead of printing a bare
@geom-linewhen the reference closes a parenthetical, and links no longer run into the preceding word or comma. (#215GitHub) - docs: every
scale-*reference page lists the keys its..argsaccepts with their type, accepted values, and default, including the previously undocumentedoob, instead of naming a few of them in prose. (#214GitHub) - docs: in the collapsed navbar, the colour-scheme toggle and the search button group at the right edge, separated by the same gap as the rest of the navbar-right controls, and the brand centres. The toggle used to sit beside the brand with the search alone at the far right. (#210GitHub)
- docs: the navbar GitHub icon becomes a widget showing live star and fork counts and a project menu (repository, issues, pull requests, releases, star, fork, Typst Universe, sponsor), replacing the separate Typst Universe, source-code, releases, and sponsor links. The version switcher, GitHub widget, search button, and colour-scheme toggle share one pill button style. (#205GitHub)
- docs: add a “Wrangling data” guide walking a dataset from coercion through grouped aggregation, reshaping, and joining into
#plot, with guidance on when native Typst suffices. (#198GitHub) - docs: the News page and the changelog link the Gribouille 0.6 release announcement. (#227GitHub)
- docs: the stable site is rendered wholly from the release tag instead of taking its pages from
mainagainst a pinnedsrc, so each site documents the API it ships with. A documentation fix now reaches the stable site at the next release rather than immediately. (336b698GitHub) - docs: the navbar is dark in both light and dark schemes, matching the other project sites. Add scheme-aware scrollbars, an accessible skip link and focus outline, and fix the tabset panel border that was indistinguishable from the background in dark mode. (d21e005GitHub)
- docs: in the collapsed navbar, opening a menu such as Guides overlays on top instead of growing the navbar and pushing the other items down, matching the GitHub widget menu. (930fb21GitHub)
0.5
0.5.0 (2026-07-13)
Breaking changes
- feat!:
linetypeongeom-segment,geom-curve,geom-spoke,geom-errorbar,geom-errorbarh,geom-linerange, andgeom-pointrangedefaults toautoand honours a mapped linetype scale instead of pinning"solid". (#169GitHub) - feat!: every constructor dict stores its concrete type under a single
name:key. The per-family fieldsgeom:(layers),coord:,facet:,family:(scale stubs),labeller:, andkey:(draw keys) are renamed,guide-custom()returnskind: "guide", name: "custom", andposition-fill()/position-identity()/position-stack()carry an explicitparams: (:). Only code that pattern-matches the returned dicts is affected. (#168GitHub) - feat!: the per-aesthetic
scale-*constructors collapse into an aesthetic-agnostic set keyed throughscales(), soscale-colour-viridis-d()becomesscales(colour: scale-viridis-d())andscale-x-log10()becomesscales(x: scale-log10()).plot(scales:)takes only thescales()dictionary, with no positional array, andexpand-limits()returns an aesthetic-keyed dictionary. (#158GitHub)
Changes
- feat:
geom-beeswarm,position-jitter, andposition-jitterdodgeswarm or jitter a discrete x directly, likegeom-violin, soas-factoris needed only to force a numeric column onto a discrete axis. Level positions follow the sorted axis domain, so the swarm aligns regardless of row order. (#196GitHub) - feat:
facet-wrapandfacet-gridgain agutterargument and honour a newtheme(panel-spacing:)default, a length for both axes or a(x:, y:)dictionary. The fixed 0.4/0.3cm panel gaps become a shared 0.5cm default. (#191GitHub) - feat:
composegutteraccepts a(x:, y:)dictionary for independent column and row spacing alongside the existing scalar length. (#191GitHub) - feat:
stat-waffleturns per-group counts, one per row or the roundedweightsum, into unit cells on an integer grid, column-major from the bottom-left with groups tiling consecutive runs. Render waffle charts withgeom-tile. (#189GitHub) - feat:
stat-connectgainsconnection: "sigmoid", a logistic S-curve connector rescaled through both observations withsmoothandncontrol. Paired withgeom-lineand a reversed y scale it draws bump charts. (#188GitHub) - feat:
position-stackgains streamgraph baseline offsets:offset: "silhouette"centres each stack on zero andoffset: "wiggle"uses the Byron-Wattenberg wiggle-minimising baseline, turning stackedgeom-areainto a streamgraph. (#187GitHub) - feat:
stat-differenceshades the band between two series by which one is on top. Exact linear crossovers are inserted as shared vertices so ribbon segments meet cleanly, and each run carries a_signlevel, named throughlevels:, forfill: after-stat("_sign"). (#186GitHub) - feat: fills accept native Typst
tilingpaints, both as fixedfill:values and throughscale-manual(values:), with legend swatches rendering the patterns. Per-row alpha and seam sealing skip non-colour paints. (#182GitHub) - feat:
position-beeswarmandgeom-beeswarmarrange overplotted points into a deterministic density-shaped swarm (van der Corput walk scaled by each point’s kernel density), a reproducible alternative toposition-jitter. (#181GitHub) - feat:
geom-density-ridgesandstat-density-ridgesdraw overlapping ridgeline plots from raw observations: one Gaussian-KDE ridge per y bucket with heights normalised across buckets, ascaleparameter in y-level units, and a newheightaesthetic channel. (#180GitHub) - feat:
geom-density-2d/geom-density-2d-filledand their stats trace iso-lines or shade iso-bands of a native 2D Gaussian kernel density estimate of the raw(x, y)sample, with per-axis bandwidth and grid control. (#178GitHub) - feat:
geom-smooth/stat-smoothgainmethod: "loess"withspananddegreecontrol: native tricube-weighted local polynomial fits with a pointwise confidence band onn − trace(L)degrees of freedom. (#177GitHub) - feat:
geom-violinandstat-ydensitydraw mirrored per-bucket density silhouettes withscale: "area"/"count"/"width"normalisation,trimcontrol, and dodge support, sharing the native Gaussian KDE core withstat-density. (#176GitHub) - feat:
geom-densityandstat-densitybring native 1D kernel density estimation: Gaussian kernels evaluated directly on ann-point grid, Silverman (bw.nrd0) bandwidth withadjustandtrimcontrol, weight support, and_density/_count/_scaled/_nafter-stat columns. (#175GitHub) - feat: every geom exposes
key:, a legend glyph override, and, where meaningful,stat:andposition:. Stat-backed geoms takestat: autoto build their default stat from the geom parameters. (#169GitHub) - feat: a keyed
scales()constructor, mirroringguides(), binds scale overrides to aesthetics as named arguments, for examplescales(x: scale-continuous(), colour: scale-viridis-d()), instead of a positional array. (#157GitHub) - feat: an installable Agent Skill teaches coding agents to author Gribouille plots, confirming every argument against the site’s
.llms.mdreference. The repository doubles as a Claude Code plugin marketplace, so the skill installs through/plugin installornpx skills add. (#154GitHub) - feat: geom and theme-element
stroke:accept the native Typst1.3pt + accentform, writing thickness and paint together. An explicitcolour:still wins over the embedded paint. (#153GitHub) - fix: support explicit
as-factor()onxforgeom-violin,geom-boxplot, and other per-group stats when a grouping aesthetic reuses the same column. (#195GitHub) - fix:
geom-densitywith a mappedfillaesthetic shades the curves instead of rendering a blank panel. The default is unfilled through a fill role rather than a hardfill: none. (#192GitHub) - fix: non-identity positions (
jitter,beeswarm) over anas-factorpositional column that is also mapped tocolour/filldraw the mapped scale colours instead of the default. The 1-indexed positions go to a synthetic column, so the source column keeps its levels. (#192GitHub) - fix: pre-stat grouping skips late-binding markers without a source column, such as
fill: after-stat("_sign")andcolour: after-stat("_level"), instead of crashing on the marker dict. The stat-output column groups the rows once the stat has run. (#186GitHub) - fix:
annotateforwards anoneorautovalue on an aesthetic keyword, such asannotate("rect", fill: none), to the geom as a layer parameter instead of storing it as a data cell. The disable and scale-resolve sentinel then applies, and the shape is drawn unfilled. (#183GitHub) - fix: fill opacity defaults to 1 on
geom-area,geom-ribbon,geom-polygon,geom-ellipse, andgeom-markinstead of an implicit 0.3-0.6 translucency. Explicitalpha:values and mapped alpha aesthetics are unaffected. (#179GitHub) - fix: abutting opaque fills (tiles, hexes, stacked bars and areas, iso-band cells) are stroked with their own fill colour, removing the hairline background seams that antialiasing bled through between adjacent shapes. (#178GitHub)
- fix: stat-quantile replaces the O(n³) pair enumeration with an exact O(n² log n) breakpoint search, scaling geom-quantile to thousands of rows with identical fits on unique optima. (#174GitHub)
- fix: an unknown scale-* constructor argument fails at scales() binding with the valid keys for that scale and aesthetic, and stray positional arguments are rejected instead of ignored. (#172GitHub)
- fix: an unknown
stat, scaletransform, oroobname fails with a clear error instead of silently rendering as identity or dropping rows. (#162GitHub) - fix:
theme()rejects unknown or misspelled element keys and positional arguments instead of storing a key the renderer never reads. (#162GitHub) - fix:
aes()rejects unknown aesthetic names, such as the US spellingcolor, with a message listing the valid channels. (#162GitHub) - fix:
plot()validates themapping,layers, andcoordarguments up front with a named error instead of a cryptic renderer failure. (#162GitHub) - fix: data-ingestion and
from-themepath errors show the offending value. (#162GitHub) - fix: mapping an aesthetic or a facet variable to a column absent from the data fails with a clear error naming the aesthetic, the unknown column, and the available columns, instead of rendering a misleading all-
noneplot. (#156GitHub) - 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: the published Typst Universe README drops the repo-only “Ask DeepWiki” badge and keeps the “AI assistants” section. (#194GitHub)
- docs: add streamgraph, bump chart, difference band, and waffle chart gallery examples. (#193GitHub)
- docs: a Recipes guide shows chart types and effects built by composing layers and native Typst, with no dedicated geom: lollipop and dumbbell charts, group highlighting, zoom insets, marginal panels, irregular grid layouts, and trend-line casing. (#185GitHub)
- docs: the agent skill covers the current API: the aesthetic-agnostic
scales()constructors, the density and pattern-fill idioms, and a symbol inventory regenerated fromlib.typand checked in CI. (#184GitHub) - docs: each scale constructor reference page carries a runnable example in the keyed
scales()form. (#160GitHub) - docs: an AI Assistants guide explains how to use Gribouille with large language models through the
llms.txtmachine-readable documentation and the installable skill. (#154GitHub) - 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.4
0.4.1 (2026-06-23)
- fix:
position: "dodge"shifts point-based geoms (text, label, point, linerange, and others) 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, and 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()andcompose()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, the default, keeps the smooth area. (#135GitHub) - feat:
element-text()andelement-typst()angleis honoured on axis titles, strip text, and legend title and entry labels, where before it reached only tick labels and the plot title, subtitle, and caption. Axis titles default to 0deg on x and 90deg on y, and reserve the correct space at any angle. (#134GitHub) - feat:
geom-text(),geom-label(), andgeom-typst()accept anangleparameter, a Typst angle defaulting to0deg, rotating each label. (#134GitHub) - feat: every aesthetic key can be pinned as a constant directly on any geom, for example
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, for exampleexpand: (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 or array parameter still draws shared lines when nothing is mapped. (#129GitHub) - feat: a font set in
theme(text: ...)reaches literal-glyph point markers, such asshape: 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 the x and y and the major and 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, and reverse, and sub-decade lines for log10.
scale-*-continuous, including log10, sqrt, and reverse, acceptminor-breaksandn-minorto position them. (#125GitHub) - feat: the
legend-positiontheme entry sets a global side for every legend, astheme(legend-position: "bottom")or throughtheme-sub-legend(position:), accepting the same values asguide-legend(position:). Any explicitguides()placement still wins. (#123GitHub) - feat: discrete swatch legend key glyphs are resizable through
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, for examplelimits: (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, and 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 apply togeom-text,geom-label, andgeom-typst, where they used to be a silent no-op. (#131GitHub) - fix: setting the base
line/rectstroke intheme()cascades to every line and rect surface: panel grid, axis line, ticks, legend ticks, and legend bar.element-line/element-rectstrokeaccepts a ratio, such as80%, to scale the parent surface thickness, while an absolute length still pins a surface. (#124GitHub) - fix: setting the base
textsize intheme()cascades to every text surface: axis titles, tick labels, legend, strip, and plot title.element-text/element-typstsizeaccepts a ratio, such as80%, to scale the parent surface size, while an absolute length still pins a surface. (#121GitHub) - fix:
position: "dodge"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 built with the newdefer()helper,defer(plot, ...), ordefer(compose, ...)to nest, replacingplot(..., defer: true). Panels omit their ownwidth/height, and the composition sizes each cell. (#81GitHub)
Changes
- feat: the published package ships Tinymist-friendly docstrings, so 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, its arc, minor ticks, and tick labels, andguides(r: none)hides the radial tick labels, leaving the spokes and circles.guides(theta: none)used to add a theta arc instead of hiding the axis. (#106GitHub) - feat:
guides(x: none)andguides(y: none)hide that axis’s tick marks and tick labels, including any log minor ticks, and reclaim the freed space. The axis line, grid, and title stay, and the title is removed 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. This replaces the removedguide-none(), wherenoneis passed instead. (#104GitHub) - feat:
annotate()gains aclipargument,trueby default. Setclip: falseto let an annotation overflow the panel, such as 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 resampled onto a shared grid and stacked without an explicitstat: stat-align(). (#77GitHub) - fix:
stat-bin-2dandstat-bin-hex_densityis 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 and negative forlog10, panics with a clear scale message instead of a raw Typst error. The sqrt inverse clamps padded view bounds at zero, so sqrt axes stay monotone and show the0break. (#109GitHub) - fix: a horizontal legend (
position: "top"or"bottom") withguide-legend(align: center)oralign: rightcentres 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-backgroundinherits the baserectelement like every other*-backgroundsurface, sotheme(rect: ...)cascades to it instead of being ignored. (#101GitHub) - fix:
guide-legend(nrow:)andguide-legend(ncolumn:)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:)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 silence.alignis a Typst alignment:left,center, orright. (#98GitHub) - fix:
annotate(clip: false)placed outside the scalelimitsdraws 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 or right legend that would overrun the caption, or a hoisted
compose()legend that leaves no room for the panels, 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, where the line used to be drawn fully opaque. (#85GitHub) - fix:
geom-area(position: "stack")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 list their real parameters instead of an opaque..argsrow, and a mixed signature likeannotate(geom, ..fields)also listsclip. (#102GitHub) - docs: the
theme()reference table 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,falseby default. Whentrue, panels share margins grid-wise, left and right per column and top and bottom per row, so their plot areas line up across rows and columns, likepatchworkandcowplotpanel 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, such asgeom-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, and"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 and vertical legends 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, such asB.1andB.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 controls the collected legend’s side throughguides, such asguides(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’spositiondefaults 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()andelement-typst()gain analignparameter setting per-surface text alignment, independent of the container. Title and subtitle default to left, caption to right, and axis titles and strip text to 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 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 such as
geom-smoothno longer panic when a grouping aesthetic is mapped throughafter-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, so
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, and others), for exampleaes(x: "class", fill: "class"), resolves the grouping aesthetic across aggregating stats (boxplot,summary,count/sum, histograms). It used to draw 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/heightbound 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 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 follow the light/dark theme, and the active tab label uses the brand primary colour in both schemes. (#15GitHub)
- docs: the development version is downloadable from the dev documentation site and installable as a local package, and the 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.