vanilla-aria-modals 1.1.5 → 1.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/README.md +4 -4
- package/package.json +1 -1
- package/src/ModalHandler.js +17 -3
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file. Dates use I
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/).
|
|
6
6
|
|
|
7
|
+
## [1.1.6] - 2026-02-20
|
|
8
|
+
### Fixed
|
|
9
|
+
- Update trap focus logic to ignore hidden elements, selecting only visible focusable ones
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- Informational debug statements for focus management
|
|
13
|
+
- Example JS now toggles `inert` on `<main>` when a modal opens
|
|
14
|
+
|
|
7
15
|
## [1.1.5] - 2026-02-19
|
|
8
16
|
### Fixed
|
|
9
17
|
- Remove the unnecessary `isToggle` parameter type definition from the `.d.ts` file.
|
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ Written in vanilla JS for full flexibility. You can modify it directly in `node_
|
|
|
14
14
|
|
|
15
15
|
## Set up
|
|
16
16
|
|
|
17
|
-
```
|
|
17
|
+
```javascript
|
|
18
18
|
import ModalHandler from 'vanilla-aria-modals';
|
|
19
19
|
const modalHandler = new ModalHandler();
|
|
20
20
|
```
|
|
@@ -33,7 +33,7 @@ A fully detailed example including the necessary JavaScript, HTML, and CSS files
|
|
|
33
33
|
|
|
34
34
|
**Note:** `lm` in the code stands for *HTMLElement*.
|
|
35
35
|
|
|
36
|
-
```
|
|
36
|
+
```javascript
|
|
37
37
|
// Basic example of showing a modal
|
|
38
38
|
showModal() {
|
|
39
39
|
modalContainerLm.style.display = 'block';
|
|
@@ -88,7 +88,7 @@ In Single Page Applications (SPA) or frameworks like React, Vue, or vanilla JS w
|
|
|
88
88
|
|
|
89
89
|
### Example: Cleanup on route change or component unmount
|
|
90
90
|
|
|
91
|
-
```
|
|
91
|
+
```javascript
|
|
92
92
|
// Suppose your SPA route or component changes
|
|
93
93
|
function onRouteChange() {
|
|
94
94
|
// Clear leftover document events, active modals, focus tracking, modal ID key counter
|
|
@@ -186,7 +186,7 @@ Registers A11y events and modal stacking handling:
|
|
|
186
186
|
|
|
187
187
|
If you need to pass additional arguments to the close handler, you can wrap it in a function that returns a handler accepting only the two parameters (`e` and `modalKey`):
|
|
188
188
|
|
|
189
|
-
```
|
|
189
|
+
```javascript
|
|
190
190
|
const closeModalWrapper = (...args) => {
|
|
191
191
|
// Returns a handler that the utility calls internally with e and modalKey
|
|
192
192
|
return (e, modalKey) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vanilla-aria-modals",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.6",
|
|
4
4
|
"description": "Framework-agnostic utility for managing accessibility in modals or modal-like UIs, including modal stacking, focus management, and closing via Escape key or outside click.",
|
|
5
5
|
"main": "src/ModalHandler.js",
|
|
6
6
|
"scripts": {
|
package/src/ModalHandler.js
CHANGED
|
@@ -80,15 +80,15 @@ export default class ModalHandler {
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
#trapFocus(e, element) {
|
|
83
|
-
// Select all focusable elements within the given element
|
|
84
|
-
const focusableLms = element.querySelectorAll(`
|
|
83
|
+
// Select all visible (not hidden) focusable elements within the given element
|
|
84
|
+
const focusableLms = [...element.querySelectorAll(`
|
|
85
85
|
a[href]:not([disabled]),
|
|
86
86
|
button:not([disabled]),
|
|
87
87
|
textarea:not([disabled]),
|
|
88
88
|
input:not([disabled]),
|
|
89
89
|
select:not([disabled]),
|
|
90
90
|
[tabindex]:not([tabindex="-1"])
|
|
91
|
-
`);
|
|
91
|
+
`)].filter(lm => lm.offsetParent !== null && getComputedStyle(lm).visibility !== 'hidden');
|
|
92
92
|
// Get the first and last focusable elements
|
|
93
93
|
const firstFocusableLm = focusableLms[0];
|
|
94
94
|
const lastFocusableLm = focusableLms[focusableLms.length - 1];
|
|
@@ -399,6 +399,11 @@ export default class ModalHandler {
|
|
|
399
399
|
const lastFocusableLm = lastFocusedLm ? lastFocusedLm : document.activeElement;
|
|
400
400
|
if (auto) this.#focusHandler[modalKey] = lastFocusableLm;
|
|
401
401
|
|
|
402
|
+
if (this.#debug) {
|
|
403
|
+
console.log(`[ModalHandler][DEBUG]: Focusing first element in modal "${modalKey}" => `, firstFocusableLm);
|
|
404
|
+
console.log(`[ModalHandler][DEBUG]: ${auto ? 'Stored' : 'Returned'} last focused element for modal "${modalKey}" => `, lastFocusableLm);
|
|
405
|
+
}
|
|
406
|
+
|
|
402
407
|
// Needs a timeout for keyboard navigation, if not focus is unreliable
|
|
403
408
|
setTimeout(() => {
|
|
404
409
|
firstFocusableLm.focus();
|
|
@@ -418,8 +423,17 @@ export default class ModalHandler {
|
|
|
418
423
|
}
|
|
419
424
|
|
|
420
425
|
const lastFocusableLm = auto ? this.#focusHandler[modalKey] : lastFocusedLm;
|
|
426
|
+
|
|
427
|
+
if (this.#debug) {
|
|
428
|
+
console.log(`[ModalHandler][DEBUG]: Restoring focus for modal "${modalKey}" to element => `, lastFocusableLm);
|
|
429
|
+
}
|
|
430
|
+
|
|
421
431
|
lastFocusableLm.focus();
|
|
422
432
|
|
|
433
|
+
if (this.#debug && auto) {
|
|
434
|
+
console.log(`[ModalHandler][DEBUG]: Cleared stored focus for modal "${modalKey}"`);
|
|
435
|
+
}
|
|
436
|
+
|
|
423
437
|
// Clean up the stored focus
|
|
424
438
|
if (auto) {
|
|
425
439
|
delete this.#focusHandler[modalKey];
|