Fragment links often replace the primary content element of your application layout. For this purpose you can now define default targets that are automatically updated when no target selector is given.
Layers are fully isolated, meaning a screen in one layer will not accidentally see elements or events from another layer. For instance, fragment links will only update elements from the current layer unless you explicitly target another layer.
Overlays allow you to break up a complex screen into subinteractions.
Subinteractions take place in overlays and may span one or many pages. The original screen remains open in the background.
Once the subinteraction is done, the overlay is closed and a result value is communicated back to the parent layer.
Navigation intent
You can now define whether a framgent update constitutes a user navigation. Switching screens needs other defaults than updating a tiny box.
User navigation aborts earlier requests, fixing race conditions on slow connections.
Accessibility
New overlays are focused automatically and trap focus in a cycle. Closing the overlay re-focuses the link that opened it.
Focus is automatically managed when rendering major new content. A new [up-focus] attribute allows
you to explicitly move the user's focus as you update fragments.
Keyboard navigation is supported everywhere.
Focus, selection and scroll positions are preserved within an updated fragment.
Reworked Bootstrap integration
The Bootstrap integration is now minimal and as unopinionated as possible. Little to no Bootstrap CSS is overridden.
Bootstrap versions 3, 4 and 5 are now supported.
Quality of live improvements
Unpoly now ships with a bandwidth-friendly polling implementation that handles many edge cases.
The position of a clicked link is considered when deciding which element to replace. If possible, Unpoly will update an selector in the region of the link that triggered the fragment update. This helps with multiple self-contained components (with the same selector) on the same page.
The log output is more much more compact and has a calmer formatting.
New fragments are no longer revealed by default. Instead Unpoly scrolls to the top when the main target has changed, but does not scroll otherwise.
History is no longer changed by default. Instead Unpoly updates history only when a main target has changed.
Many optimizations have been made to preserve bandwidth on slow connections. For example, Unpoly stops preloading and polling whenthe connection has high latency or low throughput.
The client-side cache can be carefully managed by both the client and server.
If you are using Ruby on Rails, the new protocol is already implemented by the unpoly-rails gem.
If you are using Elixir / Phoenix, the new protocol is already implemented by the ex_unpoly package.
Overview of breaking changes
Please use unpoly-migrate.js for a very smooth upgrade process from Unpoly 0.x or 1.x to Unpoly 2.0.
By loading <code>unpoly-migrate.js</code>, calls to most old APIs will be forwarded to the new version. A deprecation notice will be logged to your browser console. This way you can upgrade Unpoly, revive your application with a few changes, then replace deprecated API calls under green tests.
There's a short list of changes that we cannot fix with aliases.
Overlays (modals, popups) have different HTML
But it's similar. E.g. <div class="modal"> becomes <up-modal>.
Unpoly only sees the current layer
You can target other layers with { layer: 'any' }.
Async functions no longer wait for animations
You might or might not notice. In cases where you absolutely do need to wait, an { onFinished } callback can be used.
Tooltips are no longer built-in
But there are a million better libraries.
Unpoly 1 maintenance
With the release of Unpoly we're ending maintenance of Unpoly 1. Expect little to no changes to Unpoly 1 in the future.
GitHub issues that have been fixed in Unpoly 2 will be closed.
The code for Unpoly 1 can be found in the 1.x-stable branch.
Upgrading
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.