Skip to content

1.16.0

Choose a tag to compare

@github-actions github-actions released this 29 Sep 01:48
· 406 commits to main since this release

Breaking changes

  • A ContextMenu merges onto the element it is given rather than wrapping it. The trigger put a <div> of Base UI's around children, and nothing could reach that box — className goes to the popup — so a scroll container handed to a menu became a scroll container inside a box with no height, and its content spilled instead of scrolling. children is one element now, which the trigger merges onto exactly as Tooltip's does, and the menu costs the layout nothing. An area written as several elements, a fragment or bare text has to be wrapped in one element of the caller's own.

Where the bytes went

What you import 1.15.0 1.16.0
Button 5.1 kB 5.1 kB
Chip 3.4 kB 3.4 kB
LineChart 12.6 kB 15.7 kB
CodeBlock 5.5 kB 5.5 kB
Image 8.8 kB 8.8 kB
Gallery 11.7 kB 11.7 kB
a whole page shell 30.0 kB 30.0 kB
12 components — a typical app 71.6 kB 71.7 kB
12 components, with Korean 75.6 kB 75.7 kB
25 components — a large one 118.7 kB 118.8 kB
all exports 286.6 kB 290.4 kB

One row moved, and it is the one the release is about. A LineChart grew 3.1 kB and so did every other cartesian chart: the reference lines, the export button, the second value axis and the turn arithmetic all live in chart-frame.tsx, which is in all five of their bundles.

What is not in them is the brush. It is 1.5 kB behind a React.lazy of its own, which a chart with no window never fetches, and the CSV writer is another 0.5 kB fetched on the press. Both show in the unbudgeted async column npm run size prints beside every scenario, which is where they can be watched rather than quietly become the entry's problem.

The two app rows moved a tenth each, and neither list holds a chart: that is TextField and Select carrying fieldLight beside trackPointer, and Tabs carrying its alignment map. The page shell has neither and did not move.

Registering a language still costs 4.0 kB. The one word this release added is the export button's, in the chart namespace, and none of those twelve components reads it.

neba/styles.css is 24.6 kB gzipped against 24.5 kB: the rule that puts a field's pointer light out while the reader is typing, and the utilities the brush strip and the export button are drawn with.

Added

  • nulls on a LineChart and an AreaChart, with a third answer to a gap. connectNulls had two: break at a null, or bridge it. The one it could not say is the one a caller with an event count wants, which is that a missing row means none happened — so nulls takes 'gap', 'connect' or 'zero'. zero rewrites the data rather than the drawing, so the axis takes the nought into its range and the tooltip and the table say 0 as well; a line pulled to the baseline over a table that still says nothing is a chart disagreeing with itself. connectNulls is now the old spelling of 'connect', still read when nulls is left out.

  • nulls on a Sparkline too. The same three answers, and they matter more on a strip than on a chart: there is no tooltip and no axis to notice a hole with, so one that quietly closes over three missing weeks is a trend nobody can tell was interpolated. zero rewrites the values, so the range the strip scales itself to takes the nought in and the numbers read out to a screen reader change with it.

  • tickAngle on NebaChartAxis, which turns the category labels. Between -90 and 90 degrees. Flat, a long category name has one slot to fit in, so the axis cuts it to an ellipsis and then drops every other one; turned, each label only has to clear its neighbour across its own height, and the room a name needs stops depending on how long the name is. Seven onboarding stages that showed two labels show all seven, whole. The band under the plot grows to hold them, capped at the smaller of 140 pixels and two fifths of the box — past that they are still cut, because a chart that is mostly axis is not a chart. Read on the category axis only, and only where that axis runs along the bottom.

  • brush on every cartesian chart — a window on a series a plot cannot hold. Two thousand points is a chart with no points on it: every column is a fraction of a pixel and the shape is a smear. The strip under the plot draws all of them small, the window on it says which part the chart draws, and dragging either handle or the window itself moves it. The handles are role="slider" buttons rather than shapes inside the picture, so the arrow keys move them and a screen reader is told which category each one sits on — the strip is a sibling of the plot for that reason, since role="img" makes everything under it presentational. It is drawn inside the chart's own height, like the axis labels. The window narrows the picture and nothing else: the hidden table and the exported file still hold every point.

  • secondaryAxis, and axis: 'secondary' on a series — two value scales on one plot. For the series whose units are not the others': revenue beside a conversion rate, a count beside a duration. The second axis is drawn on the far edge — the right of a vertical chart, the top of one turned on its side — and its own tickFormat writes its series' numbers everywhere they appear, the ticks, the tooltip and the table, because the alternative is a percentage printed with the other axis' currency in the one place the two meet. It casts no gridlines: two grids on one plot is graph paper drawn twice, so its ticks land at the same count as the first axis' and the rules already there serve both. Not read on a stacked chart — a stack is a total, and a total across two units is not a number. Worth reaching for rarely, which is why the axis is drawn and labelled rather than merely implied: two scales let a caller make any two series look like they move together, and the reader cannot see that it was done.

  • exportable on every chart that has a table — the numbers as a CSV file. A picture is the one form of a number nobody can paste anywhere, and the table a screen reader gets is not reachable with a pointer; this is the pointer's way to the same thing. exportFileName names the file and onExport takes the string instead of downloading it. The module that writes the CSV is fetched on the press rather than imported with the chart, which is highlight.ts' arrangement in miniature: a page that never turns this on downloads none of it, and no bundle moved. A GaugeChart does not take the three props at all — one reading is not a sheet — and the chart's own words gained an exportCsv entry in all nineteen languages.

  • references on every cartesian chart — lines and bands across the plot. A target, an SLA, a budget, the window a forecast covers: the one thing on a chart that is neither a mark nor chrome. value places one and to turns it into a band; axis: 'category' reads the numbers against the other axis, for a rule that says when rather than how much. The scale widens to hold them, so a target above everything measured is still on the chart, and one that names itself is read out with the data — the picture is aria-hidden, so a reader who gets the table instead would otherwise never learn the target exists. Drawn dashed and neutral unless told otherwise, because a reference in danger says the line is the bad thing when usually the bad thing is the data crossing it.

  • xAxis and yAxis on a HeatmapChart. It had neither, so its column names could only be thinned by the stride — a grid of long stage names showed two of them and there was no prop to say otherwise. Both are category axes here, since the magnitude is on the colour ramp the scale legend describes, so min, max, tickCount and grid are not read; label, tickFormat, hidden and thickness are, and xAxis.tickAngle turns the column names. The arithmetic behind the turn moved into chart.ts as turnedAxis, so a heatmap and a cartesian chart on one dashboard cannot disagree about how deep a band of turned names runs.

  • hole and gap on a PieChart. shape already sets how much of the middle is cut out and hole is the dial behind it, from 0 to 0.92 of the radius; gap is the surface showing between two touching slices, in pixels rather than degrees, because the gap is a constant on screen and one that looked right on a 300px chart is a wedge out of a 60px one. hole on a pie is also what gives that shape somewhere to put a center.

  • align on Tabs. Where a tab's label sits once the tab is wider than the label is. A vertical bar is the case it exists for: every tab in a column is as wide as the longest one, and centred labels down a column read as a ragged edge on both sides. It moves the label and the icons and nothing else — the tab keeps its size, its padding and its indicator.

