Repository navigation
1.5.0
Added
- Charts. Five components on one engine:
Sparkline,LineChart,AreaChart,BarChartandPieChart. They take their data the wayTabledoes —series(or, for a pie,data) as a prop rather than markup — and they take it in the same shape as each other, so a dashboard tile can be switched from one chart to another without rewriting what feeds it.Statisticjoins them in a new Charts group in the docs. - A
nullis a gap, not a zero, on every one of them. A line breaks at it, an area breaks with it, a bar is not drawn and the table cell is empty;connectNullsbridges it for the case where the gap is an artefact of collection rather than a month in which nothing happened. A chart that renders missing data as zero reports an outage as a collapse. - A series' colour follows its place in the array it was passed, never its position among the visible ones — so filtering a legend cannot repaint the survivors, and a reader who learned that Europe is blue keeps that.
series.coloroverrides the slot with aNebaColorfamily or any CSS colour, and a point's owncoloroverrides that for one mark. LineCharttakescurve(linear, a monotonesmooththat will not dip below a value both its neighbours are above, orstep),markers,gradient,connectNulls,valueLabelsandstacked. Its value axis crops to the data, because a line encodes a position and cropping moves every point by the same amount.AreaCharttakes the same three curves plusstacked—truefor totals,'full'for a chart about the mix rather than the size, where the axis becomes a percentage and the tooltip and the table keep the caller's own number. Its axis keeps zero, because there the fill's thickness is the magnitude. Unstacked bands are a wash that fades downward so two of them overlapping stay readable; stacked bands are a flat tint parted by two pixels of the surface rather than by a stroke.BarCharttakesorientation—horizontalis the right answer whenever the category names are words — plusstacked(true/'full'),rounded,barSizeandvalueLabels. Corners are cut off the data end only; a rounded foot makes the axis look scalloped. Bars grow from where zero is rather than from the bottom of the plot, so a negative bar starts on the same line as its neighbours.PieCharttakesshape—pie,donutor asemicircle — pluscenterfor what goes in the hole, andvalueLabelsfor each slice's share, drawn only where the text fits with room on both sides and dropped rather than clipped where it does not.Sparklineis not a small chart: no axes, no grid, no legend, and no numbers, because every number it could label is one the sentence around it already has.shapeis a line, an area or bars;endDot,baseline,minandmaxare the rest of it. It fills itself with its own range, which is what makes it legible at twenty pixels tall — and why two of them are only comparable when both are given the sameminandmax.- A hidden table under every chart, always. The drawing is
aria-hiddenand the data is rendered as a visually clipped<table>captioned withlabel, so no value is reachable only by pointer. The plot itself is focusable:←/→step the crosshair between categories,Home/Endjump to the ends,Escapeclears it, and the tooltip is a live region. The legend is a list ofaria-pressedbuttons, so which series are drawn is stated rather than implied by colour. - Eight new colour tokens,
--neba-chart-1…--neba-chart-8, per theme — and the one place in the library where a colour is not a semantic role, because a series is an entity and nothing about it means success or danger. They were solved rather than picked: every step inside the OKLCH lightness band, chroma above the floor where a hue stops carrying identity, every adjacent pair at least ΔE 8 apart in OKLab under simulated protanopia and deuteranopia (measured at 13.6 light and 14.5 dark), and every slot above 4:1 on white and 5.3:1 on the dark sheet. Dark is re-solved against the dark surface rather than lightened from the light values. Slots are handed out in order and never cycled: a ninth series is an "Other" row or a second chart, not a ninth hue. --neba-chart-grid,--neba-chart-axis,--neba-chart-baselineand--neba-chart-gap— the chart's chrome, derived from--neba-borderand--neba-surfaceso a chart's rules and a Card's dividers are one family of line. Gridlines are solid hairlines: a dashed grid says "projection" when all it is is a grid.src/types.tsgains the vocabulary the charts share —NebaChartSeries,NebaChartDatum,NebaChartPoint,NebaChartCategory,NebaChartAxis,NebaChartLegend,NebaChartTooltip,NebaChartCurve,NebaChartValueLabels— for the reasonNebaSizeis there: aserieshanded to a LineChart has to be the one a BarChart takes.Collapsible. One section that folds, standing on its own — what anAccordionis a set of, for a "Show more" on a form or the detail under a row.title,subtitle,startIconandactionbuild the header the wayAccordionItemdoes, withactionoutside the trigger so a header that both folds and holds a switch has two things to press rather than one nested in the other;triggerreplaces the header entirely and the element passed becomes the trigger, handed the click,aria-expandedand thearia-controls.keepMountedandhiddenUntilFounddecide whether a closed panel is in the DOM, the second of them so the browser's own page search can open it.Rating. A score as a row of stars, and two components in one skin. Choosable, it is arole="radiogroup"of real<input type="radio">s hidden under the half-stars they stand for — one tab stop for the row, arrow keys within it,aria-checkedon the one that is taken and a value in a form submission, none of which a row of<button>s would have.readOnlyrenders no inputs at all and leaves onerole="img"carrying the score as a sentence, which is why it is the one read-only in the library that does not drain the saturation: it is not a control being held still, it is the number itself.precisionbounds what can be picked and never what is drawn, so avalueof4.3stays 4.3 — an average is not a choice, and rounding it would report a different number from the one it was handed. The fraction is a filled star laid over an empty one and clipped from the inline start, so nothing is scaled and a half star fills from the right under RTL on its own.BottomNavigationandBottomNavigationItem. An app's main destinations, held against the bottom edge of the window —positiondefaults tofixedhere, against thestaticeverything else defaults to, because that is what the component is. It is a<nav>of ordinary buttons (or<a>s, given anhref) witharia-current="page"on the one you are on, and deliberately not arole="tablist": a tab list promises one tab stop for the set and arrow keys within it, and a bottom navigation changes the page rather than which panel of one is showing.labelsdraws every name, only the current one, or none — and a name it does not draw stays in the document, because a glyph on its own has no accessible name at all.safeAreaholds the row clear of a phone's home indicator while the sheet still reaches the bottom of the screen.FloatingActionButtonandFloatingAction. The one action a screen is about, floating over it. The button is aButtonunchanged — same variants, same elevation ladder, same pointer light — started one step up the size ladder atlg, because this is the control that has to be found and hit with a thumb without being looked at.extendedwriteslabelbeside the glyph, which is also its accessible name, so the word drawn and the word read can never differ.positionaddsabsoluteto the three CSS valuesNebaPositionhas, which is what pins one inside a card or aMockuprather than to the window;cornerandoffsetplace it. GivenFloatingActionchildren it becomes a dial:aria-expandedandaria-controlsrather than arole="menu"it would not honour, the actions as ordinary buttons next in the tab order, Escape closing it and handing the focus back, and a press outside putting it away.
Documentation
- Five component pages in both locales —
Sparkline,LineChart,AreaChart,BarChart,PieChart— with the data model written out once on the LineChart page and cross-referenced from the rest, their props rows (including tables forNebaChartAxis,NebaChartLegendandNebaChartTooltip), sixteen demos, a Charts group in the component gallery, three charts and a row of sparklines on the sample screen, and their entries inllms.txt. Statisticmoved from Display to Charts, in both locales and in every index that names it.- Four component pages in both locales —
Collapsibleunder Surfaces,Rating,BottomNavigationandFloatingActionButtonunder Inputs — with their props rows, twenty-one demos, four cards in the component gallery, two new blocks on the sample screen, and their entries inllms.txtand the README. - A
ratingnamespace insrc/internal/i18n.ts, translated into all eighteen locales: the group's name, the sentence one star is read out as, and what an unrated control says. The sentence carries both numbers rather than counting stars, because a count of stars is a plural in most languages and a fraction in none of them.
Every release is in the changelog on the docs site and in CHANGELOG.md at this tag.