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. Wire onPreviousPage / onNextPage and the previous/next buttons appear; pass linesPerPageValue + onLinesPerPageChange and 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 while finalPagination < totalPagination); canPreviousPage / canNextPage override it — useful when your API returns formatted counts like "1.234". New labels previousLabel / nextLabel (pt-BR defaults). Without the callbacks nothing changes: the bar renders exactly as before.

  • DataTable per-column filters: the filterValue shape is documented per variant (string[] for 'select', [min?, max?] for 'range', string for 'text'; a cleared filter is undefined) — the contract you need for controlled columnFilters and custom filterFns. The variant union is exported as FilterVariant, and DataTableLabels gains filterRangeMin / filterRangeMax so 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, alignSelf and justifySelf on every component. Any component — a Text, an Input, a Radio, a Meter, Image, Svg — can now claim a named Grid slot 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 a Flex just 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. A Paper with flat renders 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).

  • Link accepts JSX children. Pass rich content as children (it takes precedence over text) — Link is the right element for anything that navigates, keeping the external-link security and the guaranteed contrast that a bare <a> or Text as="a" does not.

  • Removed the internal SurfaceFlex / SurfaceGrid. These were never a supported API (an internal engine detail that leaked through the flex/grid subpaths). If you imported them: a flat surface is now <Paper flat>, and a surface with its own background/border is a Paper or Card. Layout stays on Box/Flex/Grid.

7.0.0