Changed

  • A field's pointer light is half what a control's is, and goes out while the reader types. A control is the thing the pointer acts on, so the bloom under the cursor is the control answering; a field is on the way to somewhere else, and what the reader looks at a moment later is their own text over the exact patch the bloom is brightest on. So a TextField, NumberField, Combobox, Select, PromptInput and the date and time pickers take fieldSpotlightSlot, which is the same light at 50%. And because a pointer resting on a field is where the hand left it — over the text, since that is where the reader clicked to get the caret — the one moment the bloom is least wanted is the one moment it cannot get out of the way on its own: a keystroke puts it out and the next pointer movement brings it back. Any key, not only the ones that produce text. Nothing about a Button, a Toggle, a Pill or a menu row changes, and neither does what a page carrying one of those weighs: the two handlers are their own export beside trackPointer rather than a line inside it.

  • A chart's value labels wear their own series' colour. On a plot with four lines on it, a number floating above a point belongs to whichever line it is nearest, and "nearest" is exactly what a reader cannot judge where two of them cross — so the hue says which. Not the mark's colour as it stands: a ramp slot is solved to be a 2px line and lands near 4:1 on white, under what twelve-pixel type has to clear, so the label is that colour taken one step toward the page's own ink. Measured per slot in both themes, worst case 4.97:1 on white and 6.38:1 on the dark sheet.

  • A hidden series fades in the legend instead of going grey. Grey is a ninth colour on a chart that has eight, and a row recoloured to say "off" stops saying which series it is. It fades whole — swatch and name together, at its own colour — which is the same sentence the hover dimming makes one scale up: not the one you are looking at.

Fixed

  • A Switch is drawn inside its own field. The track is taller than the line of text it labels from md up — 20, 24 and 28 pixels against a line of 18.2, 21 and 23.8 — and the box it sits in is that line, so the top and the bottom of the track were drawn outside the field. In anything that scrolls, that is a track with its corner clipped off; against whatever sits above the row, it is a track laid over it. The row makes room for the overflow instead, half above the line and half below, which leaves the track exactly where it was against the label and makes the field the height of what it draws. A Switch at those three steps is therefore 1.8, 3 and 4.2 pixels taller than it measured before. xs and sm do not move: the track already fits inside the line there.

Every release is in the changelog on the docs site and in CHANGELOG.md at this tag.