Changelog
What changed in @apollion-dsi/core (and its lockstep @apollion-dsi/tokens),
newest first. Plain summary — for the full technical detail of any release,
see the package CHANGELOG.md shipped inside the npm tarball.
7.2.0
Table paginates now — and the DataTable filter contract is spelled out
-
Navigable pagination on
Table. The pagination bar used to be display-only: it showed the range and a rows-per-page selector that did nothing. WireonPreviousPage/onNextPageand the previous/next buttons appear; passlinesPerPageValue+onLinesPerPageChangeand the rows-per-page selector becomes controlled. The bar stays stateless — you own the page index and the data slice, whether the slicing happens on the server or in memory:<Table initialPagination={start + 1} finalPagination={end} totalPagination={total} linesPerPage={[ { label: '10', value: 10 }, { label: '20', value: 20 }, ]} linesPerPageValue={pageSize} onLinesPerPageChange={setPageSize} onPreviousPage={() => setPage(page - 1)} onNextPage={() => setPage(page + 1)} > {/* rows */} </Table>The buttons' enabled state is derived from a numeric range (previous while
initialPagination > 1, next whilefinalPagination < totalPagination);canPreviousPage/canNextPageoverride it — useful when your API returns formatted counts like"1.234". New labelspreviousLabel/nextLabel(pt-BR defaults). Without the callbacks nothing changes: the bar renders exactly as before. -
DataTableper-column filters: thefilterValueshape is documented per variant (string[]for'select',[min?, max?]for'range',stringfor'text'; a cleared filter isundefined) — the contract you need for controlledcolumnFiltersand customfilterFns. The variant union is exported asFilterVariant, andDataTableLabelsgainsfilterRangeMin/filterRangeMaxso the range placeholders are localizable like every other filter string. -
Docs site. Every page now loads CSS from
<head>and scripts from the end of<body>, and the HTML minifier no longer breaks React hydration (the site was logging React #418 on every page). No API impact.
7.1.0
Every component is a direct Grid slot now — plus a flat Paper
-
area,alignSelfandjustifySelfon every component. Any component — aText, anInput, aRadio, aMeter,Image,Svg— can now claim a namedGridslot directly, with no wrapper:<Grid medias={{ xs: { areas: '"label" "field"' } }}> <Text area="label">Amount</Text> <Input area="field" /> </Grid>Previously only the containers and a few elements accepted
area; form controls and several leaves did not, so you had to wrap each one in aFlexjust to place it. The props are additive and do nothing unless the parent lays out with grid template areas — no change to existing screens. -
New
Paper flat. APaperwithflatrenders transparent and with no elevation (deep: 0) while keeping every other Paper ergonomic — a resting neutral surface you can animate to a solid raised one (a header that's transparent on mobile and a panel on desktop, a neutral→filled reveal). -
Linkaccepts JSX children. Pass rich content as children (it takes precedence overtext) —Linkis the right element for anything that navigates, keeping the external-link security and the guaranteed contrast that a bare<a>orText as="a"does not. -
Removed the internal
SurfaceFlex/SurfaceGrid. These were never a supported API (an internal engine detail that leaked through theflex/gridsubpaths). If you imported them: a flat surface is now<Paper flat>, and a surface with its own background/border is aPaperorCard. Layout stays onBox/Flex/Grid.
7.0.0
Layout and surface are now separate — plus a lighter Dropdown, a new Box, and per-viewport responsiveness
Box,FlexandGridare layout-only now. They carry spacing, size, geometry, the flex/grid mechanism and the responsive channels — and nothing else. Background, border and elevation (bgColor,border*,deep), textcolor,font*andmotionno longer type-check on them. ReadingFlex/Gridin your code now means "this is layout"; visual chrome lives on a surface. Migrating: move the background/border/elevation to aPaperorCard, text styling to aText, and animation to themotionprop on the animating component. Output is unchanged for valid code — only the types got stricter.- New
Boxcontainer. A plaindisplay: blockblock — the sanctioned replacement for a raw<div>and the old internalBase. Layout-only, with a polymorphicas. Reach forBoxfor a block,Flex/Gridfor layout,Paper/Cardfor a surface. See the Box guide. - New
viewportMediasresponsive channel. One style object per viewport breakpoint ({ md: { flexDirection: 'row' }, xl: { p: 'small' } }) — the viewport sibling of the container-querycqchannel, available on every container. Pure CSS media queries, SSR-safe. Usecqwhen a component should react to the space it sits in,viewportMediasfor genuine page-shell breakpoints. - Complete prop types on
GridandCard. Layout objects onGrid/Cardnow type the full surface (cq,viewportMedias,motion,flex,alignSelf, the responsive prefixes) — no more false "property does not exist" errors. New exportedFlexProps/GridProps/PaperProps/CardPropstypes carry the polymorphicas/forwardedAs, andCardtypes the anchor attributes (href,target,rel,download) for an interactiveas="a"tile. Dropdown,TooltipandPopoverload their positioning engine lazily. The@floating-uiengine (~60 KB gzipped) now loads on first open instead of shipping in your initial bundle — the eager entry for each drops to a couple of KB. Triggers stay eager, so there's no remount or flash; open, dismiss, focus trapping, the arrow and positioning are all unchanged.Dropdownanimates open by default. A fade + scale-in on open (themotionprop, default'scale'); setmotion="none"to turn it off.prefers-reduced-motionzeroes it automatically.
Breaking change — the engine left the public API. The design-system
engine is no longer importable. @apollion-dsi/core/factory (the
apollion.* primitives like apollion.div/apollion.input, styled,
shouldForwardProp and the raw *Factory/*Props bundles),
@apollion-dsi/core/containers/base (Base/BaseContainer) and
@apollion-dsi/core/containers/content are removed as published subpaths.
These were internal building blocks, public only by accident. Migrating:
compose the design-system components instead — apollion.div/BaseContainer →
Box/Flex/Grid; apollion.input → the DS Input;
visual chrome → Paper/Card. Your components' own prop types are
unaffected.
Major release. @apollion-dsi/tokens rides along at 7.0.0 (no breaking
change on the tokens side).
6.0.0
Animations are now built-in CSS — no more framer-motion
- Every component can animate on its own, with zero extra bundle weight.
A new
motionprop (fade,scale,slide-up/down/left/right,collapse,sheet,sheet-top,drawer-left/right) drives enter/exit transitions with plain CSS — no animation library ships in your bundle anymore.Modaland the toast/bannerNotificationnow animate through the same presets. - New
Sheetcomponent — a sliding modal for mobile-first flows: a bottom sheet by default, a side drawer viaplacement. Same focus-trap and Escape/close behavior asModal. - New motion tokens (
theme.motion,@apollion-dsi/core/themes/motion): a duration/easing scale and named intents (enter,exit,emphasis,settle, …) exposed as--apollion-motion-*CSS variables — reduce them globally withprefers-reduced-motion, or reach for them directly in your own styles. - Optional View Transitions wiring for animated theme/route cross-fades,
timed to the same tokens — opt in with
<GlobalStyle extend={viewTransitionStyles} />.
Breaking change — migrating from AnimatedContainer/AnimatedFlex:
the @apollion-dsi/core/containers/motion subpath is gone. Replace the
framer initial/animate/exit props with the motion preset that best
matches your choreography (see the Motion guide),
and pair it with the new useExitTransition hook if the element needs to
animate out before unmounting. If you passed animation props directly to
Notification, those are no longer accepted — it animates itself now.
Major release. @apollion-dsi/tokens rides along at 6.0.0 (no breaking
change on the tokens side).
5.10.0
Steps stays a stepper on mobile
- The step trail no longer turns into a progress bar on small screens. On
narrow layouts
Stepsused to swap to a progress bar with a "step X of Y" line. Now it stays the same trail — numbered circles, connectors, labels — just turned vertical: the circles stack, the connectors run down between them, and each label sits beside its circle. The consistency makes it far easier to follow. - It adapts to the space it's in, not the screen. The horizontal↔vertical
switch follows the width of the slot the component sits in (a container
query), so a
Stepsplaced in a narrow sidebar goes vertical even on a wide desktop. counterLabelis deprecated. There's no counter to localize anymore, so the prop is accepted but ignored. It will be removed in the next major — drop it when convenient.
Minor release. @apollion-dsi/tokens rides along at 5.10.0.
5.9.0
Dark mode that holds up on LCD phones
- Cards no longer vanish into the background in dark mode. On low-contrast LCD screens (e.g. iPhone 11), the page background and a card's background used to read as the same near-black — the card edge disappeared. Dark elevation now steps up more between the page and its cards, so surfaces stay distinct on those panels while looking the same as before on OLED and desktop.
- The boost is adaptive and safe. It only kicks in for near-black dark grounds (where the problem happens) and tapers off as your dark background gets lighter, so gray-anchored dark themes are unchanged and text contrast is never spent. Light mode is untouched.
Minor release. @apollion-dsi/tokens rides along at 5.9.0.
5.8.1
Mobile & console polish
- Date field. The
InputDatecalendar icon was redrawn, and the trigger icon now stays inside the field when the calendar popover opens. - Cards. A Card's
mediais full-bleed again — the image meets the card edges, with padding kept on the text below it. - Notifications on mobile. The title and message wrap and stack beside the icon instead of being squeezed onto one line.
- Range marks. The tick dots line up with the slider thumb.
- Cleaner console. The library now ships with the modern (automatic) JSX runtime, so React no longer logs an "outdated JSX transform" warning in your app.
Patch release — no API changes. @apollion-dsi/tokens rides along at 5.8.1.
5.8.0
Mobile-first, from the ground up
- Container queries. Components can now adapt to the width of their slot,
not just the viewport. Mark a wrapper with
containmentand use the newcqprop the same way you use responsive props today.CardandUploadCardare size containers out of the box, so the same component looks right in a narrow sidebar and in a full-width page — no viewport overrides. - Breakpoint tokens everywhere. The viewport breakpoint scale
(
sm 575 · md 767 · lg 990 · xl 1200, px) now ships as design tokens on every surface — JSON / DTCG / TS, CSS variables, and a Tailwindscreensscale — plus the new@apollion-dsi/core/themes/breakpointsexport. - Mobile is the default, not an afterthought. The
useMediaQueryflags now cover every width with no overlap (newisDesktop; the old 767px double-match is gone) and start on the mobile band before hydration. Layout components keep their navigation landmarks in the DOM on mobile. A typed auto-fitGrid(columns={{ autoFit: '250px' }}) wraps by container width, overflow-safe. container→pageShell. The page-shell prop was renamed and reads its max width fromtheme.layout.pageMaxWidth;containerstill works as a deprecated alias until the next major.
Fixes & polish
- DataTable horizontal scroll now spans the full row — borders and background no longer stop at the viewport edge, and the header stays pinned while the body scrolls.
- UploadCard lays the drop zone and file list side by side on a wide card and stacks them on a narrow one, and the list fills its panel (no stray column).
- Tabs on touch no longer show a highlight box or an underline on the selected tab — just the indicator bar.
- Tidied control spacing on Radio / Switch and removed a legacy flex-gap fallback; no visual change in supported browsers.
5.7.0
Dark mode is now an engine
- Dark and light are two modes of one theme.
ApollionProvidergainsmode/defaultMode(light/dark/system), SSR-safeinitialMode, persistence (localStorage/ cookie) and document sync — flip withsetMode()and every color switches with no re-render and no flash (built on the CSSlight-dark()function). An orthogonala11yaxis adds grayscale / high-contrast / colorblind palettes. New subpathsthemes/mode(SSR script, cookie readers, storage adapters) andthemes/ground. Every surface publishes readable text inks against its own background automatically. The live flip needs a Baseline-2024 browser; older engines render the light side. - Surface ladder:
theme.colors.surface/ink/edge/wash— grounds, text hierarchy, lines and interaction washes that clear WCAG AA and APCA by construction in both modes. Every built-in component sits on the ladder. - The previous
useSystemPreference,themeMode/onThemeModeChangeandtoggleThemestill work — deprecated in favor of the new props.
New components
Option— a segmented value selector (grey pill track, raised selected cell) for a compact exclusive choice: buy / sell, 25 / 50 / 75 %.Steps— a step trail (numbered badge, connector, label) for multi-step flows; collapses to a progress bar with "step X of Y" on mobile.Divider— a standalone rule: horizontal or vertical, tone from the edge ladder or any color, plus an "or"-style labeled variant.IconText— an inert icon + text pair (not a button, not a label), with alignment and spacing tokens; type and color cascade to both parts.
Theming
typeWeightorigin (light/regular/stronger) oncreateTheme/ApollionProvider— shift the whole weight ladder from one prop instead of remapping the numbers by hand.theme.component.textsets the default weight / size / color of a bare<Text>.Button color="neutral"— a quiet chrome palette derived from the neutral ramp — and a newghostbutton variant (bare, wash on hover) for icon clusters.
Components
Checkbox,RadioandSwitchtake acolorand now default to the brandprimary(was a fixed blue); a locked-on switch reads quieter than an interactive one.Cardis a Paper-like surface with named grid slots (title / content / action) that keeps the footer pinned, plus aninteractivehover lift.InputCurrencygains a ticket layout (suffix + attached percent chips);Spinnera determinatecountdownring;Textatickflash for live values;Field's hint line no longer shifts when an error appears.- Polish across the set: the
Tabsselected indicator, single-selectList(exclusive), a full-bleedNotification type="page"banner, the completeFlex/Gridalignment surface,DescriptionListpair spacing, and a chrome-freeLink.Button.
Accessibility
- Every surface, ink, edge and wash is contrast-checked (WCAG AA + APCA) by construction in both modes; new components ship axe-clean.
5.6.0
Features
- One-palette dark mode: pass a single light-mode
colorsset toApollionProviderand both the light and dark themes are derived automatically — no more copying the palette and inverting four fields by hand. The canonical-dark factory is now published astoDarkColorsfrom@apollion-dsi/core/themes/colors. An explicittheme/lightTheme/darkThemestill takes precedence when you need a non-canonical dark theme.
5.5.0
Features
- Table components can now be localized: the pagination and filter strings on
DataTableandTablePaginationaccept override props, so you can render them in any language (defaults are unchanged).
Accessibility
- Button
outlinedandlinkedtext now meets WCAG AA contrast against the page surface on any palette — the same fix carries toTabs,CalendarandTable. Text contrast is now checked automatically on every component.
5.4.0
Features
- Dark mode emits real token values: dark palettes are derived by construction instead of mirroring the light set, so exported themes and CSS carry true dark colors.
- A Tailwind preset ships alongside the CSS tokens, and per-component size scales can be tuned through the theme.
colorandbgColoraccept raw CSS colors (#hex,rgb(),oklch(),var(--…)) directly, for data-driven tints withoutstyleescapes.
Accessibility
Calendarday-grid text was raised to AA contrast, and every component now passes the semantic accessibility sweep.Avatartakes analtprop and exposes proper image semantics.
Bug fixes
- Dropdown and select menus no longer appear behind sticky table headers.
- Server-side rendering produces stable class names, fixing hydration so re-theming and interactive controls work on server-rendered pages.
Polish
- New changelog page and a version badge in the site header.
5.3.0
Features
- Every color palette now ships a guaranteed-readable accent for tonal surfaces: chips and badges pair background and ink with WCAG AA contrast by construction, on any seed — no more manual inversion on high-luminance themes.
5.2.0
Performance
- Published class names are now short hashes. Server-rendered HTML (static pages, reports, e-mails) gets meaningfully smaller since every node repeats its classes.
5.1.0
Accessibility
Notificationbecame a live region — toasts are now announced by screen readers, with alert semantics for the danger variant.Modalgained dialog semantics, focus trap,Escapeto close and focus return.Spinnerannounces itself with an accessible status label.Tabsfollows the ARIA Tabs pattern: proper roles, arrow-key navigation with roving tabindex,Home/Endsupport.
Performance
- The color engine no longer depends on an external color library at runtime — a bit-exact internal port cut key bundles roughly in half (button 72.7 → 38.1 KB, flex 65.6 → 31.1 KB) with zero visual change.
5.0.0
Breaking
- Animation containers moved to their own subpath
(
@apollion-dsi/core/containers/motion) so the animation runtime stays out of your bundle unless you animate. - Icons are now tree-shakeable: import the icon and pass it via
icon(<Icon icon={trash} />); the stringnameprop and the global icon registry were removed. Importing one icon costs ~0.2 KB instead of ~28 KB. Avatar.icontakes an icon element instead of a name string.
Performance
- Core layout bundles shrank by about two thirds (e.g. flex ~189 → ~65 KB); the animation library left the initial bundle of 36 of 41 subpaths.
4.12.1
Bug fixes
- Disabled and muted colors are now mode-aware semantic tokens — soft fills no longer collapse on dark themes.
4.12.0
Features
- Hover and pressed states are guaranteed to be perceptible on any theme: the engine re-derives them when a custom palette would produce an invisible shift. Compliant themes stay byte-identical.
- Per-slot palette overrides: pass an explicit partial palette
(
{ base, action, … }) when you need exact control; omitted steps still derive automatically.
Bug fixes
- Contained
Buttonlabel color no longer depends on stylesheet insertion order (it could render invisible in dev servers).
4.11.0
Features
readableprop: any text color can opt into automatic AA legibility against the page surface, preserving hue.transformjoined the layout props (with responsive variants).Meter— new data-display component for static measurements: single value, band, dual-fill comparison with threshold ticks.Labelgainedinverted(strong background + contrast-derived ink).legibility="on-photo"preset — readable text over photographic backgrounds.DescriptionListgaineddividers; high neutral ramp indices used as text are theme-legible by default on dark themes.- New readable-text layer: derived AA ink per palette, also emitted as
tx.*CSS variables by the tokens package.
Bug fixes
Text:childrennow wins overtextwhen both are passed, as documented.Flex gap={0}is no longer discarded.ProgressBargained native ARIA and forwards native props to the DOM.
4.10.0
Features
- Prose links are always distinguishable inside running text (underline engine, WCAG 1.4.1); quiet nav links restore their underline on hover/focus.
4.9.x
Features
- New
Select— a token-styled native<select>that works with JavaScript disabled (pure SSG), alongside the richerInputSelect. - Accessibility palette presets: grayscale, high-contrast (AAA) and
colorblind-safe, ready for
createTheme.
4.8.0
Features
Texttypes its HTML attributes from the chosenvariant, not only fromas— e.g.variant="blockquote"acceptscitedirectly.
Bug fixes
Linkmerges the consumer'srelon external URLs instead of overwriting it.
4.7.0
Features
Textaccepts the HTML attributes of the tag chosen viaas.
Bug fixes
- Contrast engine picks the highest-contrast text on mid-tone backgrounds, guaranteeing AA everywhere.
4.6.x
Bug fixes
styled-componentsbecame a peer dependency — eliminates the double-instance crash when the app resolves a different patch version.Image/Svgemit nativewidth/heightattributes (prevents layout shift).
4.5.x
Features
- Typography joined the density axis: the same
dimensionknob that drives spacing now scales type, on a fixed 16px root.fontSizetokens becameremstrings (with a px mirror for layout math).
4.4.0
Features
- New
Switchcomponent — on/off toggle with keyboard support, size axis and the same anatomy asCheckbox/Radio.
4.3.x
Features
- Dark-mode-stable on-colors for solid surfaces and a
readableColorhelper that adjusts luminance while preserving hue;Linktargets AA with margin on any nearby surface.
4.2.0
Features
- Native dark mode in
ApollionProvider: light/dark theme pair, controlled mode, system preference watcher anduseApollionTheme(). Checkbox/Radiostring labels render with DS typography; newlabelProps.
Bug fixes
- DataTable empty state centering, pagination scroll region, Calendar today+selected contrast.
4.1.0
Features
- New
DescriptionListcomponent (semantic key/value list). Fieldhint props acceptReactNode— inline hint affordances without sibling workarounds.- Tokens output aligned with the Design Tokens Format Module (structured OKLch color values, composite tokens, reference graph).
4.0.0
Breaking
- Root barrel removed — import from granular subpaths
(
@apollion-dsi/core/elements/button). - Palette derivation moved to the OKLch color space (perceptually uniform
ramps; the
oppositehue rotation changed accordingly). - New
dimensiondensity axis on the provider (compact/normal/spacious).