|
| 1 | +# Observable Plot - Changelog |
| 2 | + |
| 3 | +Year: **Current** · [2025](./CHANGELOG-2025.md) · [2024](./CHANGELOG-2024.md) · [2023](./CHANGELOG-2023.md) · [2022](./CHANGELOG-2022.md) · [2021](./CHANGELOG-2021.md) |
| 4 | + |
| 5 | +## 0.6.18 |
| 6 | + |
| 7 | +[Released TK, 2026.](https://github.com/observablehq/plot/releases/tag/v0.6.18) |
| 8 | + |
| 9 | +The [area mark](https://observablehq.com/plot/marks/area) now supports a **line** option: when set to true, a stroked line is drawn on top of the filled area, removing the need for a separate line mark; when line is true, the the fill opacity defaults to 0.3 and the stroke options (`strokeWidth`, etc.) apply only to that line. |
| 10 | + |
| 11 | +<img src="./img/ridgeline.png" width="928" alt="a ridgeline plot of traffic patterns by location, with stroked lines on top of filled areas"> |
| 12 | + |
| 13 | +```js |
| 14 | +Plot.plot({ |
| 15 | + height: 300, |
| 16 | + marks: [ |
| 17 | + Plot.areaY(traffic, { |
| 18 | + x: "date", |
| 19 | + y: "vehicles", |
| 20 | + fy: "location", |
| 21 | + fill: "#eee", |
| 22 | + line: true, |
| 23 | + fillOpacity: 1, |
| 24 | + curve: "basis" |
| 25 | + }) |
| 26 | + ] |
| 27 | +}) |
| 28 | +``` |
| 29 | + |
| 30 | +The [raster mark](https://observablehq.com/plot/marks/raster) now supports a **colorSpace** option, allowing interpolation in wide-gamut color spaces such as *display-p3*. For example, this raster plot of penguin body mass vs. flipper length encodes the `island` channel with vivid P3 colors: |
| 31 | + |
| 32 | +<img src="./img/raster-p3.png" width="640" alt="three clusters of penguins rendered as blurred color fields in vivid lime, orange, and violet"> |
| 33 | + |
| 34 | +```js |
| 35 | +Plot.plot({ |
| 36 | + color: {range: ["oklch(90% 0.4 135)", "oklch(75% 0.3 55)", "oklch(65% 0.35 305)"]}, |
| 37 | + marks: [ |
| 38 | + Plot.raster(penguins, { |
| 39 | + x: "body_mass_g", |
| 40 | + y: "flipper_length_mm", |
| 41 | + fill: "island", |
| 42 | + interpolate: "random-walk", |
| 43 | + blur: 8, |
| 44 | + colorSpace: "display-p3" |
| 45 | + }) |
| 46 | + ] |
| 47 | +}) |
| 48 | +``` |
| 49 | + |
| 50 | +[Pointer tips](https://observablehq.com/plot/interactions/pointer) are now exclusive by default: when multiple pointer-driven marks overlap, only the closest point is shown. This avoids the common issue of multiple marks creating overlapping tips. This behavior is controlled by the new **pool** [mark option](https://observablehq.com/plot/features/marks#mark-options), which defaults to tru for tip marks; set `pool: false` to restore the previous behavior. |
| 51 | + |
| 52 | +The new top-level [**legend** plot option](https://observablehq.com/plot/features/legends) provides a convenient shorthand for requesting a legend, replacing the more verbose `color: {legend: true}` pattern. |
| 53 | + |
| 54 | +```js |
| 55 | +Plot.plot({ |
| 56 | + legend: true, |
| 57 | + color: {type: "ordinal", domain: "ABCDEFGHIJ"}, |
| 58 | + marks: [Plot.cellX("ABCDEFGHIJ")] |
| 59 | +}) |
| 60 | +``` |
| 61 | + |
| 62 | +The new [plot.scale("projection")](https://observablehq.com/plot/features/projections) method exposes the plot’s projection, allowing programmatic access after rendering. The returned object supports *apply* and *invert* for converting between geographic and pixel coordinates, and can be passed as the **projection** option of another plot. |
| 63 | + |
| 64 | +```js |
| 65 | +const plot = Plot.plot({projection: "mercator", marks: [Plot.graticule()]}); |
| 66 | +const projection = plot.scale("projection"); |
| 67 | +projection.apply([-1.55, 47.22]) // [316.7, 224.2] |
| 68 | + |
| 69 | +// reuse in a new plot with different marks but the same projection |
| 70 | +Plot.plot({projection, marks: [Plot.geo(countries)]}) |
| 71 | +``` |
| 72 | + |
| 73 | +The [opacity scale](https://observablehq.com/plot/features/scales) and associated legend now support *ordinal* and *threshold* types. |
| 74 | + |
| 75 | +```js |
| 76 | +Plot.cellX(d3.range(10), {fill: "red", opacity: Plot.identity}).plot({ |
| 77 | + opacity: {type: "threshold", legend: true, domain: [2, 5, 8], range: [0.2, 0.4, 0.6, 0.8]} |
| 78 | +}) |
| 79 | +``` |
| 80 | + |
| 81 | +Plot now supports the `light-dark(…)` CSS color syntax, making it easier to define colors that adapt to dark mode. Color and opacity legends also render correctly with `light-dark(…)`, `currentColor`, and display-p3 colors. |
| 82 | + |
| 83 | +```js |
| 84 | +Plot.barX(alphabet, {x: "frequency", y: "letter", fill: "light-dark(steelblue, orange)"}) |
| 85 | +``` |
| 86 | + |
| 87 | +This release includes several more bug fixes and improvements: |
| 88 | + |
| 89 | +The [tick format](https://observablehq.com/plot/features/scales) now defaults to a comma-less format when tick values are likely year integers. |
| 90 | + |
| 91 | +<img src="./img/axisYears.png" width="640" alt="before and after comparison of year tick labels, showing commas removed"> |
| 92 | + |
| 93 | +The [stack transform](https://observablehq.com/plot/transforms/stack) now preserves NaN values instead of coercing them to zero. The [dodge transform](https://observablehq.com/plot/transforms/dodge) no longer crashes when the radius is negative. The [area mark](https://observablehq.com/plot/marks/area) now respects the **reduce** option when using the [interval transform](https://observablehq.com/plot/transforms/interval). |
| 94 | + |
| 95 | +For line and area marks, the *z* channel now defaults to null when the color channel is redundant with the position channel (*e.g.*, `lineY(data, {y: "value", stroke: "value"})`), preventing the line from being split into single-point series. The default offset in windowless environments (*e.g.* server-side rendering) is now zero, prioritizing high-density displays. The default colors for the [box mark](https://observablehq.com/plot/marks/box) and [tree transform](https://observablehq.com/plot/transforms/tree) now support dark mode. |
| 96 | + |
| 97 | +The [tip mark](https://observablehq.com/plot/marks/tip) no longer crashes when the title channel contains null; it now ignores the contours channel and literal symbols; and the tip arrow is smaller when using a corner anchor. [Markers](https://observablehq.com/plot/features/markers) no longer inherit `strokeDasharray`. The [pointer transform](https://observablehq.com/plot/interactions/pointer) now allows `pointerdown` event propagation. |
| 98 | + |
| 99 | +Various type fixes and documentation improvements; thanks @gka and @jsoref! |
| 100 | + |
| 101 | +--- |
| 102 | + |
| 103 | +For earlier changes, continue to the [2025 CHANGELOG](./CHANGELOG-2025.md). |
0 commit comments