Layout and surface are now separate — plus a lighter Dropdown, a new Box, and per-viewport responsiveness

  • Box, Flex and Grid are 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), text color, font* and motion no longer type-check on them. Reading Flex/Grid in your code now means "this is layout"; visual chrome lives on a surface. Migrating: move the background/border/elevation to a Paper or Card, text styling to a Text, and animation to the motion prop on the animating component. Output is unchanged for valid code — only the types got stricter.
  • New Box container. A plain display: block block — the sanctioned replacement for a raw <div> and the old internal Base. Layout-only, with a polymorphic as. Reach for Box for a block, Flex/Grid for layout, Paper/Card for a surface. See the Box guide.
  • New viewportMedias responsive channel. One style object per viewport breakpoint ({ md: { flexDirection: 'row' }, xl: { p: 'small' } }) — the viewport sibling of the container-query cq channel, available on every container. Pure CSS media queries, SSR-safe. Use cq when a component should react to the space it sits in, viewportMedias for genuine page-shell breakpoints.
  • Complete prop types on Grid and Card. Layout objects on Grid/Card now type the full surface (cq, viewportMedias, motion, flex, alignSelf, the responsive prefixes) — no more false "property does not exist" errors. New exported FlexProps / GridProps / PaperProps / CardProps types carry the polymorphic as / forwardedAs, and Card types the anchor attributes (href, target, rel, download) for an interactive as="a" tile.
  • Dropdown, Tooltip and Popover load their positioning engine lazily. The @floating-ui engine (~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.
  • Dropdown animates open by default. A fade + scale-in on open (the motion prop, default 'scale'); set motion="none" to turn it off. prefers-reduced-motion zeroes 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/BaseContainerBox/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 motion prop (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. Modal and the toast/banner Notification now animate through the same presets.
  • New Sheet component — a sliding modal for mobile-first flows: a bottom sheet by default, a side drawer via placement. Same focus-trap and Escape/close behavior as Modal.
  • 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 with prefers-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 Steps used 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 Steps placed in a narrow sidebar goes vertical even on a wide desktop.
  • counterLabel is 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 InputDate calendar icon was redrawn, and the trigger icon now stays inside the field when the calendar popover opens.
  • Cards. A Card's media is 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 containment and use the new cq prop the same way you use responsive props today. Card and UploadCard are 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 Tailwind screens scale — plus the new @apollion-dsi/core/themes/breakpoints export.
  • Mobile is the default, not an afterthought. The useMediaQuery flags now cover every width with no overlap (new isDesktop; 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-fit Grid (columns={{ autoFit: '250px' }}) wraps by container width, overflow-safe.
  • containerpageShell. The page-shell prop was renamed and reads its max width from theme.layout.pageMaxWidth; container still 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. ApollionProvider gains mode / defaultMode (light / dark / system), SSR-safe initialMode, persistence (localStorage / cookie) and document sync — flip with setMode() and every color switches with no re-render and no flash (built on the CSS light-dark() function). An orthogonal a11y axis adds grayscale / high-contrast / colorblind palettes. New subpaths themes/mode (SSR script, cookie readers, storage adapters) and themes/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 / onThemeModeChange and toggleTheme still 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

  • typeWeight origin (light / regular / stronger) on createTheme / ApollionProvider — shift the whole weight ladder from one prop instead of remapping the numbers by hand.
  • theme.component.text sets the default weight / size / color of a bare <Text>.
  • Button color="neutral" — a quiet chrome palette derived from the neutral ramp — and a new ghost button variant (bare, wash on hover) for icon clusters.

Components

  • Checkbox, Radio and Switch take a color and now default to the brand primary (was a fixed blue); a locked-on switch reads quieter than an interactive one.
  • Card is a Paper-like surface with named grid slots (title / content / action) that keeps the footer pinned, plus an interactive hover lift.
  • InputCurrency gains a ticket layout (suffix + attached percent chips); Spinner a determinate countdown ring; Text a tick flash for live values; Field's hint line no longer shifts when an error appears.
  • Polish across the set: the Tabs selected indicator, single-select List (exclusive), a full-bleed Notification type="page" banner, the complete Flex / Grid alignment surface, DescriptionList pair spacing, and a chrome-free Link.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 colors set to ApollionProvider and 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 as toDarkColors from @apollion-dsi/core/themes/colors. An explicit theme / lightTheme / darkTheme still 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 DataTable and TablePagination accept override props, so you can render them in any language (defaults are unchanged).

Accessibility

  • Button outlined and linked text now meets WCAG AA contrast against the page surface on any palette — the same fix carries to Tabs, Calendar and Table. 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.
  • color and bgColor accept raw CSS colors (#hex, rgb(), oklch(), var(--…)) directly, for data-driven tints without style escapes.

Accessibility

  • Calendar day-grid text was raised to AA contrast, and every component now passes the semantic accessibility sweep.
  • Avatar takes an alt prop 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

  • Notification became a live region — toasts are now announced by screen readers, with alert semantics for the danger variant.
  • Modal gained dialog semantics, focus trap, Escape to close and focus return.
  • Spinner announces itself with an accessible status label.
  • Tabs follows the ARIA Tabs pattern: proper roles, arrow-key navigation with roving tabindex, Home/End support.

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 string name prop and the global icon registry were removed. Importing one icon costs ~0.2 KB instead of ~28 KB.
  • Avatar.icon takes 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 Button label color no longer depends on stylesheet insertion order (it could render invisible in dev servers).

4.11.0

Features

  • readable prop: any text color can opt into automatic AA legibility against the page surface, preserving hue.
  • transform joined the layout props (with responsive variants).
  • Meter — new data-display component for static measurements: single value, band, dual-fill comparison with threshold ticks.
  • Label gained inverted (strong background + contrast-derived ink).
  • legibility="on-photo" preset — readable text over photographic backgrounds.
  • DescriptionList gained dividers; 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: children now wins over text when both are passed, as documented.
  • Flex gap={0} is no longer discarded.
  • ProgressBar gained 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 richer InputSelect.
  • Accessibility palette presets: grayscale, high-contrast (AAA) and colorblind-safe, ready for createTheme.

4.8.0

Features

  • Text types its HTML attributes from the chosen variant, not only from as — e.g. variant="blockquote" accepts cite directly.

Bug fixes

  • Link merges the consumer's rel on external URLs instead of overwriting it.

4.7.0

Features

  • Text accepts the HTML attributes of the tag chosen via as.

Bug fixes

  • Contrast engine picks the highest-contrast text on mid-tone backgrounds, guaranteeing AA everywhere.

4.6.x

Bug fixes

  • styled-components became a peer dependency — eliminates the double-instance crash when the app resolves a different patch version.
  • Image/Svg emit native width/height attributes (prevents layout shift).

4.5.x

Features

  • Typography joined the density axis: the same dimension knob that drives spacing now scales type, on a fixed 16px root. fontSize tokens became rem strings (with a px mirror for layout math).

4.4.0

Features

  • New Switch component — on/off toggle with keyboard support, size axis and the same anatomy as Checkbox/Radio.

4.3.x

Features

  • Dark-mode-stable on-colors for solid surfaces and a readableColor helper that adjusts luminance while preserving hue; Link targets 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 and useApollionTheme().
  • Checkbox/Radio string labels render with DS typography; new labelProps.

Bug fixes

  • DataTable empty state centering, pagination scroll region, Calendar today+selected contrast.

4.1.0

Features

  • New DescriptionList component (semantic key/value list).
  • Field hint props accept ReactNode — 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 opposite hue rotation changed accordingly).
  • New dimension density axis on the provider (compact / normal / spacious).