Ещё не переведено
Эта страница пока недоступна на русском, поэтому показана английская версия.
Изменения
Заметки о выпусках этого приложения и каждого установленного пакета Ab.
ab-elements-app
ab-elements-app 0.2.29
0.2.29 (2026-11-12)
- 📝 Write the theming, icons and fonts, and layout-rule guides against the published package APIs, with the layout figures in
.github/layout/ - ✨ Add
/[locale]/changelog, built from the app changelog and each installed package changelog, as plain Markdown with stable anchors - 🔒 Fail the build when an installed package version, or the app's own version, has no released changelog entry (
AB_CHANGELOG_GATE=warnis review-only and stays off in CI) - ⬆️ Use ab-nextjs-core 0.2.4, ab-nextjs-theme 0.3.10, ab-nextjs-fonts 0.2.8, ab-nextjs-components 0.7.1, ab-nextjs-animations 0.2.6, ab-nextjs-icons 0.2.8 and ab-nextjs-hooks 0.1.8, with an exact release-age pin for each that expires 24h after its publish
- ✅ Test the changelog parser and the three guides plus
/changelog - 📝 Name the theme, fonts and icons versions in the guide callouts from the installed package, not a typed number
- 💄 Show gitmoji shortcodes as emoji on the changelog page, from a fixed table, and leave every other shortcode as text
- 🐛 Take Home's What's new titles and dates from the latest released changelog entries
- 🐛 Parse a changelog
:slug:before emphasis, so:white_check_mark:is not an italic "check" - 🎨 Retint the layout-rule figures to the bronze theme, with sage only on the small scrolls caption
- 📱 Let layout-rule figures scroll inside the article on a phone, so captions stay at least 12px
- 🌐 Translate the top-nav Packages and Guides labels in French, Spanish and Russian
- 🔒 Keep changelog shortcode lookup off the prototype chain, and send every href through the same gate
0.2.28 (2026-11-12)
- ✨ Add API props tables extracted at build time with ts-morph from the published declarations, and render them with the packaged AbPropsTable on the drawer, layout-slot and scroll-spy pages
- 📝 Record a symbol inventory of what those pages cover, what stays deferred, and which names are not a public import
- ⬆️ Use ab-nextjs-components 0.7.0
- ✅ Test that ArrowRight scrolls each props table at 390px after the scroll settles, and that the document does not
- 🔧 Drop the expired components 0.7.0 release-age pin
0.2.27 (2026-11-06)
- 📝 Write the getting started pages: Introduction, Installation (pnpm, npm, yarn and bun) and Quick start, using the published layout APIs
- 📝 Write the eight package overviews (fonts, icons, animations, theme, hooks, core, components and i18n) against the published package APIs
- 📝 Keep the introduction in user-facing language and point exact colours and typefaces at the Theme page
- ♻️ Order the package pager like the sidebar: Fonts, Icons, Animations, Theme, Hooks, Core, Components, i18n
- ✅ Test the layout rules on every docs page, and that the introduction stays free of design-spec tokens and the pager follows the sidebar
0.2.26 (2026-11-04)
- ✨ Add live Preview / Code tabs to docs examples: an MDX
<Example>renders the real package components (packaged AbPreviewCode), and its Code tab shows the exact same source, highlighted by Shiki at build time (one source per example, no eval, no runtime code strings, no iframe) - ✨ Show the packaged preview toolbar on every example: a light/dark toggle for that preview only and a reload that remounts it, labelled in all four locales
- 🔒 Check every live example at build time: package components and literal props only, no handlers, spreads, expressions or raw HTML, and URL props limited to
/path(not//),#hash,https:andmailto:(anything else fails the build) - 🛡️ Add
pnpm check:no-eval(also in CI): the client bundle must contain noevalornew Function, so the site keeps working under a CSP without'unsafe-eval' - ♿ Keep one tab stop per code block (the code wrapper; arrow keys scroll long lines) and no separate tab panel stop
- 📝 Add live examples (buttons, chips and pills, a keyboard hint, a callout) to the Components page
- 📈 Audit
/docs/packages/componentsin Lighthouse and Lighthouse CI too - ⬆️ Upgrade ab-nextjs-components to 0.6.0, with an exact release-age pin that expires 24h after its publish, and drop the 0.5.0 pin
- ✅ Test the live previews in every locale and theme: the tabs, the keyboard and tab order, both panels, the code matching the preview, the toolbar, arrow-key scrolling, the copy button at 390px and no CSP eval violation
0.2.25 (2026-11-04)
- ✨ Add the docs page template: chips under each title (section, package, Client or Server Component, status) and Edit this page, Report an issue and View source links in the aside and the outline drawer, in all four locales
- 👷 Run Lighthouse CI in warn mode on
/,/docs/installationand/fr/docs/quick-start(mobile and desktop, every assertion a warning) - 🐛 Rename the Lighthouse CI preset and port variables to
AB_LH_*, so lhci stops reading them as flags - ⬆️ Upgrade ab-nextjs-components to 0.4.2, then to 0.5.0 for one active sidebar item (Introduction no longer lights up next to the current page), with an exact release-age pin that expires 24h after its publish
- 🔥 Remove personal names from comments and docs
- ✅ Test the docs page template in every locale and theme (breadcrumbs, chips, TOC and scroll spy, the outline drawer below 1180px, the links)
- ✅ Test that exactly one sidebar and nav drawer item is active on
/docsand/docs/installationin every locale
0.2.24 (2026-11-03)
- ➕ Add Fumadocs MDX, fumadocs-core and zod for the docs pipeline
- 📝 Add the first docs content in four locales
- ✨ Render the MDX docs pages in the shell
- ♻️ Render the docs with the packaged code blocks, callouts, tabs and pager
- 🐛 Let the picked theme set the color-scheme and keep the crumb a label at 768px
- 💄 Highlight the code with github-dark on the dark code surface
- ✨ Link the Docs crumb and highlight with both Shiki themes
- ⬆️ Upgrade to theme 0.3.8 and components 0.4.0, then to theme 0.3.9 and components 0.4.1
- ✅ Test the docs pages in all four locales
- ✅ Load the docs source in unit tests and cover the docs sitemap
0.2.23 (2026-11-01)
- ✅ Test the layout rules on Home, the 404 and the Welcome at 390, 768, 1180, 1280 and 1920px in light and dark: the document never scrolls, only the panes scroll and they scroll independently, empty slots are 0px, the aside is a pane from 1180px and the right drawer below it, the tablet
<<toggle opens it (Escape closes it and focus returns), and the scroll spy follows main - ✅ Test touch on phones: 44px tap targets, edge swipes that open the nav and outline drawers, scrim taps and swipes that close them, and every drawer staying inside the app with focus back on its opener
- ✅ Test accessibility: axe at every width in both themes and with each drawer open, one
h1, named landmarks, the skip link first and no Tab stop in a hidden pane - 📈 Add
pnpm lighthouse(andlighthouse:strict): Performance, Accessibility, Best Practices and SEO for/,/frand the 404 on the mobile and desktop presets, the median of 3 runs against the plan's targets - 📱 Use the packaged mobile header search slot on the 404 (search · theme, the shared theme glyph)
- ♿ Name the Home aside landmark after its outline
- 🗃️ Register the
brightness_autoicon, so the Settings drawer never falls back to the Material Symbols font - ⬆️ Pin the published ab-nextjs-components 0.3.2, ab-nextjs-icons 0.2.7 & ab-nextjs-fonts 0.2.7 (Inter now swaps in, so the Home text paints at once), with exact release-age pins that expire 24h after each publish, and drop the expired pins
0.2.22 (2026-10-30)
- ✨ Build the 404 page inside the docs shell in en, fr, es & ru: the packaged
AbErrorHero(gradient 404, link_off badge, faint dot grid), the large search field, Back to home · Browse docs, "Did you mean …?" on every width, and Suggested rows (mobile) or cards with an icon tile, bold title & arrow (from 640px) - 📑 Show Popular pages in the aside from 1180px (
AbToclinks variant) with Report a broken link · Open an issue - 📱 Give the 404 mobile header a Search pill and a theme icon, and stack the two actions full width below 768px so longer labels never wrap
- 🐛 Serve every unknown URL (including
/foo.bar, no more 500) a real 404 status in the visitor's locale, withnoindex - 🌐 Localize AbButton links through AbLinkProvider (no more server-computed hrefs)
- 🗃️ Register the
link_offandsettingsicons, so they never fall back to the Material Symbols font - ⬆️ Pin the published ab-nextjs-components 0.3.1 & ab-nextjs-icons 0.2.6, with exact release-age pins that expire 24h after each publish
- ✅ Test the 404 in every locale (status, h1, localized links, mobile rows, global 404) and run axe on it at every width in both themes
0.2.21 (2026-10-30)
- 🏗️ 📱 Rebuild the Welcome on the packaged core panes: header · main · aside, with the counter in main, one scroller below 1180px (header, counter, playground and text scroll together) and the playground pane from 1180px
- ✨ Show the packaged v6 Live Playground scenes (
AbPlaygroundScene, compact below 768px and full from 768px, no JS) with the abElements logo, code-name captions and the v6 page, pane and card surfaces - 🌐 Add the i18n slide "Every language, built in" (10 slides now; the last slide moves to s10) in en, fr, es & ru
- 📱 Open the playground in a right drawer below 768px from a "Show playground" button (Esc, backdrop tap & swipe close it, focus returns)
- 📌 Pin the slide dots & arrows to the bottom of main at every width (a named "Slide controls" main bar, never an app footer); Skip stays in the top bar
- 🎨 Match the v6 call to action: a bronze rounded Get Started and a card-style Continue with GitHub (52px, 56px from 1180px)
- ♿ Put the top bar in a banner landmark and make each slide title the page's single
h1(no axe issues at any width) - ⬆️ Pin the published ab-nextjs-components 0.2.3, ab-nextjs-core 0.2.3, ab-nextjs-theme 0.3.7 & ab-nextjs-animations 0.2.5, with exact release-age pins that expire 24h after each publish, and drop the expired pins
- ✅ Test the 10 slides, the playground drawer (dialog, Esc, backdrop tap, real-touch swipe, hit-testing, focus return) and the packaged scenes, and refresh the Welcome visual baselines
0.2.20 (2026-10-21)
- ✨ 📱 Build the docs shell from packaged pieces only: the compact app bar, the sidebar (rail, version switcher, profile button), the bottom nav (Home · Packages · Search · Profile) and the 768 / 1180 / 1920 panes, where only the main pane scrolls
- ✨ Build Home with the packaged package cards & previews, Guides, What's new and a scroll-spied "On this page" aside with the "New" promo
- 🗃️ Add the drawers: the mobile header (logo · language · theme), Settings (theme & language), the nav drawer (left edge swipe), the search drawer (components & hooks grouped by package, "Did you mean") and the outline drawer (right edge swipe below 1180, or the tablet
<<) - ✨ Share one
ab-pminstall key across the app & migrate the Welcome'sab-welcome-pm - 🌐 Add the Shell & Home messages in en, fr, es & ru, including the drawer and Components preview labels
- ♻️ Use the packaged
abThemeScriptinstead of the app's own theme script - 🎨 Load Mulish & Roboto Mono and set the Home pane widths & surfaces as token overrides
- ⬆️ Pin the published ab-nextjs-theme 0.3.6, ab-nextjs-core ^0.2.2 & ab-nextjs-components 0.2.2 (plus hooks 0.1.7, icons 0.2.4 & fonts 0.2.6), with exact release-age pins that expire 24h after each publish
- ✅ Test the docs shell, the shell data & messages, the theme script, the shell icons and the release-age pins
0.2.19 (2026-10-16)
- 🌐 Polish & refine the Welcome translations in fr, es & ru
- ♿ Make long Welcome slides a focusable, keyboard-scrollable region
- ➕ Add @axe-core/playwright for the accessibility e2e tests
- ✅ Test the Welcome messages & the full gate table
- ✅ Add the Welcome e2e tests: gate (incl. Get Started without JavaScript), slides (incl. swipe at 390px), Splash shown once, theme, motion, axe & Cyrillic
- 🍱 Add the Welcome visual snapshot baselines (s01 & s09; laptop & mobile, light & dark)
- ⬆️ Bump ab-nextjs-theme 0.3.3 & ab-nextjs-components 0.1.12: the globe menu can be clicked with a mouse again (scoped layout
mainz-index), and theAbInstallSnippettabs pass AA in every state - ✅ Drop the globe menu & AbInstallSnippet test allowances (no axe exceptions left)
- 💄 Use the filled (solid bronze) AbButton for the Welcome Get Started
- Deferred: WebKit e2e, the full 72+ visual set & tablet frame, Lighthouse / JS budget, the HTTPS (
Secure) cookie check, and a CI e2e job (0.2.20+)
0.2.18 (2026-10-15)
- ✨ Add the Welcome v6 walkthrough at
/[locale]/welcome: 9 slides built onAbCarousel&AbFlowDiagram, with Skip to the last slide and a Get Started action - 🛂 Gate the first home visit behind the Welcome, remembered for one year (
AB_APP_COOKIE_MAX_AGE.oneYear); direct links, bots & browsers withoutsec-fetch-destnever see it - 🌐 Add the Welcome messages (en, fr, es, ru)
- 💄 Keep the system theme mode in the no-flash theme script
- 💄 Keep the Welcome diagrams clear of their header, never clip a slide's top, and show Skip as plain bronze text
- 🔥 Remove the app-side theme workarounds now fixed in ab-nextjs-theme 0.3.2
- ⬆️ Bump ab-nextjs-theme 0.3.2, ab-nextjs-components 0.1.11 & the other Ab packages for the Welcome
- ✅ Test the Welcome gate, the Get Started action, the slides, messages & scenes
- 🍱 Swap the README screenshots to the Welcome v6 (laptop & mobile)
0.2.17 (2026-10-14)
- ✨ Add the Splash screen (light & dark), shown on the first visit only
- ♻️ Make the Splash a thin wrapper over
ab-nextjs-components/ab-splash, with the gate built from the i18n config - ⬆️ Bump ab-nextjs-components 0.1.9, ab-nextjs-hooks 0.1.5 & ab-nextjs-animations 0.2.3
- ✅ Test the Splash gate & timing (skips
/en, bots & webdriver, and second visits) - ✏️ Move the global styles comment back above
globals.css
0.2.16 (2026-10-14)
0.2.15 (2026-10-14)
- 🔒 Add baseline security headers: HSTS, nosniff, Referrer-Policy, Permissions-Policy, COOP,
X-Frame-Options: DENY& a report-only CSP; dropX-Powered-By - ✅ Test the security headers with Vitest & Playwright (new
test:e2escript) - 💡 Update the copyright year to 2026 in the license headers & the LICENSE
0.2.14 (2026-10-14)
0.2.13 (2026-10-08)
0.2.12 (2026-10-08)
0.2.11 (2026-10-06)
0.2.10 (2026-10-06)
0.2.9 (2026-10-06)
0.2.8 (2026-10-05)
0.2.7 (2026-10-05)
0.2.6 (2026-10-03)
0.2.5 (2026-10-03)
0.2.4 (2026-10-03)
0.2.3 (2026-10-03)
0.2.2 (2026-10-03)
0.2.1 (2026-10-03)
0.2.0 (2025-03-09)
0.1.5 (2024-06-09)
0.1.4 (2024-06-07)
0.1.3 (2024-06-07)
0.1.2 (2024-06-07)
0.1.1 (2024-06-07)
Fonts
ab-nextjs-fonts 0.2.8
0.2.8 (2026-11-12)
- Normalize the changelog format and backfill missing entries.
0.2.7 (2026-11-01)
- ⚡
font-display: swapon every@font-face(Inter, Quicksand, Roboto, Zilla Slab; Mulish + Roboto Mono already had it), test-guarded for every family - 📦 Inter woff2: the 8 shipped static weights (200–900) now load
woff2first, with the TTF kept as fallback. Same glyphs (2505 code points) and weights, converted losslessly with fontTools. Regular is 101 KB (was 310 KB); all 8 weights 0.86 MB, was 2.51 MB (−66%)
0.2.6 (2026-10-20)
- ⌨️ Roboto Mono (G30, D29a): new
roboto-mono/family, the abElements code font. Variable weight 100–700, normal + italic, Latin + Cyrillic (same coverage as Mulish), woff2 first (≈105 / 113 KB) with the variable TTFs as fallback,font-display: swap - ⚖️ Upstream google/fonts
ofl/robotomonofiles with their SIL OFL 1.1 licence (roboto-mono/OFL.txt) - 📦
robotoMonoStylesexport (font-robotomono-light…-bold), README section - 🔧 npm author email is abrahamukachi@gmail.com
- Tests: faces, files exist + published, licence, Latin + Cyrillic coverage, export ↔ CSS classes
0.2.5 (2026-10-14)
- Mulish titles (§8 Q6): the plain
'Mulish'family is now the variable font (font-weight: 200 1000, normal + italic), sofont-weight: 700/800render real Bold/ExtraBold instead of faux bold. Includes Cyrillic (220/256 U+04xx) for Russian titles - woff2:
Mulish-VariableFont_wght.woff2(77 KB, was 210 KB TTF) + italic (83 KB), served first; variable TTF kept as fallback font-display: swapon every Mulish face- Tests: variable range, swap, files exist, Cyrillic coverage
- Packaging: the 23 static TTFs no CSS references are no longer published (every referenced face still ships; test-guarded)
- Tooling:
typecheckscript (tsconfig.typecheck.json)
0.2.4 (2026-10-03)
- Publish to npm automatically from GitHub Actions with Trusted Publishing (OIDC + provenance, no NPM_TOKEN)
- Ship only package files via
files;nextpeer is now^16.3.4
0.2.3 (2026-09-23)
- Maintenance release; see the compare link.
0.2.2 (2025-09-17)
- Maintenance release; see the compare link.
0.2.1 (2024-06-10)
- Maintenance release; see the compare link.
0.2.0 (2024-06-10)
- Maintenance release; see the compare link.
0.1.10 (2024-06-10)
- Maintenance release; see the compare link.
0.1.9 (2024-06-10)
- Maintenance release; see the compare link.
0.1.8 (2024-06-10)
- Maintenance release; see the compare link.
0.1.7 (2024-06-10)
- Maintenance release; see the compare link.
0.1.6 (2024-06-09)
- Maintenance release; see the compare link.
0.1.5 (2024-06-09)
- Maintenance release; see the compare link.
0.1.4 (2024-06-09)
- Maintenance release; see the compare link.
0.1.3 (2024-06-09)
- Maintenance release; see the compare link.
0.1.2 (2024-06-09)
- Maintenance release; see the compare link.
0.1.1 (2024-06-09)
- Maintenance release; see the compare link.
0.1.0 (2024-06-03)
- Initial release
Icons
ab-nextjs-icons 0.2.8
0.2.8 (2026-11-12)
- Normalize the changelog format and backfill missing entries.
0.2.7 (2026-11-01)
- ✨
brightness_auto(outlined + filled, weights 100–700, original geometry): the "system" theme glyph used by components' AbSettingsDrawer - 💄
link_off: Updated drawing, its slash now matchesvisibility_off - 🐢
prepackworks on Node 20: it runstsup --cleandirectly instead ofpnpm build(pnpm 11 needs Node ≥ 22, sonpm packfailed on Node 20) - Totals: 273 outlined / 248 filled
0.2.6 (2026-10-30)
- ✨
link_off(outlined only, weights 100–700, original geometry): the 404 page glyph
0.2.5 (2026-10-20)
- ✂️ Smaller tarball:
filesno longer shipsdemo-data/(demo fixtures) orab-icons-legacy/(pre-0.2 assets, nothing imports them), nor the unreferencedpics/me-nobg.png. 5039 → 4653 files, 1.93 → 1.63 MB packed. Every documented entry (dist,css,material-icons,ab-icons,logos,pics,launchers,ant-design-icons) still ships - 🏷️ README: the release line is a shields.io npm version badge (was a stale "0.2.2"), and a test checks the AbIcons totals against the icon map
0.2.4 (2026-10-20)
- ✨ Docs shell icons (G49, G3 batch 1), outlined + filled, original geometry:
animation,article,dashboard_customize,deployed_code,interests,keyboard_double_arrow_left,keyboard_double_arrow_right,match_case,new_releases,package_2,school,webhook, plustoc,left_panel_open,left_panel_close(TOC button / aside toggle) andtext_fields,desktop_windows - ⬛ New filled variants for
search(active bottom-bar tab),arrow_forward,chevron_right,code,download,expand_more - Line glyphs (chevrons,
toc,code, …) are filled as a bold 2.25 stroke; shapes use the solid mask style - 🧊
deployed_codeis a cube with‹ ›code chevrons, so it no longer reads aspackage_2 - ✍️ Generated
ab-icons/icons/*.tsmodules carry the house@authorsline - 🆔 Unique mask ids: filled svgs use
<name>FilledMask(was the outlined<name>Mask), so outlined + filled on one page never share an id (fixes the solid-square active Home). Test: every id is unique across all variants - 🆔 Per-instance ids:
scopeAbIconSvgIds(svg, scope)(fromab-nextjs-icons/ab-icons) suffixes everyidand itsurl(#…)/href="#…"refs, so two filled Homes on one page (e.g. with ReactuseId()) never share a mask. components 0.1.13AbIcondoes this per render - 📦 Ships
dist/:prepackrunspnpm build, andcheck:publish/prepublishOnlyfail whendist/index.*is missing (scripts/check-dist.mjs) - 🔧 npm author email is abrahamukachi@gmail.com
- Totals: 271 outlined / 247 filled; weights 100–700, per-icon modules, metadata, README gallery and dark previews regenerated
0.2.3 (2026-10-14)
- ✨
translate(outlined, original geometry): the i18n card on Welcome s01 ("eight packages") - ✨
github(outlined + filled): GitHub's official mark from Octiconsmark-github-24(MIT), scaled into the 2–22 box. Attribution inab-icons/NOTICE.md; GitHub logo guidelines apply - 📦 Per-icon modules
ab-icons/icons/<name>.ts(254):import github from 'ab-nextjs-icons/ab-icons/icons/github'gives{ outlined, filled? }for just that icon (type-only import of the map), so client bundles skip the 378 KB map. Generated bypnpm icons:modules;icons:modules:checkguards drift - Totals: 254 outlined / 224 filled; README gallery + dark previews regenerated
- 🔣 Generator in the repo:
scripts/regenerate-ab-icons-meta.py(from the install payload, byte-identical output) with--check, run bycheck:publish/prepublishOnly(needspython3);icons:meta/icons:meta:checkscripts; fails ifgithub.svgships without the Octicons NOTICE - 🟢
icons:modules:checkno longer loads.ts(works on Node 20) - ©️ Full license header on
ab-icons/index.css+ab-icons/icon-map.ts(emitted by the generator) - Tooling:
typecheckscript (tsconfig.typecheck.json)
0.2.2 (2026-10-06)
- barcode (filled): redrawn as five solid bars (thick/medium alternating) that span the outlined icon's bounds, replacing the thin knocked-out bars that read poorly at small sizes.
- build: new wrench-style glyph for outlined, filled and all weights 100–700 (replaces the previous irregular wrench outline).
- README gallery dark-mode previews regenerated for
barcodeandbuild.
0.2.1 (2026-10-05)
- README AbIcons gallery: alphabetical table of all 252 outlined icons with filled previews where available (223), generated by
scripts/readme-icons.mjs(pnpm readme:icons/readme:icons:check) between<!-- AB_ICONS:START -->/<!-- AB_ICONS:END -->markers. - Dark-mode previews: README-only copies under
docs/readme-icon-previews/dark/(outsidefiles) using GitHub#gh-light-mode-only/#gh-dark-mode-onlyfragments socurrentColoricons stay visible on dark backgrounds without duplicating SVGs in the published package.
0.2.0 (2026-10-05)
- AbIcons core-gap: 168 new concepts (336 new SVGs: outlined + filled). Package totals: 252 outlined, 223 filled (29 outlined-only UI strokes such as
add/close/searchhave no filled pair). - Weights 100–700 (Material Symbols–style) for outlined icons, with pre-rendered
ab-icons/weights/<w>/andweight.css/.abicon-w*. - Default weight is now 200 (stroke 1.25), down from the previous implicit 400 / 1.85 look on older outlined art — existing apps that relied on the thicker default will look thinner until they set
--abicon-weight: 400orgetAbIconSvg(..., { weight: 400 }). - Polish:
settings(simple gear),qr_code,scooter,umbrella,shopping_bag,usb, redrawnhandshake; filled glyphs grown to outlined outer bounds where they were undersized.
0.1.5 (2026-10-03)
- Publish to npm automatically from GitHub Actions with Trusted Publishing (OIDC + provenance, no NPM_TOKEN)
- Ship only package files via
files;nextpeer is now^16.3.4
0.1.4 (2026-09-23)
- Version bump after a staged 0.1.3 publish conflict
0.1.3 (2026-09-23)
- Add the AbIcons set and Ant Design filled/outlined variants, including the full Ant Design icons-svg catalog
- Theme-adaptive Ant/AbIcons and logo dark/light copper set
- Upgrade eslint-config-next for Next.js 16.3.4
- Copyright year → 2026
0.1.2 (2025-09-17)
- Maintenance release; see the compare link.
0.1.1 (2025-03-09)
- Maintenance release; see the compare link.
0.1.0 (2024-06-03)
- Initial release
Animations
ab-nextjs-animations 0.2.6
0.2.6 (2026-11-12)
- Normalize the changelog format and backfill missing entries.
0.2.5 (2026-10-29)
- locale-cycle (new): a 4-slot locale loop (EN → FR → ES → RU), moved from components' i18n playground scene.
.ab-locale-cycle-word(fade in + 8px rise, ease-out-cubic over the first 10%, held for its slot) and.ab-locale-cycle-chip(instantstep-endjumps); slot via--ab-locale-cycle-index, loop via--ab-locale-cycle-duration(2400ms), chip colours--ab-locale-cycle-on-bg|on-fg|off-fg;[data-ab-still]= the still frame; pause inside[data-ab-paused='true']. Reduced motion (OS or[data-ab-reduced-motion='true']): still frame only.AB_LOCALE_CYCLE_WORD_CLASS,AB_LOCALE_CYCLE_CHIP_CLASS,AB_LOCALE_CYCLE_SLOTS;locale-cycle-word/locale-cycle-chipinsupportedAnimations(21 total) - state-cycle (new): the Welcome v6 "upgraded" 4-state loop (4 × 600ms = 2.4s, in sync with
.ab-wire-pulse). Per state (--ab-state-cycle-index):.ab-state-cycle-word|chip|hl|dim; per step:.ab-state-cycle-press(--ab-motion-press-scale0.94, 0–15%),.ab-state-cycle-pop(0.6 → 1.06 → 1),.ab-state-cycle-rise(14px → 0); per loop:.ab-state-cycle-switch+.ab-state-cycle-knob(off for states 2–3),.ab-state-cycle-fill(scaleX 0 → 1),.ab-state-cycle-ride(offset-distance0 → 100% over 0–75%, then holds). Still frame = state 0 ([data-ab-still], fill 40%, ride at the end); pause and reduced motion as locale-cycle.AB_STATE_CYCLE_CLASSES,AB_STATE_CYCLE_STATES,AB_STATE_CYCLE_DURATION;state-cycle-highlight|press|pop|rideinsupportedAnimations(25 total)
0.2.4 (2026-10-14)
- slide-step (new): direction-aware slide enter / leave.
.ab-slide-step-in/.ab-slide-step-out(keyframesabSlideStepIn/abSlideStepOut); forward / back fromdata-ab-directionon the element or an ancestor; RTL mirrors under[dir='rtl']or--ab-slide-step-flip: -1; tunables--ab-slide-step-duration/-easing/-distance;getAbSlideStepDirection(from, to, count, loop)(shortest way round when looping). Reduced motion (OS or[data-ab-reduced-motion='true']): opacity cross-fade only (--ab-slide-step-reduced-duration, default 120ms) - wire (new): SVG flow-diagram wires.
.ab-wire-draw(draw-on, staggered by--ab-wire-index) and.ab-wire-pulse(fade in, then a dash travels;--ab-wire-pulse-iterations,-duration,-delay,-stagger); pause inside[data-ab-paused='true']. Reduced motion: wires drawn, pulse frozen at--ab-wire-poster - spin (new):
.ab-spinfor loading rings. Reduced motion: slow opacity "breathe", no rotation - progress-sweep (new):
.ab-progress-sweepindeterminate sweep (RTL-mirrored). Reduced motion: full, softened static bar - motion (new): tokens
--ab-motion-duration-short|medium|long,--ab-motion-ease-standard|emphasized,--ab-motion-press-scale,--ab-motion-lift-scale; transition classes.ab-motion-colors,.ab-motion-interactive,.ab-motion-transform,.ab-motion-size,.ab-motion-press,.ab-motion-lift(AB_MOTION,AB_MOTION_TOKENS). Reduced motion: transitions off, no scale feedback - Registry:
slide-step-in,slide-step-out,wire-draw,wire-pulse,spin,progress-sweepadded tosupportedAnimations(19 total); every new folder +styles.cssinexports/files - Docs: README "Class naming:
ab-vs legacy" (new classes areab--prefixed; legacy names are not renamed)
0.2.3 (2026-10-14)
- fade (G28): new
fade/animation —.fade(keyframesabFade) driven by--fade-from/--fade-to;refuses the same vars (+ duration / easing / delay vars),FadeAnimation,getAbFadeAnimation(reduced),prefersAbReducedMotion() - Reduced motion:
.fade,.fadeInand.fadeOutturn the animation off underprefers-reduced-motion: reduceand jump to the final opacity - Types: fix
getAllKeyframestyping (TS2322) and allow.tsimport paths; newtypecheckscript;exportsmap (root,./types, every animation folder, and./*so<name>/styles.csspaths keep working)
0.2.2 (2026-10-03)
- Publish to npm automatically from GitHub Actions with Trusted Publishing (OIDC + provenance, no NPM_TOKEN)
- Ship only package files via
files;nextpeer is now^16.3.4
0.2.1 (2026-09-23)
- Maintenance release; see the compare link.
0.2.0 (2024-06-09)
- Maintenance release; see the compare link.
0.1.36 (2024-06-08)
- Maintenance release; see the compare link.
0.1.35 (2024-06-08)
- Maintenance release; see the compare link.
0.1.34 (2024-06-08)
- Maintenance release; see the compare link.
0.1.33 (2024-06-08)
- Maintenance release; see the compare link.
0.1.32 (2024-06-06)
- Maintenance release; see the compare link.
0.1.31 (2024-06-06)
- Maintenance release; see the compare link.
0.1.30 (2024-06-06)
- Maintenance release; see the compare link.
0.1.29 (2024-06-06)
- Maintenance release; see the compare link.
0.1.28 (2024-06-06)
- Maintenance release; see the compare link.
0.1.27 (2024-06-06)
- Maintenance release; see the compare link.
0.1.26 (2024-06-06)
- Maintenance release; see the compare link.
0.1.25 (2024-06-06)
- Maintenance release; see the compare link.
0.1.24 (2024-06-05)
- Maintenance release; see the compare link.
0.1.23 (2024-06-05)
- Maintenance release; see the compare link.
0.1.22 (2024-06-05)
- Maintenance release; see the compare link.
0.1.21 (2024-06-05)
- Fix publish to GitHub packages
0.1.20 (2024-06-05)
- Maintenance release; see the compare link.
0.1.19 (2024-06-05)
- Maintenance release; see the compare link.
0.1.18 (2024-06-05)
- Maintenance release; see the compare link.
0.1.17 (2024-06-05)
- Maintenance release; see the compare link.
0.1.16 (2024-06-05)
- Maintenance release; see the compare link.
0.1.15 (2024-06-04)
- Maintenance release; see the compare link.
0.1.14 (2024-06-04)
- Maintenance release; see the compare link.
0.1.13 (2024-06-04)
- Maintenance release; see the compare link.
0.1.12 (2024-06-04)
- Maintenance release; see the compare link.
0.1.11 (2024-06-04)
- Maintenance release; see the compare link.
0.1.10 (2024-06-04)
- Maintenance release; see the compare link.
0.1.9 (2024-06-04)
- Maintenance release; see the compare link.
0.1.8 (2024-06-04)
- Maintenance release; see the compare link.
0.1.7 (2024-06-04)
- Maintenance release; see the compare link.
0.1.6 (2024-06-04)
- Maintenance release; see the compare link.
0.1.5 (2024-06-04)
- Maintenance release; see the compare link.
0.1.3 (2024-06-04)
- Maintenance release; see the compare link.
0.1.2 (2024-06-04)
- Version bump to 0.1.2
0.1.1 (2024-06-03)
- Version bump to 0.1.1
0.1.0 (2024-06-03)
- Initial release
Theme
ab-nextjs-theme 0.3.10
0.3.10 (2026-11-12)
- Normalize the changelog format and backfill missing entries.
0.3.9 (2026-11-03)
- 🔤 Keep the mono font on
code,preand Shiki spans - 📏
.ab-prosetext inherits its size instead of the base 24px - 📋
.ab-proselists get disc and decimal markers - 🎨
.ab-proseinline code uses surface tokens for contrast
0.3.8 (2026-11-03)
- 🎨
color-scheme: light/dark on the theme scopes, and on contrast-scheme classes - 📝
.ab-prose/.ab-prose-none: typography for MDX docs, using theme tokens - ⚠️ Warning and danger tokens (
on-,container,on-container) for every scheme
0.3.7 (2026-10-29)
- 🟤 Dotted surface tokens for the Welcome playground (dot colours in their percent form).
- 🎠 Welcome surface tokens from the v6 mock: pane (light #fffcfa), main, card and a new node token. Add
data-ab-surface="page"to keep a pane on the page colour. - 🥉
--ab-color-on-bronze(#fff8f5, the same in dark): text on bronze, for the v6 Get Started button. - ➖
--ab-color-line(v6--line): lightrgb(107 79 53 / 16%), darkrgb(255 232 210 / 10%). - 🔗 Links:
--ab-link-color, applied through a low-specificity@layer base { :where(a) }rule so components can override it. - 🔘 Button sizing: the legacy
[data-type]button size rules now skip.AbButton(:not(.AbButton)). AbButton sizes itself (components ≥ 0.2.3). Colours and state layers are unchanged. - 🧹 Release-age pins: removed the expired D33
minimumReleaseAgeExcludeentries (fonts 0.2.6, icons 0.2.4). - 🛡️ Pack guard: a test checks that shipped relative imports resolve inside the package
files.
0.3.6 (2026-10-21)
- 🖥️ Gapped light panes (mock 05): at ≥ 1920px in light,
--ab-color-pane-mainis #fff and--ab-color-cardis #fffcfa, matching the mock's.gappedvalues. The floating main pane turns white on the #fff8f5 background. Dark has no gapped mock and is unchanged. The block sits before the dark block, so.darkalways wins. - 🪟 New
--ab-color-pane: #fff at ≥ 1920px in light (mock 05--pane), for the sidebar and TOC/aside panes. Core ≥ 0.2.1 reads it. It isn't set anywhere else, and dark sets it toinitial, so every other width and dark keep their current colours. - 🛡️ Guard test:
--ab-color-accentis never used as a text colour (use--ab-color-accent-text).
0.3.5 (2026-10-20)
- 🏠 Home palette (P15/P16, spec §2): new
--ab-color-*tokens with the exact approved mock values for light and the warm-brown dark:bg,pane-main,card,card2,border,div,text,muted,faint,accent,accent-text,tint,btn,btn-text,code,code-text,kbd,hoverandsage-accent, plus--ab-shadow-card. Existing tokens are unchanged. - 🌿 Sage beta-chip text: light
--ab-color-sage-accent#778d79 (3.2:1) → #566a58, ≥ 4.72:1 on the sage tint over bg/card/card2. A candidate #5f7461 measured 4.46:1 on card, so it is one step darker. Dark #8fa491 already ≥ 5.03:1, unchanged. Tint unchanged. Tested. - ♿ AA nudges (2026-10-20 20:26): a few mock colours moved just enough to reach 4.5:1, each ratio tested:
- light
--ab-color-faint#9c8c80 → #807062 - light
--ab-color-accent-text#8b6340 → #88603d(4.5:1 on--tint) - light
--ab-color-btn#a67c52 → #8b6340(white text 5.31:1; also the New badge) - dark
--ab-color-faint#86776b → #9a8a7d - 🥉 Warm dark accent (P15): in dark,
--ab-color-primary/--ab-focus-ring=#c29a6f(with--ab-color-on-primary: #19120c) instead of the Material#fcb975. Every component that reads them turns warm bronze. - 🔷 Shapes (P16):
- radii:
--ab-radius-kbd5,-chip6,-row8,-tile9,-button10,-code12,-card14,-pill999 - sizes:
--ab-button-height40 (-touch44),--ab-button-padding-inline16,--ab-chip-height20,--ab-chip-padding-inline7 - shadows and colours:
--ab-shadow-button,--ab-shadow-thumb,--ab-color-thumb,--ab-scrim-color(40% / 60%),--ab-color-handle,--ab-color-sheet-edge - 🧅 Cascade layer: the bare element rules (
body,h1–h3,p,button,span,a, …) incss/typography.cssandcss/styles.cssnow sit in@layer base(Tailwind v4's base layer). Tailwind utilities and any unlayered app CSS now win over them. ⚠️ An app that relied on those defaults beating its own unlayered rules will see its own rules apply. - ⚠️ Heads-up for consumers: any layered CSS in your app (Tailwind's
utilitiesandcomponentslayers, or a third-party library's@layer) now beats the theme'sbody,h1–h3,p,aandbuttondefaults. Before this change those defaults were unlayered and beat every layered rule. Only unlayered app CSS is unaffected. - 📐 Breakpoints (Decision 6): mobile <768, tablet 768–1179, joined panes 1180–1919, gapped panes ≥1920. They're declared as `--ab-breakpoint-tablet` / `-joined` / `-gapped` for reference (core ≥ 0.1.7 owns the media queries). The gapped panes now use the desktop mock geometry: ⚠️ `--ab-pane-gap` **12px → 16px** and `--ab-pane-radius` **16px → 20px**. `--ab-pane-shadow` is new: the mock shadow in light, `none` in dark.
0.3.4 (2026-10-20)
- 🧭 Docs-shell tokens (G18 slice):
--ab-focus-ring-width/--ab-focus-ring-offset(the primary ring is ≥ 3:1 on background and surface-container in both themes),--ab-pane-gap/--ab-pane-radius,--ab-color-divider/--ab-divider-hairline, and--ab-color-code-surface/--ab-color-on-code-surface(dark in both themes, ≥ 4.5:1) - ↕️ Legacy button margins skip AbButton: the
margin-top/bottom(24/16px, 32/24px from 460px) on outlined / text buttons now use:not(.AbButton), so an AbButton in the app bar no longer makes it 105px tall - ⌨️
--ab-font-code='Roboto Mono'(ab-nextjs-fonts 0.2.6, D29 a / G30) first, then the system mono stack (--ab-font-mono) as the fallback. The fonts peer and devDependency move to^0.2.6, andcss/typography.cssimportsab-nextjs-fonts/roboto-mono/styles.css - 🔧 npm author email is abrahamukachi@gmail.com
- 📝 Only Ab forms are styled: the form layout, disabled opacity, typography and staggered entrance now target
:is(form.AbForm, form[data-ab-part="form"]). A plain<form>(search box, newsletter, …) keeps the browser layout - ➖
ab-nextjs-iconsis a required peer (G20), no longer a runtime dependency, so apps get one icons copy. Install it next to the theme (^0.2.3, satisfied by 0.2.4) - 📝 Code file headers use the house
@authorsemail - 🔣 icons peer
^0.2.4(peer + dev; was^0.2.3) - ⏳ D33:
pnpm-workspace.yamlturns onminimumReleaseAgeStrictand exempts exactlyab-nextjs-fonts@0.2.6andab-nextjs-icons@0.2.4until 24h after their publish (2026-10-21 17:06 / 17:15 UTC);__tests__/release-age.test.tsfails after that and only accepts exact versions - Tests: tokens declared, focus-ring and code-surface contrast, D29a Roboto Mono + mono fallback, no bare
formselector, icons as a non-optional peer
0.3.3 (2026-10-16)
- 🌐 Menus are no longer hidden behind content: the layout
mainrule (position: relative; z-index: 99) matched every<main>, so any<main>became a stacking context painted over popovers outside it, like the globe/language menu. It now targets only the Ab layout main:#appLayout > main,main.AbMainLayoutandmain[data-ab-part="main"] - 🥉 New bronze filled button:
button[data-type="filled"]/a[role="button"][data-type="filled"]paints a solid--md-sys-color-primarybackground with--md-sys-color-on-primarylabel and icon (6.47:1 light, 7.74:1 dark, measured in WebKit). Hover and focus add an 8% / 12% on-primary state layer (focus also draws a 2px--ab-focus-ringoutline); disabled uses Material's on-surface 12% / 38%. Every colour can still be overridden with the--ab-button-*variables - 🎨 Button icons follow the label colour:
--material-icon-coloron contained, outlined and text buttons (and their hover / focus states) read the--ab-button-background-color*overrides, so an app that set a custom background got an icon the same colour as the background. They now read the matching--ab-button-text-color*(label) variables - 👻 Text-button focus reads a real variable: the text-button focus rule read
--ab-button-color-focus, which nothing defines, for both its label and icon. Both now read--ab-button-text-color-focus, like the other button types - 📱 Filled follows the mobile size: the 20px /
8px 16pxmobile button rule now includesbutton[data-type="filled"](it rendered at 18px) - Tests: no bare
mainwith z-index, the scoped main selectors, the filled base / hover / focus / disabled rules, on-primary-on-primary contrast ≥ 4.5:1 in light and dark, every button--material-icon-colorreads a--ab-button-text-color*variable (disabled excepted), no--ab-button-color-focus, filled in the mobile size rule
0.3.2 (2026-10-15)
- 🩹 Legacy colour aliases are live again: the section comments in the
[data-theme="light"], .lightand[data-theme="dark"], .darkblocks ofcss/colors.csswere never closed, so--primary-container-colorand the other 48 aliases in each block were swallowed and AbButtoncontainedrendered transparent. The comments are closed, and each alias now points at the live Material token (--md-sys-color-*fromlight.css/dark.css). The old--*-color-light/--*-color-darksource values were themselves commented out (an old green palette), so the aliases had nothing to point at - ♿ Form entrance respects reduced motion: the staggered
form > *fade/slide-in only runs inside@media (prefers-reduced-motion: no-preference), and it no longer hard-setsopacity: 0(backwardsfill instead). Children are visible by default, including when thefadeIn/slideFromDownkeyframes (from the optionalab-nextjs-animationspeer) aren't loaded - 🧱 Only the Ab layout aside is laid out: the layout
asiderules (hidden by default,position: absoluteon phones, 60% width on laptops,data-opened/data-closing) now target#appLayout > aside,aside.AbAsideLayoutandaside[data-ab-part="aside"], so a plain<aside>in content is no longer hidden or absolute-positioned - ⬆️
ab-nextjs-icons ^0.2.3(was^0.1.4): removes the duplicate icons 0.1.x copy apps got next to the components' 0.2.3.css/typography.cssstill importsab-nextjs-icons/css/material-icons.css, which 0.2.3 ships - Tests: comment balance + every alias resolves (light + dark), form entrance gated + no hard opacity 0, no bare
asidelayout selector, one icons version in the lockfile. Checked in WebKit: contained buttonrgb(255, 220, 189)light /rgb(105, 60, 0)dark (was transparent), form visible under reduced motion and without keyframes, plain<aside>static
0.3.1 (2026-10-14)
- New
css/ab-tokens.css(imported bycolors.css):--ab-*tokens for abElements components ≥ 0.1.10 - ♿
--ab-color-bronze-text(§8): small bronze text that passes AA. Light#8a6440(5.03:1 on background, 4.56:1 on surface-container); dark#d9ab7f(8.9:1 / 7.86:1). The base--ab-color-bronze#a67c52stays for large text/UI (3.55:1) - 🔤
--ab-font-title= Mulish (§8 Q6: Cyrillic) +.font-title/.ab-titleutilities (weight 800). Globalh1–h3are unchanged (still Inter) - 🎨 aliases onto the live
--md-sys-color-*palette (primary, surface, surface-container, outline-variant, …),--ab-color-sage,--ab-focus-ring,--ab-font-body,--ab-font-mono;.text-bronze - Tests: tokens present, aliases resolve in both palettes, AA contrast computed from the live palette
- Dependencies:
ab-nextjs-fonts(^0.2.5) andab-nextjs-animationsare now optional peers, no longer dependencies. ⚠️styles.cssstill@imports the font stylesheets, so apps using it must installab-nextjs-fontsthemselves (README).ab-nextjs-iconsstays a dependency (css/typography.cssimports itsmaterial-icons.css) - Types:
CoreColors.tertiary(the misspelledtertiatystays as an optional@deprecatedalias);CoreColors.error,Theme.typographyandTheme.stylesare optional andFontSizeentries are[size, meta], matching runtime - Tooling:
typecheckscript (tsconfig.typecheck.json)
0.3.0 (2026-10-05)
BREAKING CHANGES
- Dialog, toast, logo, spinner, and doodle chrome CSS + assets moved to
ab-nextjs-components>=0.1.8. Apps on^0.2.10that only bump the theme would silently lose all chrome. - Migration: add this import right after the theme import:
@import "ab-nextjs-theme/styles.css";
@import "ab-nextjs-components/styles.css";0.2.10 (2026-10-03)
- Publish to npm automatically from GitHub Actions with Trusted Publishing (OIDC + provenance, no NPM_TOKEN)
- Ship only package files via
files;nextpeer is now^16.3.4 - Fix
styles.cssbreaking app builds: the Ab logo and spinners now ship inassets/, the LYD-only images (doodles, 3D, emoji GIF, lock) became opt-in custom properties, and a newcheck-css-assetsguard fails packing if a CSSurl()doesn't resolve inside the package
0.2.9 (2026-10-03)
- Fix
file:dependencies and add a publish guard
0.2.8 (2026-09-23)
- Upgrade tooling for Next.js 16.3.4
- Type the default
abThemeexport - Copyright year → 2026
0.2.7 (2025-09-17)
- Maintenance release; see the compare link.
0.2.6 (2025-09-17)
- Maintenance release; see the compare link.
0.2.5 (2025-09-17)
- Maintenance release; see the compare link.
0.2.4 (2025-09-16)
- Maintenance release; see the compare link.
0.2.3 (2025-03-09)
- Maintenance release; see the compare link.
0.2.2 (2025-03-09)
- Maintenance release; see the compare link.
0.2.1 (2025-03-09)
- Maintenance release; see the compare link.
0.2.0 (2025-03-08)
- Maintenance release; see the compare link.
0.1.5 (2024-08-02)
- Maintenance release; see the compare link.
0.1.4 (2024-07-31)
- Maintenance release; see the compare link.
0.1.3 (2024-07-30)
- Maintenance release; see the compare link.
0.1.2 (2024-06-10)
- Maintenance release; see the compare link.
0.1.1 (2024-06-10)
- Maintenance release; see the compare link.
0.1.0 (2024-06-03)
- Initial release
Hooks
ab-nextjs-hooks 0.1.8
0.1.8 (2026-11-12)
- Normalize the changelog format and backfill missing entries.
0.1.7 (2026-10-20)
- 🔭
useAbScrollSpy(ids, { rootMargin, threshold, root, enabled, initialId })(G46): the active section for an "On this page" TOC. One IntersectionObserver; the first visible id in order wins and the last one sticks between sections; SSR / no-IO safe. AlsoscrollToAbSection(id, { offset, updateHash, root }): scrollsrootwhen given (a pane), else the window; smooth, or instant under reduced motion.AB_SCROLL_SPY_ROOT_MARGIN='-64px 0px -60% 0px' - 📏 Panes scrolling (D35, G55): with core 0.1.6 the page never scrolls, so pass the main pane as
root(useAbPage().mainScrollElement); the spy listens to that scroller, and at the bottom of the root the last id wins (lastAtBottom, defaulttrue). With arootthe default margin isAB_SCROLL_SPY_PANE_ROOT_MARGIN='0px 0px -60% 0px'(no app bar inside a pane); the window keeps-64px.scrollToAbSectiontakescontainer(rootstays as a deprecated alias) - 🌗
abThemeScript/getAbThemeScript({ defaultTheme, storageKey, legacyStorageKey }): the inline no-flash script, server-safe atab-nextjs-hooks/abThemeScript. Paints<html>exactly likeapplyAbThemeToDocument(tested), migratesabTheme, falls back to the OS scheme when storage is blocked, and JSON-encodes its options - 📦 New entry points
./useAbScrollSpyand./abThemeScript; catalog 46 hooks - ⏭️
useAbHotkey(G48) is deferred to P5 (D24 a)
0.1.6 (2026-10-14)
- useAbMedia (G10): live
matchMediaboolean viauseSyncExternalStore; SSR/hydration value =defaultValue(false); never throws (missingmatchMedia, invalid query); legacyaddListenerfallback. Helpers:matchAbMedia,getAbMediaQueryList - useAbClipboard (G10):
{ copy, copied, error, reset }; async Clipboard API withexecCommand('copy')fallback;copiedauto-resets afterresetAfterms (default 2000,AB_CLIPBOARD_RESET_MS); timer cleared on unmount. Helper:copyAbText - useAbReducedMotion (G32): live
prefers-reduced-motion: reduceboolean (AB_REDUCED_MOTION_QUERY, same string as animations);prefersAbReducedMotionNow() - useAbSwipe (G32): Pointer Events swipe with 48px threshold or flick velocity, axis lock (vertical drags left to scrolling),
onNext/onPrevflipped in RTL,[data-ab-swipe-ignore]zones, touch + pen by default. PureresolveAbSwipe/getAbSwipeLogical - G11 cookie lifetime:
toggleAppHello(state?, { maxAge })/toggleAppReady(state?, { maxAge })(seconds, validated; default stays 7 days so it is non-breaking). PresetsAB_APP_COOKIE_MAX_AGE.oneWeek/.oneYear,resolveAbAppCookieMaxAge(),AbAppCookieOptions;useAbApp().toggleHello/toggleReadyforward the options. Cookies now useMax-Ageinstead ofExpires. Welcome v6 uses 1 year - Theme system mode (G9):
useAbThemeMode()→{ mode, resolvedTheme, setMode }with'light' | 'dark' | 'system';'system'followsprefers-color-schemelive.<html>keeps the RESOLVED class/data-theme(existing.darkCSS works) plus newdata-theme-mode.useAbThemetuple unchanged and accepts'system'. NewresolveAbTheme,isAbThemeMode,AB_THEME_DARK_QUERY,AB_THEME_MODES. App no-flash scripts must resolve'system'before paint - Docs: README note: the Welcome passes
{ maxAge: AB_APP_COOKIE_MAX_AGE.oneYear }(default stays 7 days)
0.1.5 (2026-10-14)
- useAbLocalStorage (G10):
useState-like localStorage hook —[value, set, remove]; JSON by default (customserialize/deserialize); never throws (blocked getter, throwinggetItem/setItem, quota, corrupt JSON → initial value; refused writes kept in memory); SSR-safe viauseSyncExternalStore; synced across tabs (storage) and same-tab instances (ab-local-storageevent).typecheckscript. Helpers:getAbLocalStorage,readAbLocalStorage,writeAbLocalStorage
0.1.4 (2026-10-05)
- Dialogs: target
aside.AbAsideLayout/aside[data-ab-part="aside"](never the first<aside>/ a sidebar) - Dialogs: a cancelable backdrop click closes the dialog;
onConfirm/onCancelrun then close (returnfalseto keep it open) - Dialogs / toasts: text is escaped by default; pass
html: truefor trusted markup - Exports:
AbDialogPart,DialogParams,DialogList,AbDialogResult,ToastParams, theme helpers - Theme:
useAbThemeuses thethemekey on<html>(class +data-theme+color-scheme), matching ab-elements-app's no-flash script; migrates legacyabTheme/body[data-theme]once - Menus / toasts: same aside-layout selector as dialogs; toast uses the
.popInclass fromab-nextjs-animations
0.1.3 (2026-10-03)
- Publish to npm automatically from GitHub Actions with Trusted Publishing (OIDC + provenance, no NPM_TOKEN)
- Ship only package files via
files;nextpeer is now^16.3.4 - Export
./helpers/*and./helpers/useAbTogglefor deep imports (already in the published 0.1.2 tarball)
0.1.2 (2026-09-23)
- Next.js 16.3.4 / React 19 peers and eslint-config-next flat config
- Export surface expanded for client hooks + stricter TypeScript types
- Copyright year → 2026
- Smoke test asserts package version 0.1.2
- Short barrel names are canonical (
useBrand,useFaq, …);useAb*aliases retained - Cookie-mutating server actions live in
server/*.actions.ts('use server'); syncuseAbApp/useAbAuthstay plain modules (fixes "Server Actions must be async functions") useAbThemehydrates fromlocalStorageinuseEffect(no render-time access)- Auth token + cached user cookies are httpOnly; user JSON no longer readable from JS
package.jsonexports+files; removedpeerDependenciesMetaoptional flags for next/react/react-dom- README reflects 0.1.2 /
main(dropped stalechore/upgrade-next-16note)
0.1.1 (2026-09-16)
- Initial Next 16 tooling pass and package smoke tests
0.1.0 (2024-06-04)
- Initial release
Core
ab-nextjs-core 0.2.4
0.2.4 (2026-11-12)
- Normalize the changelog format and backfill missing entries.
0.2.3 (2026-10-29)
- 📱 Mobile aside drawer:
AbAsideDrawerTrigger,useAbAsideDrawer, and--ab-aside-drawer-zlift the mobile aside drawer above main. E2E covers the drawer. - 🧩
asideBelow: place the aside inline before main (useAbInlineScroller); sized to its content and kept within the phone width below 1180px.asideAnchorslot. - 📌
mainBarPin: pins the main bar at every width (mainBarLabel); unit tests (client + server, CSS) and e2e - 🏠
surface="page":AbAppLayoutcan use the v6 Welcome page background.AbDottedSurfaceand thedata-ab-surfacedotted hook - ✨
mainHeaderAt="all"keeps one main header at all widths; the mobile main header can grow for an extra row and is sized for a compact AbMobileHeader - ♿ The main scroller is a focusable named region;
AbAsideLayoutcan name its landmark witharia-label - 🐛 Server layout CSS twins stay in sync (drift guard test); the tablet aside uses the pane token for an exact dark; auto scrollbar gutter on the phone main scroller; the main header stays above the main scroller; legacy 1536px margins are reset on the first content item
- 🛡️ Pack guard: shipped relative imports resolve inside
files
0.2.2 (2026-10-21)
- ➖ Pane dividers: the faint header hairline
- 📐 Aside padding matches the mock
- ✅ Tests pin the hidden aside at mobile and tablet tiers
0.2.1 (2026-10-21)
- 🎨 Main pane background:
AbMainLayout(client + server) paints--ab-color-pane-main(theme ≥ 0.3.5) in light and dark, then the old chains (--color-background→--surface→#fff; dark--color-dark-background→--surface→#0a0a0a). The theme never defined--color-background, so the pane was white instead of #fff8f5 / #1d150f. The bottom fade uses the same colour. - 🎨 Aside pane background:
AbAsideLayout(client + server) does the same:--ab-color-pane-mainfirst in light and dark, for the pane and its fade. It was white too. - 🪟 Side panes at 1920: the sidebar / rail pane (
:where(), zero specificity), the ≥ 1180px aside column andAbAsideLayoutread theme 0.3.6's--ab-color-panefirst. The theme only sets it at ≥ 1920px in light (#fff, mock 05), so everywhere else, and in dark, the fallbacks keep today's colours: a transparent sidebar and a--ab-color-pane-mainaside. - 📟
tabletHeader="main": from 768 to 1179px, the main-header slot is now exactly--ab-header-height(60px) tall and its child fills it, like the app header row (mock 06.mbar). It used to take the child's own height, which was 48px. - 🏷️ Sidebar logo row: AbSidebar's
logorow (data-ab-part="sidebar-logo", components ≥ 0.1.15) is shown only where the app header is hidden, which istabletHeader="main"at 768–1179px. Everywhere else in panes it's hidden, because the app bar already carries the brand. - 🚫 AbAsideLayout: no more
transition: all 300ms(the no-transitions rule; motion comes from ab-nextjs-animations). - 📱 AbAppLayout
mobileHeader="main"(drawers v2): below 768px the app header row is hidden and AbMainLayout'smainHeaderbecomes the 56px mobile bar (1px divider, notch padding, z 10). Hidden at 768px and up unlesstabletHeader="main"shows it on tablet. Default"header"(unchanged).
0.2.0 (2026-10-20)
⚠️ BREAKING (`variant="panes"` only; the default variant is unchanged)
- 📐 Breakpoints moved: joined panes now start at 1180px (was 1024) and gapped panes at 1920px (was 1440). So 1024–1179 now shows the tablet layout (overlay aside), and 1440–1919 shows joined panes.
- 🔎
AB_ASIDE_SHEET_QUERYchanged from'(max-width: 1023px)'to'(max-width: 1179px)', soisAsideSheet/ small-screen checks flip at 1180. - 🔝 The header row has a fixed height:
--ab-header-height(52px on mobile, 60px from 768, 64px from 1920) plus the safe-area inset. A taller custom header gets clipped, so set--ab-header-heightto keep it. - 🗂️ New pane-width defaults: tablet sidebar 248 (was 280), overlay aside 320 (was
min(40vw, 360px)), rail 64 (was 72), joined 260 / 236, gapped 288 / 272. - 🪟 Gapped look: 16px gap (was 12), outer gap on the sides and bottom only, 20px radius (was 16), and a light-only
--ab-pane-shadow. - 🧭 Migrate (keep the 0.1.6 look):
.AbAppLayout { --ab-sidebar-width: 280px; --ab-aside-width: min(40vw, 360px); --ab-rail-width: 72px; --ab-header-height: 64px; --ab-pane-gap: 12px; --ab-pane-radius: 16px; --ab-pane-shadow: none; }. The breakpoints themselves can't be overridden (they're media queries; configurable breakpoints are P1).
Changes
- 📐 Breakpoints (Decision 6, 2026-10-20): mobile <768, tablet 768–1179 (the aside is a sheet), joined panes 1180–1919, gapped panes ≥1920. They were 1024 and 1440. `AB_ASIDE_SHEET_QUERY` is now `(max-width: 1179px)`. The 1180 boundary is the same one AbAppBar already uses to move its nav into More.
- 🪟 Gapped panes follow the desktop mock (05): a 16px gap, an outer gap on the sides and bottom only (the header sits on top), a 20px radius and a soft
--ab-pane-shadow. The defaults matchab-nextjs-theme0.3.5. - 🗂️ Pane widths + header height (spec §3): the defaults are now in
:where()(zero specificity), so an app's--ab-sidebar-width/--ab-aside-width/--ab-rail-width/--ab-header-heightalways win. The values: tablet sidebar 248 · aside 320; joined 260 / 236; gapped 288 / 272; rail 64. The header row is--ab-header-height: 52px on mobile, 60px from 768, 64px from 1920. - 📟
tabletHeader="main"(P2): from 768 to 1179 the app header row is hidden and AbMainLayout'smainHeaderbecomes the bar. At other widths that slot is hidden. - 🌗
--ab-pane-shadowisnonein dark.
0.1.6 (2026-10-20)
- 🧭 Docs-shell panes (G17):
AbAppLayout(client + server) getsvariant="panes"andrailCollapsed. Four breakpoints: mobile (bottom bar, aside as a full-screen sheet), tablet 768–1023 (280px sidebar or 72px rail, overlay aside on the right, hidden by default), laptop 1024–1439 (joined panes, hairline dividers), desktop ≥ 1440 (gapped panes with radii). Uses the theme 0.3.4 tokens with fallbacks. The default variant is unchanged - 🧷 Rail: 200ms width transition, instant under reduced motion; stays expanded with JS off (
@media (scripting: none)) - 📑 Aside toggles (useAbPage):
toggleAside,toggleAsideOnMobile,asideId(the aside'sid), anduseAbAsideToggle(), which picks the sheet or the pane for the viewport and returnsaria-expanded/aria-controls/onClick.Escapecloses the sheet - 🎞️ Aside slide:
slideFromRight(ab-nextjs-animations) at 240ms (asideDurationdefault 240, was 300); under reduced motion no slide and instant open/close (getAbAsideDuration) - 📏 Layout rule (D35, G50–G52, G54): the page never scrolls. In panes the app is a
100dvhgrid (auto minmax(0,1fr) auto,overflow:hidden) and<html>/<body>are locked while it is mounted (:has()plus adata-ab-layout-lockfallback, counted byacquireAbLayoutLock()so unmounting one of two layouts keeps it). Main, aside and sidebar each scroll on their own:min-height:0,overscroll-behavior: contain,scrollbar-gutter: stable, safe-area padding. The 64px--ab-app-bar-heightoffset and the sticky columns are gone - 🫥 Empty chrome is 0px (G50): null header/footer slots are not rendered, and
:empty/:has()collapse the rest; strings are wrapped (toAbSlot) so text-only slots never collapse - 🔝 New slots (G52):
AbMainLayoutmainHeader/mainBar,AbAsideLayoutasideHeader/asideBar(data-ab-part="main-header"…).header/footer/chromestay as deprecated aliases - 📜 Scrollers on useAbPage (G55):
mainScrollElement/asideScrollElement(content wrappers aredata-ab-part="main-content"/"aside-content"), for hooks 0.1.7useAbScrollSpy({ root }). The serverAbMainLayout/AbAsideLayoutset them too, through a tiny client island (AbScrollRegistrar, one hidden<span>as the scroller's first child) - 🧱 No nested headers: in panes (or when the slot child is already a
<header>) the header wrapper is a<div>;overlaysdrops the legacy layers (off by default in panes); the pane CSS also targets AbSidebar'sdata-ab-part="rail" - 🆔 AbMainLayout / AbAsideLayout:
idprop, andchrome={false}drops their empty header/footer wrappers and backdrop/menus/dialogs/toasts/progress/canvas (defaulttrue, unchanged). ServerAbAsideLayoutsetsid(defaultab-aside) - 🌫️ Sheet: tablet backdrop (click closes), focus moves into the sheet and back to the opener,
Escapeskips events an inner menu alreadypreventDefaulted, and one open/close timer so quick toggles never race - 🔧
typecheckscript; 📝 house@authorsemail in the code file headers - Tests: per-breakpoint CSS, rail + reduced motion + JS off, aside 240ms / reduced motion, toggles and aria. Checked in WebKit at 390 / 768 / 1280 / 1600px
0.1.5 (2026-10-05)
- Landmarks: header / footer wrappers set
data-ab-part="header"/data-ab-part="footer"
0.1.4 (2026-10-05)
- Semantics: layout wrappers use landmark tags —
<header>/<footer>(was<div>);<main>and<aside>unchanged; sidebar / bottom bar stay the consumer's<nav>(AbSidebar/AbNavbarin components) - Aside targeting:
AbAsideLayoutsetsdata-ab-part="aside"(and keepsclass="AbAsideLayout") souseAbDialog/useAbMenu/useAbToastcan find the real aside, never a sidebar - Main:
AbMainLayoutsetsdata-ab-part="main" - Animation: client
AbAsideLayoutuses the real.slideFromRightclass fromab-nextjs-animations(was undefinedanimate-slide-from-right)
0.1.3 (2026-10-03)
- Publish to npm with Trusted Publishing (OIDC);
nextpeer^16.3.4
0.1.2 (2026-09-23)
- Version bump after a staged 0.1.1 publish conflict
0.1.1 (2026-09-23)
- Publish of the Next.js 16.3.4 layouts port
0.1.0 (2024-06-03)
- Initial release
Components
ab-nextjs-components 0.7.1
0.7.1 (2026-11-12)
- Normalize the changelog format and backfill missing entries.
0.7.0 (2026-11-06)
- 📋 AbPropsTable (server component): accessible, responsive docs prop tables from build-time structured data. Export it from the package root or
ab-nextjs-components/ab-props-table; row/default/column/label types are exported too. An omitted default (or{ kind: 'none' }) means "No default",{ kind: 'unknown' }is explicitly unknown, and{ kind: 'value', value }renders a code value. All input is escaped text: no introspection, evaluation or raw HTML. Configurable captions/labels/column order, required/deprecated annotations, one keyboard-scrollable region, wrapping long types and light/dark token fallbacks are included.
0.6.0 (2026-11-04)
- ⚠️ Breaking:
htmlis nowtrustedHtmlon AbCodeBlock, AbDemoCode and AbPreviewCode. The string goes intodangerouslySetInnerHTMLwithout sanitizing, so pass only HTML you render yourself (e.g. ShikicodeToHtml), never user input. Preferhighlighted/ children. Rename the prop to upgrade. - ⚠️ Breaking (markup): code-block focus moved. The focusable, named element is now the scroll wrapper (
[data-ab-part="code-block-code"],role="group"), not the<pre>. The old regex that patchedtabindex/aria-labelinto the<pre>HTML (it broke on>inside attributes) is removed; it was internal, so no export changes. - 🔐
warnAbRiskyHtml: a dev-onlyconsole.warnwhentrustedHtmlcontains<script, anon…=handler,javascript:,<iframeorsrcdoc. Silent in production. It is not a sanitizer. - ✨ AbPreviewCode (server component): a docs Preview / Code pair. AbContentTabs over an AbDemoBox preview and an AbDemoCode source block; both panels are in the server HTML. Nothing is parsed or evaluated from
code. - 🧰 Preview toolbar (
AbPreviewStage, a small client island): arole="toolbar"with one tab stop (←/→/Home/End), a light/dark toggle (aria-pressed) for that preview only, a reload button that remounts the preview, and an open-in-new-tab link withhref(target="_blank" rel="noopener noreferrer"). 44px targets; names vialabels.toolbar,labels.dark,labels.reload,labels.open. New AbPreviewCode props:toolbar(defaulttrue) andhref. Exported:AbPreviewStage,AbPreviewStageProps,AbPreviewStageLabels. - 🧪 AbDemoBox: server-safe, with
scheme('inherit' | 'light' | 'dark'), a scopedalignand an optionallabel(a named region). - 🗄️ Drawers inside the preview scope: AbDrawer hosts its layer in the nearest
[data-ab-preview-scope], so a drawer demo stays inside its box. The selector is exported asAB_PREVIEW_SCOPE_SELECTOR. - 💻 AbDemoCode is built on AbCodeBlock: escaped
<pre>, SVG copy button, polite "Copied". - 🔣 Icons:
refreshandopen_in_new(ab-nextjs-icons) joinAB_ICON_BUILTINS. - ⌨️ One tab stop per code block: the scroll wrapper is the stop, so arrow keys scroll long lines. A Shiki
<pre tabindex="0">from children is dropped; inside atrustedHtmlstring it is set to-1after hydration (the string is never edited, so before hydration it is still a second stop). - 📋 Copy-button gutter: the code scroller ends 48px short of the copy button, so long lines never run under it (390px phones too).
- ♿ AbContentTabs: a tabpanel is a tab stop only when it has no focusable content (checked after mount and on changes). The server render keeps
tabIndex 0on every panel, so hydration matches.AB_FOCUSABLE_SELECTORis exported.
0.5.0 (2026-11-04)
- ⚠️ Heads-up (default change, not breaking): AbSidebar and AbNavDrawer now light only the deepest matching item, so
/docsno longer lights up alongside/docs/xon/docs/x. A parent still lights on routes that have no listed child (/docs/y). PassactiveMatch="prefix"for the old look. - 🐛 One active item in AbSidebar and AbNavDrawer: new
activeMatch?: 'best' | 'prefix' | 'exact'(default'best') on both, plus a per-itemexact?: booleanoverride (true= never a parent match,false= parent matching allowed under'exact'). Query strings, hashes and trailing slashes are ignored. AbNavDrawer also getslocales, and both share one helper. - ✨ Exports:
getAbActiveHrefs,matchAbHref,normalizeAbHref,flattenAbNavItems, and the typesAbActiveMatch,AbActiveMatchableandAbActiveMatchOptions.isAbSidebarActivestays, and it now ignores query strings, hashes and trailing slashes too. - 📝 Neutral wording: comments, test names, the README and this changelog no longer name reviewers. The AbProgressChips demo data uses a neutral step name ("Simmer").
- ✅ G59, stacked drawers and Escape (confirmed, regression test added): with two drawers open, Escape closes only the topmost one, and focus returns to that drawer's trigger. A second Escape closes the next one. This works across scopes (app, main, aside). An Escape an inner widget already handled closes nothing. The shared open-drawer stack in
AbDraweralready did this, so there is no runtime change.
0.4.2 (2026-11-04)
- 📌 Theme pin dropped (#23): the D33 release-age pin for
ab-nextjs-theme@0.3.9expired, so it's removed. The range stays^0.3.9.
0.4.1 (2026-11-03)
- 🌙 AbCodeBlock (#22): the dark surface sets
color-scheme: dark, so scrollbars and form controls match. - 📱 Breadcrumbs at 768px: the trail gets a real width and is clipped before the search field, so the search field no longer covers it and the Docs crumb stays clear (24px target).
- ✂️ Current crumb: it ellipsizes on its own box ("Insta…") instead of being clipped at both ends.
- 🔤 AbCallout: the callout text size no longer follows global
body, pfont sizes. - ⬆️ Theme:
ab-nextjs-theme^0.3.9.
0.4.0 (2026-11-03)
- ✨ MDX docs components (#21):
AbCallout,AbCodeBlock+AbCodeBlockCopy,AbContentTabsandAbDocPager. - 🎯 Breadcrumbs: 24px crumb targets.
- ♿ Code blocks: the
preis focusable, so keyboard users can scroll it. - ⬆️ Theme:
ab-nextjs-theme^0.3.8.
0.3.3 (2026-11-02)
- 📌 Icons pin dropped (#20): the release-age pin for
ab-nextjs-iconsis removed. - 🎯 AbSearchTrigger: the small size is 46px.
0.3.2 (2026-11-01)
- 🎯 44px tap targets (#19) across the touch controls.
- ♿ AbTocPromo: renders as a
divwith a label. - 🔍 AbMobileHeader: a
searchslot. - ✨
AB_THEME_MODE_ICONS: the theme mode glyphs, withbrightness_autofor system mode. - 🎯 AbThemeToggle:
iconShowstarget fix. - ⬆️ Icons:
ab-nextjs-icons^0.2.7.
0.3.1 (2026-10-30)
- 🧱 404 gaps (#18): new
AbErrorHero, plus the other 404 page fixes.
0.3.0 (2026-10-30)
- 🔥 Prune (#17): 5 unused components are removed:
AbKeyFeature,AbMainHeadline,AbPreview,AbSwitchBackandAbTestHello(and their server twins). ⚠️ Breaking if you imported them.
0.2.3 (2026-10-29)
- 🎪 AbPlaygroundScene: v6 scenes (welcome, all,
variant="auto"), real export names in captions, a CSS locale cycle with stills, frame-card ratio, and the v6 card token - 🔶 AbButton: owns per-type padding/size via
--ab-button-*tokens;size="lg",color="bronze"and opt-incolor="card"; the server twin uses the client CSS (single source, twin guard) - 🎠 AbCarousel:
autoHeight, headlessAbCarouselProviderwith a region hook,useAbCarouselKeys(default scope'main','document'opt-in); each part resolves its own accent - 📱 AbMobileHeader: extra row and 3-state theme, globe wiring, link fallback, compact mode, no-JS
<details>language list,barAtto hide the bar from 768px - 🧩 AbThemeModeProvider (
./ab-theme-mode) so every theme toggle shares one mode; export map guarded - 🔀 AbFlowDiagram: frame mode, rich nodes and dots
- 📥 AbBottomDrawer: close on swipe down and refocus its trigger
- ⬆️
ab-nextjs-animations^0.2.5andab-nextjs-theme^0.3.7(with D33 pins at release time)
0.2.2 (2026-10-21)
- 🌍 AbPackagePreviewComponents
labels({ button, chip, switch }); English defaults unchanged, the 0.2.1button/chipprops still work
0.2.1 (2026-10-21)
Sidebar profile
- ✨ AbSidebar
profileprop (opt-in): a 40px profile button at the bottom left opens AbSettingsDrawer. Signed out it shows the profile glyph; signed in the initials ("AU") on the container colour, or the photo masked to a circle, plus the name when expanded. Rendered on the server and hidden by CSS below 1180px (no flash); the collapsed rail names it with an AbBalloon tooltip. Label vialabels.profile(default "Profile and settings") - ✨ New
AbSidebarProfileButton(standalone) andAbProfileAvatar+getAbInitials(client + server) - ✨ AbSidebar
footerslot (bottom left, sticky) - ✨ AbBalloon
strategy="fixed": the tip is placed in the viewport, so the collapsed sidebar rail (a scroller) can't clip it; rail items + the profile button use it - ✨ AbTocPromo: the aside "New" card (mock .toc-card: 12px radius + padding, card colour, 13px title, 11.5px subtitle)
- ✨ Home preview tiles for AbPackageCard
preview:AbPackagePreviewCurve(ease-out),AbPackagePreviewCode(*kw*/~dimlines),AbPackagePreviewComponents(button · switch · pill chip); preview children no longer stretch - ✨
useAbEdgeSwipe({ maxWidth })+AB_ASIDE_DRAWER_MAX_WIDTH(1179): the right drawer swipes on mobile and tablet only - 🐛 Drawers: a swipe-opened drawer returns focus to the header / brand logo by default (
AB_DRAWER_RETURN_FOCUS; AbAppBar's brand getsdata-ab-part="app-bar-brand") - 🐛 Drawer rows: hover tints only on hover-capable pointers, so the nav drawer opens with no highlighted row
- ✨ AbSettingsDrawer: the Account section is back on top (
account,onAccount,onSignIn), plusonHelp/onAboutrows after Language (labelsaccount,signIn,help,about)
0.2.0 (2026-10-21)
Includes everything planned for 0.1.15, which is not released separately.
⚠️ Heads-up (default changes, not breaking)
- ⚠️ AbVersionSwitcher
labelnow defaults to''(it was'Docs'), so the control shows just "v0.2.x ▾". Its accessible name is thenVersion v0.2.x. Passlabel="Docs"for the old look. - ⚠️ AbAppBar compact bars (
density="compact") now show the search pill below 768px by default (it used to be a 40px icon circle). PasscompactSearch="icon"for the old look.
Drawers v2
- ✨ AbDrawer:
tier,swipe,snapPoints/defaultSnap/fullOnly/onSnapChange,handleLabels,centerIn="main",initialFocusselector,returnFocus,closeIcon,headerStart(all additive) - ✨ Gesture kit:
AB_SWIPE,resolveAbSheetRelease,resolveAbSideRelease,isInAbEdgeZone,createAbVelocityTracker,useAbEdgeSwipe - ✨ New: AbSettingsDrawer, AbNavDrawer, AbTocDrawer, AbSearchDrawer (combobox/listbox, recents, grouped results), AbMobileHeader
- 🔥 Docs removed from examples; AbVersionSwitcher
labeldefaults to '' - 🐛 Initial focus no longer scrolls the layer; returnFocus takes the first visible match
- ♿ AbVersionSwitcher: with no
label, the accessible name isVersion <version> - 🧯 AbSearchDrawer: a rejected or throwing
searchclears to "no results"; no stale results, no unhandled rejection - 🆔 AbSearchDrawer: group heading ids are sanitised (
[A-Za-z0-9_-]) and indexed, so they stay valid and unique - 📌 AbMobileHeader needs ab-nextjs-core ≥ 0.2.1 with
mobileHeader="main" - 🤖 Edge swipes work on Android Chrome: touches are read from touch events, and
touchmoveis non-passive only during an edge press, withpreventDefaultonly once the move is sideways. Vertical scrolling from the edge zone and sideways code blocks are unaffected; checked in WebKit and Chromium touch emulation.
From 0.1.15
- 🔎 AbAppBar
compactSearch('pill'|'icon'): below 768px, adensity="compact"bar now shows itsvariant="field"search as the mock's 34px "Search ⌘K" pill, not a 40px icon circle. It is the same element, styled by CSS, so there's still one hotkey listener. The default is'pill'for compact bars; comfortable bars keep the icon, as before. - ⚠️ Heads-up:
density="compact"bars now show the search pill below 768px by default (they used to show a 40px icon circle). PasscompactSearch="icon"to keep the old look. - 🏷️ AbSearchTrigger
compactLabel: an optional short label (e.g. "Search") that the compact bar shows on mobile instead oflabel("Search docs…"). Only one is ever displayed. The key cap's space is now its own span, so the pill shows "⌘K". - 🏷️ AbSidebar
logo: a 60px (--ab-header-height) logo row aboveheader, like mock 06's.sb-logo. With core ≥ 0.2.1 panes it only shows where the app header is hidden (tabletHeader="main"at 768–1179px). - 🧩 AbLocaleSwitcher
presentation="inline": no trigger and no popover; it renders a labelled group of 48px rows (--tint+--accent-textwhen active, a check mark,lang/hreflang) in place. Put it inside the mobile app drawer. Link rows mark the current locale witharia-current, button rows witharia-pressed. Rows are exactly 48px (44px minimum), 8px apart, with an 18px bronze 2px-stroke check (--ab-color-btnlight,--ab-color-accentdark). Usedividerwhen it goes last after nav / theme items, andshowLabel={false}when it's the drawer's only content (title the drawer "Language"). See the snippet inab-locale-switcher/index.tsx. The inline list is its own component (AbLocaleSwitcherInline, also exported), so changingpresentationat runtime remounts cleanly. - 🏷️ AbBottomDrawer title: Mulish (
--ab-font-title) 16/800 (was 700). The bottom padding stays 16px + the safe area. - 🔗 AbAppBar
searchCompact: a node shown instead ofsearchbelow 768px (both rendered, CSS picks). Pass<AbSearchTrigger size="sm" href="/docs" label="Search" />for the mock's mobile pill: a plain link to /docs, 114px wide (--ab-app-bar-compact-search-width) in a compact bar, with no ⌘K cap and no hotkey (noonOpenmeans no shortcut;hotkey={false}also turns both off). - ♿ Inline AbLocaleSwitcher
ariaLabel: the group's accessible name. It defaults tolabel, whether the label is visible or hidden. - 📱 No globe on the mobile bar: pass the bar's actions without the locale switcher as
compactActions(from 0.1.13), and render the inline switcher in the app drawer. - 📝 AbAppBar
searchCompactdocs: a hotkey trigger passed to bothsearchandsearchCompactregisters ⌘K twice; give only oneonOpen(orhotkey={false}on the other). - ✂️ AbAppBar compact pill: a longer (translated) label ends in an ellipsis inside the 114px pill.
0.1.14 (2026-10-20)
- ⬆️ Peer + dev range:
ab-nextjs-theme^0.3.5 (was ^0.3.4), for the Home tokens. It has a D33 release-age pin that expires 2026-10-21T20:40:07Z. Components doesn't depend onab-nextjs-core, so no core range changed.
- 🎯 AbThemeToggle icon shows the target (20:57):
variant="icon"+appearance="thumb"now shows the mode a click switches to (moon in light, sun in dark). NewiconShows?: 'current' | 'target'(defaulttargetfor thumb,currentotherwise, so fill is unchanged) andlabels.switchTofor names like "Switch to dark theme". Segmented toggles are unchanged. - 🌿 Sage chip AA: the
tone="sage"fallback text is now #566a58 (theme 0.3.5 value), ≥ 4.5:1 on the unchanged tint. Tested. - ♿ AA fallbacks and the sidebar badge:
AbBreadcrumbsandAbListnow fall back to the AA faint #807062 (was the mock's #9c8c80). On the active--tintrow, thebadgeVariant="text"sidebar badge inherits--accent-text, because faint on tint is only 3.9:1. Tested. - 🏠 Home fidelity components (spec §5, approved):
AbList+AbListItem(P13): bordered row lists with a media tile or badge, title, meta and chevron. A row withhrefis a single link.AbBreadcrumbs(P2): the tablet main bar crumb.AbVersionSwitcher(P9): the sidebar "Docs v0.2.x ▾", which opens an AbMenu, with a no-JS<details>fallback.AbBottomDrawer: the mobile bottom drawer (D40), whichAbLocaleSwitcher/AbAppBarnow use forside="bottom".AbDrawerListgainsas.- They read the
ab-nextjs-theme0.3.5 Home tokens (--ab-color-card,--ab-color-faint, …), with the light mock values as fallbacks. - 🏠 Home variants on existing components (the P4–P19 items; everything is opt-in, defaults unchanged):
AbAppBar:density="compact"(height from core's--ab-header-height, 13.5px links, brand column--ab-app-bar-brand-width236/270),divider,moreMenu={false}(P4/P5/P19).AbSearchTrigger:variant="field"(300×36, one⌘ Kcap, "coming soon" only in the tooltip and SR text) andsize="sm"(the 34px mobile pill) (P6).AbThemeToggle:appearance="thumb"(28px segments, raised thumb, filled active glyph) (P7).AbSidebar:density="compact",activeShape="rounded",badgeVariant="text", sectionitemSize="sm", andcollapseButtonVariant="outlined"(32px<</>>) (P8/P9).AbPackageCard: the Home layout withpreview,titleanddescriptionLines, version and tag chips and a trailing arrow (P10). P11variant="all"was not built (dropped by D1).AbInstallSnippet:variant="terminal"(underline tabs, copy button in the tab row, horizontal scroll instead of clipping) (P12).AbToc: afooterslot (P14). The TOC now uses the Home sizes: 11px heading, 13px links on 30px rows.AbButton:shape="rounded",size="md"(40px, 44px below 768px),type="secondary".AbChip:size="sm",shape="rounded",mono,tone="accent" | "sage"(P16).AbNavbar:indicator="none"andblur(P18).AbIconButton:aria-expanded/aria-controlspass through, and a newiconSize.AbVersionSwitcher: the accessible name is"{label} {version}", so it contains the visible text (WCAG 2.5.3).- AbList rows are 59/60px, like the mock.
AbBottomDrawer: the sheet takes focus on open, the ✕ is 44px with an 8px hover tint and a:focus-visible-only ring, plus 16px + safe-area bottom padding and the 36×4 handle. It reads the theme 0.3.5 scrim, handle and sheet-edge tokens.AbDrawergainsinitialFocus.- 🎨 Home tokens first: borders, hovers, active rows and focus rings read
--ab-color-border/-hover/-tint/-accent-text/-accent(theme 0.3.5) before the M3 tokens. On theme 0.3.5 the rings turn bronze and active rows turn--tint. - 🗄️ AbDrawer +
useAbDrawer(new, G53, D38). The drawer is scoped toapp,mainoraside. It renders into a layer inside that layout box and never scrolls the document. Sides aretop,bottom,leftandright, plus logicalstartandend. - Accessibility:
role="dialog",aria-modal, a labelled panel, a focus trap that restores focus to the opener, Escape and scrim close, and the rest of the scope isinert. - It uses the 240ms
ab-nextjs-animationsslide, which reduced motion turns off. - Without JS it renders as an in-flow
<section>(D41). - 📋
AbDrawerList+AbConfirmDrawerpresets (new, D38/D40). - 🌍
presentation="menu" | "drawer" | "auto"(G56) onAbLocaleSwitcherand on theAbAppBarMore menu. The drawer is an app-scope bottom sheet, andautouses it below 768px. The default staysmenu.
0.1.13 (2026-10-20)
- 🔗
AbLinkProvider(new,ab-nextjs-components/ab-link): every component link now renders throughAbLink, so an app can inject a locale-awareLinkonce.useAbLink,AbLink,AbLinkComponentandAbLinkPropsare exported. It's the onlynext/linkimport (test-guarded) - 🔣 AbIcon (G2): SVG first, non-breaking fallback. Registered / explicit / built-in names render AbIcons SVGs. An unregistered name still renders the Material Symbols ligature (
data-ab-icon-fallback="font", as before) and warns once in development, so nothing goes blank in a patch; register every name before the app drops the font.AbIconRegistrar(ab-nextjs-components/ab-icon/registrar) is the server-safe way to register icons from a Server Component layout. 7 more built-ins:chevron_left,chevron_right,menu,more_vert,search,close,expand_more. AbMenu icons are AbIcons now (filled when selected) - 🧭 AbSidebar v2 (G40): sections,
activeHref, filled active icon,aria-current, badges, one child level, a 72px rail with balloon tooltips, and a collapse button (aria-expanded,aria-controls, hidden without JS). Client and server twins shareab-sidebar/view. Legacylinks/page/brandLabelstill work - 📱 AbNavbar v2 (G41): link and button items, filled active icon,
aria-current, safe-area padding. The server twin takes link items only - 🧱 AbAppBar (new, G43): brand, search, nav, actions, sticky with a hairline, and a "More" overflow
AbMenubelow 1180px (Escape and outside click close it, focus goes back to the trigger). The nav stays inline without JS - 🔎 AbSearchTrigger + AbKbd (new, G44): an
hrefalways renders a real<a>(works without JS, D24a:/docs); withonOpentoo, JS intercepts plain clicks and opens the dialog. The ⌘K / Ctrl K hint andaria-keyshortcutsappear only while a hotkey is listening.shortcut(alias ofhotkey),compact(icon-only, label for screen readers),comingSoonwitharia-disabled. The hotkey is a local listener becauseuseAbHotkey(G48) is not in hooks 0.1.7 - 🃏 AbCard + AbPackageCard (new, G45): one link per card,
ab-motion-interactivetiming, a 2px hover lift on laptop and up with a real pointer, and no lift under reduced motion - 📑 AbToc (new, G46): plain
#idanchors,aria-current="location", and an optionalonNavigate(forscrollToAbSection) - 📜 Panes scrolling (D35/G55): with core 0.1.6 the page never scrolls, the main pane does.
getAbMainScroller()/AB_MAIN_SCROLLER_SELECTOR([data-ab-part="main-content"]) fromab-nextjs-components/ab-tocgive therootforuseAbScrollSpy(call it in an effect or handler, never during render;import { getAbMainScroller } from 'ab-nextjs-components/ab-toc', also on the root barrel withAbToc) and thecontainerforscrollToAbSection; a plain#idjump scrolls the pane on its own. In panes the AbAppBar is the header row outside the scroller, so it stays put without the document scrolling - 🌍 AbAppBar active link: without
activeHrefit uses the pathname minus the AbLinkProviderlocales(or its ownlocalesprop), like AbSidebar / AbNavbar, so/fr/docsmarks Docs - 🧩 AbPackageCard names wrap at hyphens: a
<wbr>after each-(toAbPackageNameParts), so narrow cards showab-nextjs-/componentson two lines instead of an ellipsis;overflow-wrap: anywheresplits a part only when it alone is wider than the card. Checked in WebKit at 1280 (no clipping, no overflow) - 🔑 AbSidebar item
id: optional, used as the React key (id ?? href) so two items may share an href - 🆔 AbIcon per-instance ids: every render suffixes the SVG ids and
url(#…)refs withuseId()(scopeAbIconIds), so two filled Homes never share a mask and a hidden twin can't turn the active Home into a solid square - 🎈 AbBalloon a11y:
role="tooltip",aria-describedbyon the trigger, shows on focus, a 300ms hover delay (AB_BALLOON_HOVER_DELAY), Escape dismisses,popInskipped under reduced motion. Without JS, CSS shows it on focus or hover. Newplacementanddelayprops - 🚫 JS-off fallbacks: AbInstallSnippet hides copy (the command shows the pnpm default). AbLocaleSwitcher with
getHrefrenders a<details>list ofhreflanglinks - 📱 AbAppBar compact phone layout (< 768px): tighter gaps, a shrinkable brand, an icon-only search pill and
compactActions(shown instead ofactions), so nothing overflows at 390px - 🔘 AbButton forwards any
aria-*/data-*prop (e.g.useAbAsideToggle().props), and thehrefvariant gets the theme's padding and colours (it rendered 20px tall with none). AbIconButton draws its glyph with AbIcon (filled whileactive, oriconFilled) - 🚧 AbNavbar button items take
disabledandcomingSoon(inert,aria-disabled, a "Coming soon" tag) - 🌍 Locale-aware active state:
AbLinkProvidertakeslocales; AbSidebar / AbNavbar strip/frfrom the pathname (oractiveHrefon the server twins, via alocalesprop).stripAbLocalePrefixis exported.AbLinkProvideris generic over the link's props, so next-intl'sLinkneeds no cast - 🃏 AbCard / AbPackageCard take
id; AbPackageCard takesmedia, and names never wrap mid-name (ellipsis +title). AbToc takeslabel(alias oftitle). AbSidebar labels accept any node (labelTextnames the rail) and use M3 label-large - 💻 AbInstallSnippet puts the command on
--ab-color-code-surface/--ab-color-on-code-surfacewith--ab-font-code(theme 0.3.4, with fallbacks) - 🛡️ Release age: the expired
ab-nextjs-theme@0.3.3exclude is gone,.npmrcno longer setsminimumReleaseAge(pnpm 11 ignores it there), andminimumReleaseAgeStrict: trueis on. Tests guard all three; the per-entry expiry allowlist stays ready for scoped D33 exemptions - 📝 Every code file carries the full house header with
@authors; the npm author email is abrahamukachi@gmail.com - 🧪 The release-age guard moved to
__tests__/release-age.test.ts: excludes must be our own exactab-nextjs-*versions and fail once expired - ⬆️ Peers + dev:
ab-nextjs-theme ^0.3.4,ab-nextjs-icons ^0.2.4(the filledsearchtab icon),ab-nextjs-hooks ^0.1.7 - ⏳ D33: exact
minimumReleaseAgeExcludepins for the three siblings in the lockfile that are < 24h old: `ab-nextjs-icons@0.2.4`, `ab-nextjs-theme@0.3.4`, `ab-nextjs-hooks@0.1.7`, each until publish + 24h (2026-10-21 17:15 / 17:25 / 17:28 UTC). `release-age.test.ts` fails after that and rejects pins that aren't in the lockfile
0.1.12 (2026-10-16)
- ♿ AbInstallSnippet tabs pass AA in every state. Each state now paints an explicit text/background pair from the live palette instead of a transparent tab and a 12% bronze tint: inactive
on-surface-variantonsurface-container(8.04:1 light / 9.67:1 dark), hoveron-surfaceon an 8%on-surfacestate layer (12.63:1 / 10.39:1), active and active + hoveron-primary-containeronprimary-container(13.28:1 / 7.22:1). Fallbacks are the light bronze palette, so it also passes without the theme - 🥉 New
AbButton type="filled"(client + server): solid bronze--md-sys-color-primarywithon-primarylabel and icon. Setsdata-type="filled", styled with hover / focus / disabled byab-nextjs-theme@^0.3.3; a.isFilledfallback paints the rest state on older themes.AbButtonTypegains'filled' - ⬆️
ab-nextjs-theme ^0.3.3(peer + dev, was^0.3.1) for the filled hover / focus / disabled states and the button icon-colour fix. The.isFilledfallback stays for apps still on an older theme - Tests: contrast computed from the theme palette (light + dark, every state, plus the no-theme fallbacks); filled type on client + server twins. Checked in WebKit (ratios above; filled 6.47:1 light / 7.74:1 dark)
0.1.11 (2026-10-15)
- 🐛 AbFlowDiagram: nodes no longer cover the header in small boxes. At 390px wide the Live Playground's top node ("core") sat under the "Live Playground" header. With a header (title, live dot or caption) the root now gets
data-ab-header="true", and nodes + wires live in a stage that starts below the header band:--ab-flow-diagram-inset-top(default2.75rem, tunable). Nodex/ystay 0–100 but now map onto that stage, and the wires share the same box so they still meet the nodes. Without a header the stage is the full card (unchanged) - 📏 AbFlowDiagram nodes scale with the card:
container-type: inline-sizeon the root; node text, padding, radius and the hub glow use clampedcqisizes (13px on a 760px card, 11px at 390px) - 🪐 AbFlowDiagram: side nodes are never clipped (s04's
--ab-color-bronzeand s07'sreduced motionwere cut off at the card edge in a 390px box). The orbit now scales with the box. Each node is anchored at the same fraction of its own box as its position (translate(-x%, -y%)via--ab-flow-node-x/-y;x = y = 50is the old centring), so the outer ring pulls in by exactly the node's width, and the wire end stays inside the pill. Nodes + wires also sit inside a side margin,--ab-flow-diagram-inset-x(default0.5rem), and an over-long label ellipsises (max-width: 100%). Positions are clamped to 0–100 like the wires - Tests: header flag, stage insets shared by nodes + wires, 390px geometry, clamped scaling, proportional anchoring + side margin, s04 / s07 orbit geometry at 390 / 760px × 276 / 380px. Checked in WebKit at 390px: "core" top 9px → 53px (header ends at 33px); no node overlaps the header or is clipped at 390 / 760px. After the orbit fix: s04 + s07 have no node clipped (x or y) or over the header at 390 / 760px wide × 276px / 380px / default-ratio heights (before: 5 nodes clipped at 390px, 2 at 760px)
0.1.10 (2026-10-15)
- Motion comes from ab-nextjs-animations (>= 0.2.4, now a required peer): no component CSS declares its own
transition,animationor@keyframesany more. Each component imports the package stylesheet it needs: - AbCarousel:
slide-step(direction-aware enter / leave viadata-ab-direction) +motion(buttons, dots) - AbFlowDiagram:
wire(--ab-wire-*tokens;data-ab-paused; 3 loops on phones unlessloopsis set) - AbThemeToggle, AbSearchbar, AbSplash fade:
motioncolours - AbIconButton:
motion(expands→ab-motion-lift,shrinks→ab-motion-press) - AbProgressChips:
motionsize - AbLinearProgress:
motiontransform +progress-sweep - AbCollapsible, AbBrand:
motiontransform - AbLikeButton / AbSearchbar spinners:
spin - Reduced motion (OS, or
reducedMotion="always"viadata-ab-reduced-motion) is handled by the package - AbCarousel: context gains
direction+previousIndex;--ab-carousel-duration/-ease/-shiftmap onto--ab-slide-step-*; the old positional slide offsets are gone - Peers:
ab-nextjs-iconsandab-nextjs-animationsare no longer optional. All four Welcome peers (and devDependencies) use caret ranges:ab-nextjs-hooks ^0.1.6,ab-nextjs-theme ^0.3.1,ab-nextjs-icons ^0.2.3,ab-nextjs-animations ^0.2.4 - Motion exceptions (named, test-guarded): the dialog list-item transition (
css/dialog.css) and the self-animating spinner SVGs stay local - Lockfile: refreshed against the published hooks 0.1.6, theme 0.3.1, icons 0.2.3 and animations 0.2.4 (
pnpm install --frozen-lockfileverified on a freshnode_modules).pnpm-workspace.yamlexempts exactly the five Welcome releases (fonts 0.2.5 included) from pnpm 11's 1-dayminimumReleaseAge, and that block should be removed once they are a day old
- AbCarousel (G31): new subpath
ab-nextjs-components/ab-carousel(+ server-safeab-carousel/helpers). Compound partsAbCarousel,AbCarouselTrack,AbCarouselSlide,AbCarouselPrev,AbCarouselNext,AbCarouselDots,AbCarouselCounter+useAbCarousel(). APG carousel semantics (aria-roledescriptioncarousel/slide, "n of total" labels, polite live region, inactive slidesinert+aria-hiddenafter hydration), RTL-aware ←/→ + Home/End scoped to the region, swipe viauseAbSwipe, reduced motion viauseAbReducedMotion+ CSS, controlled / uncontrolled, i18n labels on every control,AB_CAROUSEL_NOSCRIPT_CSSfor the no-JS stack - AbIconButton (G6):
aria-label+titlenow sit on the interactive element (never the wrapper span); newlabelprop (falls back totitle); thehrefvariant is named and no longer hasrole="button"; the ligature glyph isaria-hidden; disabled links leave the tab order; loading setsaria-busy - AbButton (G22):
startIcon/endIcon,badge+badgeTone(e.g. "Coming soon"),disabledReason(visually hidden text appended to the accessible name),focusableWhenDisabled; with a badge / reason the button usesaria-disabled(stays focusable, clicks guarded) instead of nativedisabled; disabled links render asspan role="link" aria-disabled; links no longer getrole="button"; server twin matches - AbThemeToggle (G34, new,
ab-nextjs-components/ab-theme-toggle): light / dark / system radiogroup (roving focus, RTL arrows, icon-only variant, i18n labels), driven byuseAbThemeMode();getNextAbThemeModehelper - AbChip / AbPill (G36, new, server components):
ab-chip,ab-pill - AbInstallSnippet (G35, new): pnpm / npm / yarn / bun tabs (APG tablist), choice shared via
useAbLocalStorage, copy button with polite status,data-ab-swipe-ignore;getAbInstallCommandhelper - AbLocaleSwitcher (G7, new): menu button +
menuitemradio, typeahead,onSelectorgetHref(+hrefLang) - AbIcon (G2, new,
ab-nextjs-components/ab-icon): AbIcons as inline SVG; client twin resolvessvgprop →registerAbIconsregistry → Material Symbols font (never imports the full map); server twin renders any icon; weights 100–700 map to the icons package stroke table; 8 built-ins (arrows, theme, language, copy / check) imported per icon fromab-nextjs-icons/ab-icons/icons/*(needs icons >= 0.2.3) - AbCarousel: prev / next arrows now render through AbIcon (weight 300);
--ab-carousel-icon-strokeremoved - AbFlowDiagram (G38, new, server component):
figure role="img"scenes, CSS-only draw + pulse, paused while inactive, 3 loops on mobile, reduced motion shows the poster frame;getAbFlowEdgePathhelper - Dev:
happy-dom+@testing-library/reactfor DOM tests
0.1.9 (2026-10-14)
- AbLogo:
wordmarkprop (true→ "Elements", or any string) renders a mark + Quicksand Bold lockup (font-quicksand-boldfrom ab-nextjs-fonts);colorprop (--ab-logo-color); light / dark (html.dark) - AbLogo fix:
nakedwith nosrcnow masks with the shipped Ab mark (via--app-logo-urlfallback) instead of a bronze square when the chrome CSS isn't loaded - AbSplash (new,
ab-nextjs-components/ab-splash): brand overlay +abSplashGateScript/buildAbSplashGateScript({ locales, defaultLocale }); root-path RegExp built from locales minus the default and JSON-injected; skipsnavigator.webdriver/ bot UAs; standalone viamatchMediaORnavigator.standalone; each storage get/set in its own try (failed get = seen);data-ab-splashset last; page behind isinertwhile shown; trackmin(18rem, 28vw) - CSP:
ab-nextjs-components/ab-splash/csp→getAbSplashGateSha256(script),buildAbSplashGate(options),AB_SPLASH_GATE_SHA256 - AbLinearProgress (new here,
ab-nextjs-components/ab-linear-progress): ported from the reviewed core work — determinate / indeterminate,color, reduced motion, dark, RTL sweep, emptyaria-labeldropped; shipped CSS module. AbSplash uses it, so noab-nextjs-corepeer is needed - CSP (P1):
ab-nextjs-components/ab-splash/cspnow ships compiledcsp.mjs+csp.d.ts(Node-loadable fromnext.config.*);build:cspscript,check:publish/prepublishOnlyfail when it's stale - AbSplash: unmount removes
data-ab-splash+inert; scroll lock gets the same 1.2 s CSS failsafe; surfaces#FFF8F3/#1A1310(mocks) - Tooling:
esbuild ^0.28.2is now an explicit devDependency (direct inpnpm-lock.yaml; frozen install verified) - AbSplash: StrictMode-safe teardown (
scheduleAbSplashFinish/cancelAbSplashFinish); overflow failsafe verified in Chromium + WebKit - Tooling:
typecheckscript,types/css.d.ts, vitest automatic JSX,scripts/build-demo.mjs
0.1.8 (2026-10-05)
- Chrome styles: dialog, toast, logo (
span.app-logo), spinner, and empty-state doodle CSS + SVG assets now ship here via@import "ab-nextjs-components/styles.css"(import afterab-nextjs-theme/styles.css) - AbLogo: comments corrected — mask fallback
--app-logo-urlis owned by this package’s chrome CSS, not the theme
0.1.7 (2026-10-05)
- AbNavbar: root
<nav>setsdata-ab-part="bottomBar"(client + server)
0.1.6 (2026-10-05)
- AbSidebar: renders
<nav data-ab-part="sidebar">(was<aside>) so aside dialogs/menus never hit the sidebar - AbMenu: sets
data-id={id}(keepsid) anddata-id/menu-itemon items souseAbMenucan open it; cancel isli[role=close-menu] - AbLogo: ships
ab-logo/ab-logo.svgand defaultssrcto an inlined data URI of that asset; mask types withoutsrc/maskdefer toab-nextjs-theme--app-logo-url
0.1.5 (2026-10-03)
- Publish to npm automatically from GitHub Actions with Trusted Publishing (OIDC + provenance, no NPM_TOKEN)
nextpeer is now^16.3.4; dev dependency on ab-nextjs-hooks comes from the registry
0.1.4 (2026-09-23)
- Release from
mainafter merge of PR #1 (Next 16.3.4 + Phase 1–5 ports).
- Port (client): AbBrand, AbName, AbNavbar, AbSidebar, AbText, AbTestHello, AbKeyFeature, AbMainHeadline, AbPreview, AbProduct, AbProductItem, AbSwitchBack, AbDemoBox, AbDemoCode
- Port (server): AbBrand, AbName, AbNavbar, AbSidebar, AbNavLink, AbText, AbTestHello, AbKeyFeature, AbSwitchBack
- Select/MenuItem skipped — empty on Projects (GitHub-only historically)
- Product/Preview adapted (Dexie/providers/i18n stripped); usable props API kept
- Catalog 51 Done (36 client / 15 server).
Phase 4 Port
- Port: AbSearchbar, AbSearchResult, AbPagePaginator, AbPageSwitcher, AbProgressChips, AbPrice, AbPriceTag
- Adapt: AbImage (Dexie / offline / background-removal stripped; next/image + optional fallback)
- Port (server): AbPolygon
- Catalog 28 Done (22 client / 6 server). Plain CSS modules.
Phase 2 Adapt + Phase 3 Port
- Adapt: AbBalloon (
title=locked) — Input now uses real AbBalloon - Port: AbAvatar (client + server), AbBadge (server), AbTab, AbTabs, AbMenu, AbCollapsible, AbColor, AbInfo, AbLikeButton
- Plain CSS modules; LYD brand/nav/i18n stripped; Select/MenuItem skipped (not on Projects)
Phase 2
- Ported AbIcon (client + server) — Material Symbols ligatures
- Ported AbLogo (client + server) — contained | outlined | hollow | naked; defaults from
ab-nextjs-iconslogos (#a67c52), optionalsrc/mask - Ported AbButton client from lyd-button; invented server (href →
<a>, else submit/button; no onClick) - Added minimal AbIconButton (Input dependency)
- Ported AbInput client —
useAbTogglefromab-nextjs-hooks/helpers/useAbToggle; Balloon stub viatitle=; no console.logs - Hard peers: next 16.3.4, react^19, clsx; soft optional peers: theme / icons / hooks / animations
- Plain CSS modules (no
@apply); themedata-*attrs preserved on buttons
Phase 1
- Next.js 16.3.4 / React 19 tooling scaffold + Pending catalog
0.1.3 (2026-09-23)
- Staged Phase 5 publish ahead of the 0.1.4 release from main
0.1.2 (2024-06-01)
- Stub package version bump
0.1.1 (2024-06-01)
- Version bump to 0.1.1
0.1.0 (2024-06-01)
- Initial release
i18n
ab-nextjs-i18n 0.1.0
0.1.0 (2026-10-03)
- First release: a thin i18n layer over next-intl
^4.14.9for Next.js 16.3 (localePrefix: 'as-needed', localesen,fr,es,ru) next-intl(^4.14.9) is a peer dependency, installed by the app next to this package (pnpm add ab-nextjs-i18n next-intl);icu-minify(used by the CLI) andserver-onlyare direct dependenciesdefineAbI18n,withAbI18n(precompile opt-in),createAbRequestConfig,createAbI18nProxy,createAbNavigation,AbI18nProvider- Request locale from
next/root-paramsby default (app/[locale]/layout.tsxas the root layout, static rendering withoutsetRequestLocale); next-intl's deprecatedrequestLocaleis only the fallback (Server Actions, Route Handlers) ab-nextjs-i18n/serveris server-only (import 'server-only'): importing it from a Client Component is a build error- Headless hooks:
useAbLocaleSwitch,useAbLocale,useAbTranslations,useAbFormatter, plusgetAbLocaleLabel NEXT_LOCALEcookie: only written on an explicit pick, byswitchLocaleor by a Server Action made withcreateAbLocaleCookieAction(config)(bound toconfig.localesandconfig.localeCookie: one year by default,sameSite: 'lax',path: '/',securein production). The proxy never writes it: it strips the session cookie next-intl sets on plain visits (/fr), so a saved pick is never overwritten- SEO helpers:
getAbAlternates(hreflang + x-default) andgetAbSitemapEntries - CLI
init: never overwrites, typed keys viaglobal.d.ts, 4 starter messages per locale (a plain string, an ICU{name}placeholder, a plural with each locale's CLDR categories and a rich-text tag), detects an existingproxy/middleware(.ts,.js,.mts,.mjs), prints the install command for anything missing - CLI
translate: DeepL, then OpenAI (gpt-6-luna,reasoning_effort: 'low') as the fallback, lock file, placeholder masking. Providers and keys are only needed when there is something to translate; each provider only receives its own declaredenvKeys; key values (andsk-…/…:fxkeys) are redacted from errors and reports;transgets--before the text - CLI
check(CI): missing / extra keys, placeholder and tag mismatches, ICU syntax, and plural categories missing for a locale (CLDR,Intl.PluralRules);migrate((x)to ICU{x}) - README with copy-pasteable usage examples (config, proxy with auth, layout, server/client translations, ICU, formatting, switcher, navigation and its cookies, metadata, sitemap, CLI, CI)
- Publish workflow copied from
ab-nextjs-animations(Trusted Publishing), with a typecheck step. v0.1.0 is published manually by the maintainer first so the npm trusted publisher can be linked