Skip to content

Releases: Accesserty/UI-Kit

v3.0.2

Choose a tag to compare

@Neil-Lin Neil-Lin released this 24 Oct 05:18

v3.0.2 — Screen reader fixes for forms

This patch changes how form controls report their invalid state and documents what each form control exposes to assistive technology. Tags, attributes, events and styles are unchanged.

Fixed

  • Safari with VoiceOver no longer announces empty required fields as "invalid data" as soon as a page loads. au-input, au-textarea, au-checkbox, au-switch and au-radio-group (the group and every radio) now give their inner controls aria-invalid="false" unless you set aria-invalid on the component, as au-file-upload already did. Set aria-invalid="true" when you show an error and remove it when the error is fixed. A failed browser-validated submit still announces the browser's validation message.

Documentation

  • llms.txt has a new section, "Accessibility presentation of form controls": the role, accessible-name source, forwarded attributes and focus() target of each form control.
  • llms.txt now lists au-radio-group's required, aria-describedby and aria-invalid, the accordion item's slots, and how to show an error message next to a field.
  • New demo: demo/form-registration.html, a complete registration form with an error summary, inline errors, a success message and reset. It states what native HTML, UI Kit and your own code each handle, and includes a verification record (automated runs and Safari+VoiceOver results, known issues, untested environments).

Known issue

  • The component host keeps the aria-describedby and aria-invalid you set, so the host is also exposed with the same description. Safari with VoiceOver reads the description twice for au-textarea and au-checkbox.

Verification

  • 490 unit tests passed.
  • Documentation, build-output and toolchain contracts passed; SSR stream and framework fixtures passed.
  • All Chrome browser runners passed, including the new form-registration runner.
  • All 13 Safari WebDriver runners passed on macOS.
  • Safari+VoiceOver behavior of the registration case was checked by driving VoiceOver with AppleScript.

v3.0.1

Choose a tag to compare

@Neil-Lin Neil-Lin released this 22 Oct 05:45

v3.0.1 — Toolchain refresh

This patch updates the development and build tools. Component APIs, styles, and accessibility behavior are unchanged.

Updated

  • Aligned local development and CI on Node.js 26.12.1 and npm 11.
  • Upgraded to Vite 8 and Open WC Testing 5.
  • Updated Vue, React, Nuxt, Next.js, and browser-testing dependencies.
  • Updated TypeScript to 6.0.3, retaining compiler API compatibility.

Build and testing

  • Preserved ES2022 output, classic-script bundles, standalone component files, and framework integration entries.
  • Added regression checks for toolchain consistency, version banners, and build output.
  • Made the Dropdown demo test independent of external font loading.
  • Rebuilt distribution files with the v3.0.1 version banner.

Verification

  • 485 unit tests passed.
  • 16 Chrome test groups passed.
  • All 12 Firefox groups passed across the initial run and an isolated rerun after one browser-startup failure.
  • All 12 Safari groups passed without retries.
  • SSR, hydration, type, documentation, and build-contract checks passed.

These checks do not establish complete accessibility conformance or screen-reader compatibility. Remote CI results are separate from this local verification.

Known limitations

Upstream development-dependency advisories affecting braces and node-forge remain unresolved. These dependencies are not included in the distributed component bundles.

Upgrading

No application-code changes are required when upgrading from v3.0.0. Replace the distribution files you use, keeping related framework integration files together.

Plain HTML usage still requires no Node.js installation, npm packages, or build step. Components retain zero runtime package dependencies.

v3.0.0

Choose a tag to compare

@Neil-Lin Neil-Lin released this 16 Oct 15:34

Accesserty UI Kit 3.0.0

3.0.0 is a major release. Vue, Nuxt, React and Next.js can now bind the form
components the way they bind native fields, and accordion, tabs and breadcrumbs
can render their Shadow DOM on the server. The component tags, attributes and
properties are unchanged, but custom events are renamed and a few other
details change. Read "What breaks" and "How to upgrade" below before you
replace your copy of the kit.

Plain HTML pages keep working the same way: copy a file, add a <script> tag,
use the <au-*> elements.

