diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..18e38c6
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,32 @@
+# Changelog
+
+
+
+## [4.0.0] - 2023-07-26
+
+- Update for swup 4 compatibility
+
+## [3.0.0] - 2023-03-10
+
+- Switch to microbundle
+- Export native ESM module
+
+## [2.1.0] - 2022-08-21
+
+- Set `aria-busy` on html element during transitions
+
+## [2.0.0] - 2021-03-15
+
+- Fix bundle name
+
+## [1.0.0] - 2020-08-10
+
+- Initial release
+
+[Unreleased]: https://github.com/swup/a11y-plugin/compare/4.0.0...HEAD
+
+[4.0.0]: https://github.com/swup/a11y-plugin/releases/tag/4.0.0
+[3.0.0]: https://github.com/swup/a11y-plugin/releases/tag/3.0.0
+[2.1.0]: https://github.com/swup/a11y-plugin/releases/tag/2.1.0
+[2.0.0]: https://github.com/swup/a11y-plugin/releases/tag/2.0.0
+[1.0.0]: https://github.com/swup/a11y-plugin/releases/tag/1.0.0
diff --git a/readme.md b/README.md
similarity index 75%
rename from readme.md
rename to README.md
index 790e031..c5d548f 100755
--- a/readme.md
+++ b/README.md
@@ -1,37 +1,29 @@
# Swup A11y Plugin
-**by [daun](https://github.com/daun)**
+A [swup](https://swup.js.org) plugin for enhanced accessibility.
-Enhance the accessibility of your [swup](https://github.com/swup/swup)-powered
-sites.
-
-Loading new content via AJAX is great UX for most users, but comes with serious
-shortcomings for screen reader users. We can improve the experience for
-everybody if we:
+Loading new content via AJAX is a great experience for most users, but comes with serious
+shortcomings for screen reader users. This plugin will improve that:
- **Announce page visits** to screenreaders by reading the new page title
- **Focus the main content area** after swapping out the content
-That's exactly what this plugin does.
-
## Installation
-This plugin can be installed with npm
+Install the plugin from npm and import it into your bundle.
```bash
npm install @swup/a11y-plugin
```
-and included with import
-
-```shell
+```js
import SwupA11yPlugin from '@swup/a11y-plugin';
```
-or included from the dist folder
+Or include the minified production file from a CDN:
```html
-
+
```
## Usage
@@ -60,6 +52,12 @@ See the options below for customizing what elements to look for.
```
+If you want the announcement to be different from the text content, use `aria-label`:
+
+```html
+
Project Title
+```
+
## Styling
Browsers will display a visible outline around the main content area when it
@@ -95,8 +93,7 @@ This area will receive focus after a new page was loaded.
The selector for finding headings **inside the main content area**.
-The first heading's content will be read to screen readers after a new page was
-loaded.
+The first heading's content will be read to screen readers after a new page was loaded.
### announcementTemplate
diff --git a/package-lock.json b/package-lock.json
index 001cb20..9c351cb 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,20 +1,20 @@
{
"name": "@swup/a11y-plugin",
- "version": "2.1.0",
+ "version": "4.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@swup/a11y-plugin",
- "version": "2.1.0",
+ "version": "4.0.0",
"license": "MIT",
"dependencies": {
- "@swup/plugin": "^2.0.0",
+ "@swup/plugin": "^3.0.0",
"focus-options-polyfill": "^1.5.0",
"on-demand-live-region": "^0.1.3"
},
"peerDependencies": {
- "swup": "^3.0.0"
+ "swup": "^4.0.0"
}
},
"node_modules/@ampproject/remapping": {
@@ -1934,9 +1934,9 @@
"integrity": "sha512-/3nBqG7LqmK1uqaCSTA6s2NwQBDQXNyLAFBzlX6uaxqjIQcAZyq6K+sgcQ40oj02Vn/2mLSkeL9DOfP7BPOwVA=="
},
"node_modules/@swup/plugin": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/@swup/plugin/-/plugin-2.0.2.tgz",
- "integrity": "sha512-pde/zKIgXpbI+qy8rhuy8De8KniZRuwAoxuOoGTvhErolrW2khlYKtVXgPACRmmPJvGI5ZTfBzBN5txKfIGefQ==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@swup/plugin/-/plugin-3.0.0.tgz",
+ "integrity": "sha512-dCFhmFmucMY4ae4qo01fGocU74YrLwffTTtxCUO21OyDgFdywjO4RLP0pgjsiXueBbpcXkexbj4q+O19dWQRoA==",
"dependencies": {
"@swup/browserslist-config": "^1.0.0",
"@swup/prettier-config": "^1.0.0",
@@ -1945,7 +1945,7 @@
"prettier": "^2.7.1",
"shelljs": "^0.8.5",
"shelljs-live": "^0.0.5",
- "swup": "^3.0.0"
+ "swup": "^4.0.0"
},
"bin": {
"swup-plugin": "bin/swup-plugin.js"
@@ -2577,11 +2577,14 @@
}
},
"node_modules/delegate-it": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/delegate-it/-/delegate-it-3.0.1.tgz",
- "integrity": "sha512-XU8H4pjDGBW74hFIbjdLPnvtU3HF3P9bbZvoFBSBLb5JgNaTkRb/2lvC1V+9kmZsxVR0kad4bU3rYhQ/4Ij+Gw==",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/delegate-it/-/delegate-it-6.0.1.tgz",
+ "integrity": "sha512-ZS2hRm/SaoPzaeWcWyYjzVVF4/PgALZqma9FXsunFt4XQGVAtQ79Vx7v57vNQNaI75Rl12C+x6TkLqHS5PNKLg==",
"dependencies": {
- "typed-query-selector": "^2.6.1"
+ "typed-query-selector": "^2.10.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fregante"
}
},
"node_modules/dom-serializer": {
@@ -4146,6 +4149,11 @@
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
},
+ "node_modules/path-to-regexp": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz",
+ "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw=="
+ },
"node_modules/path-type": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
@@ -5390,13 +5398,14 @@
}
},
"node_modules/swup": {
- "version": "3.0.5",
- "resolved": "https://registry.npmjs.org/swup/-/swup-3.0.5.tgz",
- "integrity": "sha512-MD2oVgyvKbUgWeGKjOzDQUfYLtqlQktREcR27QnzqKBSAjApLrbMTWToYrkI2ZnCXG6ApPMjsrRLArSwiJUBmw==",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/swup/-/swup-4.0.0.tgz",
+ "integrity": "sha512-GQX9WKFJBe4mZaryKkb8QZHsVP9u0GbMauD/B/msthNFB7rbUOqO1eSvaZB9d4TypHCjbviZ6kKac0v9vChOOA==",
"hasInstallScript": true,
"dependencies": {
- "delegate-it": "^3.0.1",
- "opencollective-postinstall": "^2.0.2"
+ "delegate-it": "^6.0.0",
+ "opencollective-postinstall": "^2.0.2",
+ "path-to-regexp": "^6.2.1"
}
},
"node_modules/terser": {
@@ -5457,9 +5466,9 @@
}
},
"node_modules/typed-query-selector": {
- "version": "2.9.2",
- "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.9.2.tgz",
- "integrity": "sha512-mOnelGQ0JBbYvboX6v/3vijUkIW9L557DHVRUFQTKG352EWvW/uDN6ORlPvTPRivefqb3QbbyZgLtPmxQaxmug=="
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.11.0.tgz",
+ "integrity": "sha512-qBs4sfmnLlPOyo2oSdvHbIFHe2CPgU54/1UGfSNceb7LARpIEVxUaeRX0Doje6oKpuySS2stqy90R3YrynR8Kg=="
},
"node_modules/typescript": {
"version": "4.9.5",
diff --git a/package.json b/package.json
index 99a8cb0..239c991 100755
--- a/package.json
+++ b/package.json
@@ -1,8 +1,8 @@
{
"name": "@swup/a11y-plugin",
"amdName": "SwupA11yPlugin",
- "version": "3.0.0",
- "description": "Enhanced accessibility for swup-powered sites",
+ "version": "4.0.0",
+ "description": "A swup plugin for enhanced accessibility",
"type": "module",
"source": "src/index.js",
"main": "./dist/index.cjs",
@@ -17,7 +17,7 @@
"dev": "swup-plugin dev",
"lint": "swup-plugin lint",
"format": "swup-plugin format",
- "prepublish": "npm run build"
+ "prepublishOnly": "npm run build"
},
"author": {
"name": "Philipp Daun",
@@ -42,12 +42,12 @@
"url": "https://github.com/swup/a11y-plugin.git"
},
"dependencies": {
- "@swup/plugin": "^2.0.0",
+ "@swup/plugin": "^3.0.0",
"focus-options-polyfill": "^1.5.0",
"on-demand-live-region": "^0.1.3"
},
"peerDependencies": {
- "swup": "^3.0.0"
+ "swup": "^4.0.0"
},
"browserslist": [
"extends @swup/browserslist-config"
diff --git a/src/index.js b/src/index.js
index 5fdbf87..4fc298e 100755
--- a/src/index.js
+++ b/src/index.js
@@ -6,46 +6,47 @@ import 'focus-options-polyfill';
export default class SwupA11yPlugin extends Plugin {
name = 'SwupA11yPlugin';
+ requires = { swup: '>=4' };
+
+ defaults = {
+ contentSelector: 'main',
+ headingSelector: 'h1, h2, [role=heading]',
+ announcementTemplate: 'Navigated to: {title}',
+ urlTemplate: 'New page at {url}'
+ };
+
constructor(options = {}) {
super();
- this.options = {
- contentSelector: 'main',
- headingSelector: 'h1, h2, [role=heading]',
- announcementTemplate: 'Navigated to: {title}',
- urlTemplate: 'New page at {url}',
- ...options
- };
+ this.options = { ...this.defaults, ...options };
this.liveRegion = new OnDemandLiveRegion();
}
mount() {
- this.swup.on('contentReplaced', this.announceVisit);
- this.swup.on('transitionStart', this.onTransitionStart);
- this.swup.on('transitionEnd', this.onTransitionEnd);
+ this.on('visit:start', this.markAsBusy);
+ this.on('visit:end', this.unmarkAsBusy);
+ this.on('content:replace', this.announceVisit);
+ }
+
+ markAsBusy() {
+ document.documentElement.setAttribute('aria-busy', 'true');
}
- unmount() {
- this.swup.off('contentReplaced', this.announceVisit);
- this.swup.off('transitionStart', this.onTransitionStart);
- this.swup.off('transitionEnd', this.onTransitionEnd);
+ unmarkAsBusy() {
+ document.documentElement.removeAttribute('aria-busy');
}
- announceVisit = () => {
+ announceVisit() {
requestAnimationFrame(() => {
this.announcePageName();
this.focusPageContent();
- });
- };
+ })
+ }
- announcePageName = () => {
- const {
- contentSelector,
- headingSelector,
- urlTemplate,
- announcementTemplate
- } = this.options;
+ announcePageName() {
+ const { contentSelector, headingSelector, urlTemplate, announcementTemplate } =
+ this.options;
// Default: announce new /path/of/page.html
let pageName = urlTemplate.replace('{url}', window.location.pathname);
@@ -67,21 +68,13 @@ export default class SwupA11yPlugin extends Plugin {
const announcement = announcementTemplate.replace('{title}', pageName.trim());
this.liveRegion.say(announcement);
- };
+ }
- focusPageContent = () => {
+ focusPageContent() {
const content = document.querySelector(this.options.contentSelector);
if (content) {
content.setAttribute('tabindex', '-1');
content.focus({ preventScroll: true });
}
- };
-
- onTransitionStart = () => {
- document.documentElement.setAttribute('aria-busy', 'true');
- };
-
- onTransitionEnd = () => {
- document.documentElement.removeAttribute('aria-busy');
- };
+ }
}