Box Kite 2.2.16
2 November 2026
What changed in this version, written as it landed. The same notes are the body of the GitHub release.
These notes are for 2.2.16. The documentation on this site is for 2.2.17, the current release — this site documents the newest version only.
2 November 2026 · npm · Compare v2.2.15...v2.2.16
The published types are whole again, so a misspelt component, variant or value is a type error rather than any — and a ref on Form and fourteen other components no longer breaks them on React 19.
Breaking changes
None.
Fixes
- From 2.2.6 to 2.2.15
@box-kite/coreshipped withoutcore/extends/boxComponents.d.ts, so the built-in components typed asany. Six of its declaration files import that one, and withskipLibCheck: true(every Vite and Next template) the missing file was silent:<Box component="cardd" />,<Box component="button" variant="nonsense" />and a misspelt value inside aBox.components()entry all type-checked. The file is back, at a seventh of its old size, so an app that compiled on 2.2.15 may now report errors — each one is a component name, a variant or a value that never rendered anything, and the fix is the one the message names.BoxComponentStylesis an interface now rather than a type alias, which is what lets a declaration name it instead of writing out every prop at every use. - Five
@box-kite/reactdeclaration files reached into@box-kite/coreby a relative path the package does not contain.react/componentsContext.d.ts, three DataGrid files andDashboardUtils.SCHEMAnamed../core/…or../../../types, which resolve to nothing in an installed package, so the DataGrid'scomponentprop and the dashboard schema read asanyunderskipLibCheck: trueand failed to compile without it. They import@box-kite/coreby name now, and the package no longer carries declarations for the MCP server,create, the registry and Supabase, which nothing could import. - A
ChartContainerseries painted with aBox.extend()token rendered transparent.series={{ completed: 'ui-primary', started: 'ui-primary/35' }}type-checked and then declared--color-completed: ui-primary, which is not a colour, so every bar and legend swatch readingvar(--color-completed)drew nothing and nothing said why. The same gap was invarsandcssthemselves, which resolved the palette's tokens but not an app's. Both now resolve an app token, and its opacity form, exactly asfilldoes:var(--ui-primary)andcolor-mix(in oklab, var(--ui-primary) 35%, transparent). A series paintfillwould refuse is left out rather than written as text, with a development warning naming the nearest token (Did you mean "teal-500"?). A colour written as CSS was never a series paint, and still is not; it goes invars:vars={{ 'color-completed': 'hsl(var(--primary))' }}. - A hand-written
var(--brand)naming aBox.extend()variable named nothing unless something else used the token.fill="var(--brand)", aMiniDonutcolour, avarsentry and a variable defined in terms of another all wrote the reference without declaring--brandin:root, so the paint was transparent. Each one declares it now, the wayfill="brand"always did. - A
refon<Form>replaced the form's own, so every submit threwCannot read properties of null (reading 'elements'). React 19 passesrefas a prop, and Form handed it to its<form>in place of the one it reads its entries from; on React 18 the ref never arrived at all.<Form ref={formRef}>now reaches the element and the form still reads its entries, whether the ref is an object, a callback or inprops. Fourteen more components kept a ref of their own in the same way, and a caller'srefbroke each one on React 19:AccordionandRadioGrouplost their arrow keys,CalendarandTabs.Listtheir keyboard focus,Toasterits hotkey, andDialog,AlertDialog,Popover,MenuandMenu.Subnever opened;Tooltip,Slider,DashboardGridandTabs.Panelslost the element their own behaviour reads. Each one now shares the element between both refs, on React 18 as well as 19.