Highlights

  • v-model in Vue and Nuxt on au-input, au-textarea, au-checkbox,
    au-switch, au-radio-group, au-rating and au-file-upload, following
    Vue's own rules for native fields. A group of checkboxes can share one array
    or Set, true-value / false-value work, type="number" inputs give
    numbers, and <au-radio :value="2"> gives 2. Server rendering supports it too.
  • A Nuxt module. Add one line to modules in place of a client plugin, the
    isCustomElement setting and <ClientOnly> wrappers.
  • React components for React 19 and Next.js: AuInput, AuTextarea,
    AuCheckbox, AuSwitch, AuRadioGroup, AuRating and AuFileUpload. They
    take value / checked, defaultValue / defaultChecked, onChange and a
    ref to the element. e.target behaves like a native field, with value,
    checked, valueAsNumber and valueAsDate.
  • Server rendering of Shadow DOM (Declarative Shadow DOM) for accordion,
    tabs and breadcrumbs. They have their final look and layout before any
    JavaScript runs, so the page doesn't jump when the script loads or fails.
    • Nuxt: on by default.
    • Self-hosted Next.js: one wrapper, withDeclarativeShadow. It doesn't work on
      Vercel.
    • Any other Node server: injectDeclarativeShadow.
  • Native form API on every form component: setCustomValidity() and
    form, alongside validity, checkValidity() and reportValidity().
    au-input also gets valueAsNumber and valueAsDate. Pressing Enter in an
    au-input still does not submit the form, on purpose.
  • Single-component files in dist/components/. All 15 components are there,
    each as a self-contained file plus a minified copy (tabs.min.js: 13 KB
    instead of 21 KB).
  • TypeScript declarations. accesserty-ui-kit.d.ts types every element, for
    example document.querySelector('au-tabs').selectedIndex. The React file adds
    every au-* tag to JSX with typed event details. Vue types v-model in
    templates.
  • One disabled look. Every component and native button dims to opacity 0.6,
    which keeps dark text at about 5:1 on white. Each component has a
    --au-…-disabled-opacity variable to change it.

What breaks

2.0.10 3.0.0 What to do
au-tabs event tab-change au-tab-change Rename the listener
au-carousel event slide-change au-slide-change Rename the listener
au-pagination events page-change, page-size-change au-page-change, au-page-size-change Rename the listeners
au-dropdown-item event selected au-select Rename the listener
au-file-upload event remove-file au-remove-file Rename the listener
Cascade layer of au-style.css components accesserty Rename it in your @layer order, if you declared one
Copying one component src/components/<name>.js dist/components/<name>.js or <name>.min.js Copy from dist/components/; the files in src/ are ES modules now
au-accordion-item with open in the markup Sends au-toggle when the script loads Sends nothing, because nothing changed Read item.open for the initial state
Ids inside accordion and tabs Shadow DOM Random Fixed (title, region, tab-1…) Only matters if your code read them

The old event names are no longer sent; there is no transition period. These
events keep their names: au-toggle, the native change and input on form
components, and au-tree's change.

In React, ontab-change becomes onau-tab-change. In Vue, @tab-change
becomes @au-tab-change.

Compared with 2.0.10

All fixes from 2.0.8, 2.0.9 and 2.0.10 are included.

