Revision code

Changes Version 3.7.0
Released on January 07, 2024 with 32 commits

Focus ring visibility

You can now control whether a focused fragment shows a visible focus ring.

Because Unpoly often focuses new content, you may see focus outline appear in unexpected places. Focus rings are important for users of keyboards and screen readers to be able to orient themselves as the focus moves on the page. However, mouse and touch users often dislike the visual effect of a focus ring.

To help your CSS show or hide focus rings in the right situation, Unpoly assigns CSS classes to the elements it focuses:

You can use these classes to hide unwanted focus rings, or style focus rings on new components.

The following supporting changes have also been made:

See Focus ring visibility for more details and examples.

Reacting to form changes

This release addresses many edge cases with features that watch form fields for changes, in particular [up-watch], [up-autosubmit] and

  • Watchers now detect changes in fields that were inserted dynamically later. This regression was introduced by Unpoly 3.0.
  • Watchers now detect changes when the form is reset.
  • Fix an issue where [up-autosubmit] would not work on forms that also have dependent fields using [up-validate].
  • Watchers no longer run callbacks if the form was aborted or detached while waiting for a previous async callback.
  • Watchers now abort their debounce delay if the entire form is aborted. Previously it would abort the delay if any watched field was aborted.
  • [up-autosubmit] now aborts a debounce delay if either the form element or the form's target are aborted. It no longer aborts the delay if any watched field is aborted.

Other changes

  • up.on() takes a { capture: true } option to register a listener that runs before the event is emitted on the element.
  • Scrolling now defaults to { behavior: 'instant' } to prevent picking up a scroll-behavior CSS property. To do pick up the property, pass { behavior: 'auto' }.
  • New function up.form.isField(). It returns whether the given element is a form field.


If you're upgrading from an older Unpoly version you should load unpoly-migrate.js to polyfill deprecated APIs. Changes handled by unpoly-migrate.js are not considered breaking changes.

See our upgrading guide for details.