2.0.10 3.0.0
Vue / Nuxt forms :value + @input, :checked + @change v-model (the old bindings still work)
Nuxt setup Client plugin, isCustomElement, <ClientOnly> One module
React / Next forms <au-input> tags with on… props (React 19), or a ref and addEventListener (React 18) AuInput… with value / onChange (React 19); the tags still work
Server-rendered Shadow DOM — accordion, tabs, breadcrumbs
setCustomValidity(), form — All 7 form components
valueAsNumber, valueAsDate on au-input — Yes
Validity API on au-rating, au-file-upload Missing Same as the other form components
Disabled opacity 0.35–0.65; au-input had no disabled look 0.6 everywhere, one variable per component
Event names Mixed All start with au- (except tree's change)
Single-component files src/components/*.js dist/components/*.js and *.min.js
TypeScript — Elements, events, JSX tags, Vue v-model
accesserty-ui-kit.js / .min.js 260 KB / 197 KB 252 KB / 190 KB
Integration files in dist/ — Vue, React, Nuxt, SSR (ES modules, each with .d.ts)
package.json exports ., ./min Also ./vue, ./react, ./nuxt, ./ssr, each with types
Unit tests 456 485
Browser suites (Chrome, Firefox, Safari) 10 12 (adds server rendering and single files)
Framework checks Next, Nuxt Also Nuxt v-model, Vue SPA, Next React, server-rendered Shadow DOM, TypeScript

How to upgrade

The full guide is in UPGRADING.md.

  1. Replace the kit. Copy the whole new dist/ folder over your copy. The
    integration files import each other by relative path. If you copied single
    components, copy them from dist/components/ instead of src/components/.

  2. Rename event listeners using the table above. Searching your code for
    tab-change, slide-change, page-change, page-size-change, selected
    and remove-file finds them.

  3. CSS: if you use au-style.css, copy the new src/css/ folder. Rename
    any components layer that you ordered for the kit to accesserty:

    @layer base, accesserty, components, utilities;
  4. Vue: use the kit's isCustomElement instead of
    tag => tag.startsWith('au-'), and install the plugin:

    import { AccessertyVue, isCustomElement } from './vendor/accesserty/accesserty-ui-kit-vue.js'
    createApp(App).use(AccessertyVue).mount('#app')
    // vite.config.js: vue({ template: { compilerOptions: { isCustomElement } } })

    Your :value / @input bindings keep working. Switch to v-model when you
    like.

  5. Nuxt: remove your client plugin, the isCustomElement setting and any
    <ClientOnly> you added for the kit, then add the module:

    export default defineNuxtConfig({
      modules: ['./vendor/accesserty/accesserty-ui-kit-nuxt.js']
    })
  6. React / Next.js (optional): switch form fields to the React components,
    and call defineElements() once in a client effect:

    import { AuInput, defineElements } from './vendor/accesserty/accesserty-ui-kit-react.js'
    useEffect(() => { defineElements() }, [])
    <AuInput label="Email" value={email} onChange={e => setEmail(e.target.value)} />

    For server-rendered accordion, tabs and breadcrumbs, run a custom server
    with withDeclarativeShadow.

  7. Check disabled fields if your design depends on their old opacity. Set
    --au-<component>-disabled-opacity (--au-btn-disabled-opacity for native
    buttons and pagination) to keep the previous value.

Support for 2.x

2.x gets bug fixes only. New features land in 3.x.

v2.0.10

Choose a tag to compare

@Neil-Lin Neil-Lin released this 15 Oct 01:50

Accesserty UI Kit v2.0.10

This release covers 2.0.8, 2.0.9 and 2.0.10 (the previous GitHub release was
v2.0.7). No API changes: replace accesserty-ui-kit.min.js (or
accesserty-ui-kit.js) and, if you use it, the src/css/ stylesheets with the
new files. Please read Behavior changes if your pages use right-to-left
text or count carousel events.

Fixed

  • A paused smooth scroll no longer makes <au-carousel> report extra
    slides.
    The carousel reads the current slide once scrolling settles. On a
    busy device, a smooth scroll could pause long enough to look settled, so the
    carousel reported the slide it was passing and then the real one. That sent
    two extra slide-change events, and screen readers announced both slides.
    The carousel now remembers where its own scroll is heading and reports
    nothing until it gets there. Pointer, wheel or touch input hands control back
    to the user, and after one second the normal reading resumes either way.
  • An untitled carousel slide is announced once. A slide without a
    data-title or heading was announced as "Item 2 of 3, item 2 of 3". It is
    now "Item 2 of 3", which matches its dot.
  • Left and right arrows in <au-radio-group> follow the reading
    direction.
    In right-to-left text, the Right Arrow moved to the option on
    the left. Left and right now point the way they move, as in <au-tabs> and
    <au-rating>, and every arrow still wraps around.
  • accesserty-ui-kit.js no longer adds globals to your page. Since 2.0.0
    the bundle defined __defProp, __defNormalProp and __publicField on
    window. It no longer does, and the file is about 5 KB smaller. Browser
    support does not change: the components already needed the same JavaScript
    level.

Documentation and demos

  • These CSS variables already worked, and the demo pages now list them: the
    dropdown arrow icons (--au-dropdown-arrow-down-icon,
    --au-dropdown-arrow-up-icon), the arrow icons that select and dropdown
    share (--au-control-arrow-down-icon, --au-control-arrow-up-icon),
    --au-file-upload-delete-active-border-color,
    --au-file-upload-delete-tap-highlight-color,
    --au-textarea-container-padding-horizontal,
    --au-tree-node-checkbox-input-indeterminate-symbol, and pagination's
    --au-btn-current-bg, --au-btn-current-text-color,
    --au-btn-current-border-color and --au-pagination-focus-color.
  • Font-family variables now state their fallback as inherit. That is what an
    unset variable already did, so text looks the same.
  • On narrow screens, demo tables scroll inside their own focusable, named area,
    and long code wraps. No demo page scrolls sideways at 320px any more.
    Duplicate landmark names and an empty table header in the demos are fixed.

Behavior changes

  • Right-to-left radio groups: the Right Arrow now selects the previous
    option and the Left Arrow the next one. Up and down are unchanged.
  • Carousel events: a smooth scroll that pauses no longer sends extra
    slide-change events. If you counted events, you may now receive fewer.
  • Untitled carousel slides: the live region text changed from
    "Item 2 of 3, item 2 of 3" to "Item 2 of 3". If you set
    data-live-template, slides with a title still use it.

v2.0.7

Choose a tag to compare

@Neil-Lin Neil-Lin released this 12 Oct 01:43

Accesserty UI Kit v2.0.7

A bug fix for <au-carousel>. No API changes: replace
accesserty-ui-kit.min.js (or accesserty-ui-kit.js) with the new file.

Fixed

  • A carousel told to start on a later slide now shows that slide.
    If your page sets current before the kit's script loads, the carousel
    opens on that slide. Before, the carousel moved there with a smooth scroll,
    which Safari sometimes skipped during page load. The dots and screen readers
    then reported the chosen slide while the first slide stayed in view. The
    starting slide is now set without animation, because it is where the page
    starts, not a move by the user. Previous/next buttons, dots, arrow keys and
    swipes still scroll smoothly. Reduced-motion settings still turn scrolling
    animation off.

v2.0.6

Choose a tag to compare

@Neil-Lin Neil-Lin released this 10 Oct 07:12

Accesserty UI Kit v2.0.6

This release covers 2.0.4, 2.0.5 and 2.0.6 (the previous GitHub release was
v2.0.3). No breaking changes to component APIs: replace
accesserty-ui-kit.min.js (or accesserty-ui-kit.js) and au-style.css with
the new files. Please read Behavior changes if you override the popover
animation or style the accordion's collapsed region.

Added

  • Find-in-page and links now open collapsed <au-accordion-item> panels.
    Where the browser supports hidden="until-found", collapsed panels stay
    searchable: Ctrl+F / ⌘F, text-fragment links (#:~:text=) and #id links
    into collapsed slotted content open the item, including every enclosing item
    of a nested accordion. Opening emits the usual au-toggle event, so framework
    bindings and exclusive groups stay in sync. Until revealed, collapsed
    content stays out of the Tab order and the accessibility tree. Browsers
    without support keep collapsed panels hidden and inert, as before.
  • Find-in-page expands collapsed <au-tree> branches. A match in a
    collapsed node expands every ancestor branch without moving focus. Collapsed
    nodes stay out of the Tab order, arrow-key order and accessibility tree.
    Node labels live in Shadow DOM, which Safari's text-fragment links do not
    search; Chrome's and Firefox's do.

Fixed

  • <au-rating> with Vue v-model no longer reverts the user's choice.
    The inner radio's native input event reached host listeners while value
    still held the previous rating, so v-model read the old value and wrote it
    back. The value now updates first; change still carries detail.value.
  • Popovers fade in, and keep their layout while fading out. The shared
    stylesheet's fade-in never ran, and the fade-out forced display: block on
    closing popovers for 0.5s, breaking grid or flex layouts. Popovers now fade
    both ways using CSS transitions only. A closing popover is already treated as
    closed: it takes no clicks or focus and is not announced. Reduced-motion
    preferences still remove the fade.

Behavior changes

  • @keyframes popover-fade-out is removed from the shared stylesheet. If your
    CSS referenced it, use the transition-based fade (see au-style.css).
  • In supporting browsers, a collapsed accordion region and a collapsed tree
    group now carry hidden="until-found" instead of hidden + inert.
    Selectors such as [hidden] still match; code that checks region.inert
    should not rely on it.

Removed

  • Angular is no longer a tested or documented integration. The Angular
    fixtures and Angular guidance are removed. The components are unchanged
    standard custom elements, so they still work in any framework that renders
    custom elements. Vue/Nuxt and React/Next remain the tested integrations.

Documentation

  • New README section, "Reserving space before registration": copyable
    :not(:defined) CSS that reserves the registered height of au-input,
    au-textarea, au-file-upload and au-tree, to avoid layout shift while
    the script loads. Text lines are reserved in lh, so the reservation holds
    in any font, including Traditional Chinese ones. On the demo pages, under
    simulated Slow 4G, cumulative layout shift fell from 0.296 to 0.023 (input)
    and 0.318 to 0.010 (form).
  • Rebuilt popover and dialog demos:
    • Popover: auto, manual and hint types; Invoker Commands; interestfor
      tooltips; anchor positioning with fallbacks.
    • Dialog: closedby; request-close with an unsaved-changes prompt; nested
      and non-modal dialogs.

Verified

  • Chrome: 453 unit tests, browser checks, and SSR in Next and Nuxt
  • Firefox: WebDriver browser checks, including the accordion and tree reveal
  • Safari 27: WebDriver browser checks for accordion, tree and rating
  • Find-in-page checked by hand in Chrome, Firefox and Safari

These checks do not establish screen-reader speech or full WCAG conformance.
Verify your assembled pages, including with assistive technologies.

Full changelog: v2.0.3...v2.0.6

v2.0.3

Choose a tag to compare

@Neil-Lin Neil-Lin released this 09 Oct 14:39

Accesserty UI Kit v2.0.3

A patch release with one accessibility fix. No breaking changes: replace
accesserty-ui-kit.min.js (or accesserty-ui-kit.js) with the new file.

Fixed

  • <au-accordion> no longer announces an instruction that does not apply.
    Every accordion carried the visually hidden text "Only one section may be
    expanded at a time.", even without the exclusive attribute. Screen readers
    read it as page content, so users heard about a restriction that did not
    exist. The instruction now appears only while exclusive is set.
  • When exclusive is switched on at runtime, the instruction uses the current
    data-text-exclusive-hint value, including any change made while
    exclusive was off. Switching it off removes the instruction again.

Documentation

  • The README links the official overview and the online playground.

Verified

  • Chrome: 447 unit tests, browser checks, SSR (Next, Nuxt, Angular) and an
    Angular AOT consumer build
  • Firefox: WebDriver browser checks on CI
  • Safari: WebDriver browser checks before tagging

These checks do not establish screen-reader speech or full WCAG conformance.
Verify your assembled pages, including with assistive technologies.

Full changelog: v2.0.2...v2.0.3

v2.0.2

Choose a tag to compare

@Neil-Lin Neil-Lin released this 21 Sep 02:43
v2.0.2

v2.0.1

Choose a tag to compare

@Neil-Lin Neil-Lin released this 18 Sep 14:46

au-input copied every host attribute onto its inner input at upgrade, so
hidden, inert, style and inline handlers stayed on the field after the host
changed and handlers ran twice. It now forwards only its documented
attributes. Below 768px the field wraps prefix/affix instead of shrinking to
32px, and colour inputs keep a usable swatch instead of 6px.

au-file-upload's default trigger drew its focus outline with the system
Highlight colour outside forced-colors mode (1.49:1 in Chrome); it now uses
a 7.6:1 default with --au-file-upload-trigger-focus-outline-* variables.
au-breadcrumbs lost its focus indicator in forced-colors mode because the
override was outranked by the nested outline: none.

The accordion, card, carousel, file-upload and breadcrumbs-html browser
checks now run in both CI configurations; breadcrumbs-html accepts a
browser argument, and file-upload subscribes to file choosers early to
avoid a Playwright race. Demo themes meet their own contrast guidance.

The bundle banner no longer embeds the build date, so rebuilds are
reproducible; package.json is private since the kit is not distributed
through npm. Docs require Node 22 and note file-upload's msg- prefix.

v2.0.0

Choose a tag to compare

@Neil-Lin Neil-Lin released this 16 Sep 01:48

refactory