aria-ease 1.2.2 → 1.2.4
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/README.md +5 -5
- package/aria-ease.d.ts +5 -5
- package/index.js +2 -2
- package/package.json +1 -1
- package/src/block/makeBlockAccessible.js +62 -0
- package/src/block/makeBlockAccessible.ts +63 -0
- package/src/menu/makeMenuAccessible.js +4 -1
- package/src/menu/makeMenuAccessible.ts +0 -1
- package/src/tab/makeTabAccessible.js +0 -60
- package/src/tab/makeTabAccessible.ts +0 -64
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Aria-Ease
|
|
2
2
|
|
|
3
|
-
Out of the box accessibility utility package to develop production ready
|
|
3
|
+
Out of the box accessibility utility package to develop production ready applications.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -57,19 +57,19 @@ const App = () => {
|
|
|
57
57
|
export default App
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
-
Add accessibility to
|
|
60
|
+
Add accessibility to block: block can be entire web page body, tabs, interactive sliders and carousels e.t.c. Basically any component that is permanently displayed and has a list of related interractive children items. The function creates a focus trap within the block and the focus can be navigated using the arrow keys.
|
|
61
61
|
|
|
62
|
-
The
|
|
62
|
+
The makeBlockAccessible function takes two string arguments; the id of the block main div, and the class name of the children item of the div. The function should be called on page render, so the event listeners get activated. On click of a button, the clicked button gets focused and the focus can be navigated using the arrow keys.
|
|
63
63
|
|
|
64
64
|
#### Usage
|
|
65
65
|
|
|
66
66
|
```
|
|
67
67
|
import { useEffect } from 'react'
|
|
68
|
-
import {
|
|
68
|
+
import { makeBlockAccessible } from "aria-ease"
|
|
69
69
|
|
|
70
70
|
const App = () => {
|
|
71
71
|
useEffect(() => {
|
|
72
|
-
|
|
72
|
+
makeBlockAccessible('custom-tab', 'custom-tab-item')
|
|
73
73
|
},[])
|
|
74
74
|
|
|
75
75
|
return (
|
package/aria-ease.d.ts
CHANGED
|
@@ -10,11 +10,11 @@ declare module 'aria-ease' {
|
|
|
10
10
|
function makeMenuAccessible(menuId: string, menuItemClass: string): void;
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* Adds keyboard interaction to
|
|
14
|
-
* @param {string}
|
|
15
|
-
* @param {string}
|
|
13
|
+
* Adds keyboard interaction to block. The block traps focus and can be interacted with using the keyboard.
|
|
14
|
+
* @param {string} blockId - The id of the block container.
|
|
15
|
+
* @param {string} blockItemClass - The class of the individual block items.
|
|
16
16
|
*/
|
|
17
|
-
function
|
|
17
|
+
function makeBlockAccessible(blockId: string, blockItemClass: string): void;
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Updates the aria attributes of the menu trigger button. Trigger button element must possess the following aria attributes; aria-expanded, aria-pressed, aria-label.
|
|
@@ -23,6 +23,6 @@ declare module 'aria-ease' {
|
|
|
23
23
|
*/
|
|
24
24
|
function updateMenuTriggerAriaAttributes(triggerId: string, ariaLabel: string): void;
|
|
25
25
|
|
|
26
|
-
export { makeMenuAccessible,
|
|
26
|
+
export { makeMenuAccessible, makeBlockAccessible, updateMenuTriggerAriaAttributes };
|
|
27
27
|
}
|
|
28
28
|
|
package/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { makeMenuAccessible } from './src/menu/makeMenuAccessible.js'
|
|
2
|
-
import {
|
|
2
|
+
import { makeBlockAccessible } from './src/block/makeBlockAccessible.js'
|
|
3
3
|
import { updateMenuTriggerAriaAttributes } from './src/menu/updateMenuTriggerAriaAttributes.js'
|
|
4
4
|
|
|
5
5
|
export {
|
|
6
6
|
makeMenuAccessible,
|
|
7
|
-
|
|
7
|
+
makeBlockAccessible,
|
|
8
8
|
updateMenuTriggerAriaAttributes
|
|
9
9
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adds keyboard interaction to block. The block traps focus and can be interacted with using the keyboard.
|
|
3
|
+
* @param {string} blockId The id of the block
|
|
4
|
+
* @param {string} blockItemClass The class of the items that are children of the block
|
|
5
|
+
*/
|
|
6
|
+
var eventListenersAdded = new Set();
|
|
7
|
+
export function makeBlockAccessible(blockId, blockItemClass) {
|
|
8
|
+
var blockDiv = document.querySelector("#".concat(blockId));
|
|
9
|
+
var blockItems = blockDiv.querySelectorAll(".".concat(blockItemClass));
|
|
10
|
+
blockItems.forEach(function (blockItem, blockItemIndex) {
|
|
11
|
+
if (!eventListenersAdded.has(blockItem)) {
|
|
12
|
+
eventListenersAdded.add(blockItem);
|
|
13
|
+
blockItem.addEventListener('keydown', function (event) { return handleKeyPress(event, blockItems, blockItemIndex); });
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
function handleKeyPress(event, blockItems, blockItemIndex) {
|
|
17
|
+
switch (event.key) {
|
|
18
|
+
case 'ArrowUp':
|
|
19
|
+
case 'ArrowLeft':
|
|
20
|
+
event.preventDefault();
|
|
21
|
+
if (blockItemIndex === 0) {
|
|
22
|
+
blockItems.item(blockItems.length - 1).focus();
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
blockItems.item(blockItemIndex - 1).focus();
|
|
26
|
+
}
|
|
27
|
+
break;
|
|
28
|
+
case 'ArrowDown':
|
|
29
|
+
case 'ArrowRight':
|
|
30
|
+
event.preventDefault();
|
|
31
|
+
if (blockItemIndex === blockItems.length - 1) {
|
|
32
|
+
blockItems.item(0).focus();
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
blockItems.item(blockItemIndex + 1).focus();
|
|
36
|
+
}
|
|
37
|
+
break;
|
|
38
|
+
case 'Enter':
|
|
39
|
+
case ' ':
|
|
40
|
+
event.preventDefault();
|
|
41
|
+
if (blockItems.item(blockItemIndex).type === 'radio') {
|
|
42
|
+
blockItems.item(blockItemIndex).checked = true;
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
else if (blockItems.item(blockItemIndex).type === 'checkbox') {
|
|
46
|
+
blockItems.item(blockItemIndex).checked = !blockItems.item(blockItemIndex).checked;
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
else if (blockItems.item(blockItemIndex).tagName === 'BUTTON') {
|
|
50
|
+
blockItems.item(blockItemIndex).click();
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
else if (blockItems.item(blockItemIndex).tagName === 'A') {
|
|
54
|
+
window.location.href = blockItems.item(blockItemIndex).href;
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
break;
|
|
58
|
+
default:
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adds keyboard interaction to block. The block traps focus and can be interacted with using the keyboard.
|
|
3
|
+
* @param {string} blockId The id of the block
|
|
4
|
+
* @param {string} blockItemClass The class of the items that are children of the block
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { HTMLElement, NodeListOfHTMLElement } from "../../Types"
|
|
8
|
+
|
|
9
|
+
let eventListenersAdded: Set<HTMLElement> = new Set();
|
|
10
|
+
|
|
11
|
+
export function makeBlockAccessible(blockId: string, blockItemClass: string): void {
|
|
12
|
+
const blockDiv: HTMLElement = document.querySelector(`#${blockId}`) as HTMLElement
|
|
13
|
+
const blockItems: NodeListOfHTMLElement = blockDiv.querySelectorAll(`.${blockItemClass}`)
|
|
14
|
+
|
|
15
|
+
blockItems.forEach((blockItem: HTMLElement, blockItemIndex: number): void => {
|
|
16
|
+
if (!eventListenersAdded.has(blockItem)) {
|
|
17
|
+
eventListenersAdded.add(blockItem);
|
|
18
|
+
blockItem.addEventListener('keydown', (event: KeyboardEvent) => handleKeyPress(event, blockItems, blockItemIndex));
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
function handleKeyPress(event: KeyboardEvent, blockItems: NodeListOfHTMLElement, blockItemIndex: number): void {
|
|
23
|
+
switch(event.key) {
|
|
24
|
+
case 'ArrowUp':
|
|
25
|
+
case 'ArrowLeft':
|
|
26
|
+
event.preventDefault()
|
|
27
|
+
if (blockItemIndex === 0) {
|
|
28
|
+
blockItems.item(blockItems.length - 1).focus();
|
|
29
|
+
} else {
|
|
30
|
+
blockItems.item(blockItemIndex - 1).focus();
|
|
31
|
+
}
|
|
32
|
+
break;
|
|
33
|
+
case 'ArrowDown':
|
|
34
|
+
case 'ArrowRight':
|
|
35
|
+
event.preventDefault()
|
|
36
|
+
if (blockItemIndex === blockItems.length - 1) {
|
|
37
|
+
blockItems.item(0).focus();
|
|
38
|
+
} else {
|
|
39
|
+
blockItems.item(blockItemIndex + 1).focus();
|
|
40
|
+
}
|
|
41
|
+
break;
|
|
42
|
+
case 'Enter':
|
|
43
|
+
case ' ':
|
|
44
|
+
event.preventDefault()
|
|
45
|
+
if (blockItems.item(blockItemIndex).type === 'radio') {
|
|
46
|
+
blockItems.item(blockItemIndex).checked = true
|
|
47
|
+
break;
|
|
48
|
+
} else if (blockItems.item(blockItemIndex).type === 'checkbox') {
|
|
49
|
+
blockItems.item(blockItemIndex).checked = !blockItems.item(blockItemIndex).checked
|
|
50
|
+
break;
|
|
51
|
+
} else if (blockItems.item(blockItemIndex).tagName === 'BUTTON') {
|
|
52
|
+
blockItems.item(blockItemIndex).click()
|
|
53
|
+
break;
|
|
54
|
+
} else if (blockItems.item(blockItemIndex).tagName === 'A') {
|
|
55
|
+
window.location.href = blockItems.item(blockItemIndex).href
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
break;
|
|
59
|
+
default:
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -20,6 +20,7 @@ export function makeMenuAccessible(menuId, menuItemClass) {
|
|
|
20
20
|
switch (event.key) {
|
|
21
21
|
case 'ArrowUp':
|
|
22
22
|
case 'ArrowLeft':
|
|
23
|
+
event.preventDefault();
|
|
23
24
|
if (menuItemIndex === 0) {
|
|
24
25
|
menuItems.item(menuItems.length - 1).focus();
|
|
25
26
|
}
|
|
@@ -29,6 +30,7 @@ export function makeMenuAccessible(menuId, menuItemClass) {
|
|
|
29
30
|
break;
|
|
30
31
|
case 'ArrowDown':
|
|
31
32
|
case 'ArrowRight':
|
|
33
|
+
event.preventDefault();
|
|
32
34
|
if (menuItemIndex === menuItems.length - 1) {
|
|
33
35
|
menuItems.item(0).focus();
|
|
34
36
|
}
|
|
@@ -37,6 +39,7 @@ export function makeMenuAccessible(menuId, menuItemClass) {
|
|
|
37
39
|
}
|
|
38
40
|
break;
|
|
39
41
|
case 'Escape':
|
|
42
|
+
event.preventDefault();
|
|
40
43
|
(getComputedStyle(menuDiv).display === 'block') ?
|
|
41
44
|
triggerButton.click() :
|
|
42
45
|
null;
|
|
@@ -44,12 +47,12 @@ export function makeMenuAccessible(menuId, menuItemClass) {
|
|
|
44
47
|
break;
|
|
45
48
|
case 'Enter':
|
|
46
49
|
case ' ':
|
|
50
|
+
event.preventDefault();
|
|
47
51
|
if (menuItems.item(menuItemIndex).tagName === 'BUTTON') {
|
|
48
52
|
menuItems.item(menuItemIndex).click();
|
|
49
53
|
break;
|
|
50
54
|
}
|
|
51
55
|
else if (menuItems.item(menuItemIndex).tagName === 'A') {
|
|
52
|
-
event.preventDefault();
|
|
53
56
|
window.location.href = menuItems.item(menuItemIndex).href;
|
|
54
57
|
break;
|
|
55
58
|
}
|
|
@@ -57,7 +57,6 @@ export function makeMenuAccessible(menuId: string, menuItemClass: string): void
|
|
|
57
57
|
menuItems.item(menuItemIndex).click()
|
|
58
58
|
break;
|
|
59
59
|
} else if (menuItems.item(menuItemIndex).tagName === 'A') {
|
|
60
|
-
event.preventDefault();
|
|
61
60
|
window.location.href = menuItems.item(menuItemIndex).href;
|
|
62
61
|
break;
|
|
63
62
|
} else if (menuItems.item(menuItemIndex).type === 'radio') {
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Adds keyboard interaction to tab. The tab traps focus and can be interacted with using the keyboard.
|
|
3
|
-
* @param {string} tabId The id of the tab
|
|
4
|
-
* @param {string} tabItemClass The class of the items that are children of the tab
|
|
5
|
-
*/
|
|
6
|
-
var eventListenersAdded = new Set();
|
|
7
|
-
export function makeTabAccessible(tabId, tabItemClass) {
|
|
8
|
-
var tabDiv = document.querySelector("#".concat(tabId));
|
|
9
|
-
var tabItems = tabDiv.querySelectorAll(".".concat(tabItemClass));
|
|
10
|
-
tabItems.forEach(function (tabItem, tabItemIndex) {
|
|
11
|
-
if (!eventListenersAdded.has(tabItem)) {
|
|
12
|
-
eventListenersAdded.add(tabItem);
|
|
13
|
-
tabItem.addEventListener('keydown', function (event) { return handleKeyPress(event, tabItems, tabItemIndex); });
|
|
14
|
-
}
|
|
15
|
-
});
|
|
16
|
-
function handleKeyPress(event, tabItems, tabItemIndex) {
|
|
17
|
-
switch (event.key) {
|
|
18
|
-
case 'ArrowUp':
|
|
19
|
-
case 'ArrowLeft':
|
|
20
|
-
if (tabItemIndex === 0) {
|
|
21
|
-
tabItems.item(tabItems.length - 1).focus();
|
|
22
|
-
}
|
|
23
|
-
else {
|
|
24
|
-
tabItems.item(tabItemIndex - 1).focus();
|
|
25
|
-
}
|
|
26
|
-
break;
|
|
27
|
-
case 'ArrowDown':
|
|
28
|
-
case 'ArrowRight':
|
|
29
|
-
if (tabItemIndex === tabItems.length - 1) {
|
|
30
|
-
tabItems.item(0).focus();
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
tabItems.item(tabItemIndex + 1).focus();
|
|
34
|
-
}
|
|
35
|
-
break;
|
|
36
|
-
case 'Enter':
|
|
37
|
-
case ' ':
|
|
38
|
-
if (tabItems.item(tabItemIndex).type === 'radio') {
|
|
39
|
-
tabItems.item(tabItemIndex).checked = true;
|
|
40
|
-
break;
|
|
41
|
-
}
|
|
42
|
-
else if (tabItems.item(tabItemIndex).type === 'checkbox') {
|
|
43
|
-
tabItems.item(tabItemIndex).checked = !tabItems.item(tabItemIndex).checked;
|
|
44
|
-
break;
|
|
45
|
-
}
|
|
46
|
-
else if (tabItems.item(tabItemIndex).tagName === 'BUTTON') {
|
|
47
|
-
tabItems.item(tabItemIndex).click();
|
|
48
|
-
break;
|
|
49
|
-
}
|
|
50
|
-
else if (tabItems.item(tabItemIndex).tagName === 'A') {
|
|
51
|
-
event.preventDefault();
|
|
52
|
-
window.location.href = tabItems.item(tabItemIndex).href;
|
|
53
|
-
break;
|
|
54
|
-
}
|
|
55
|
-
break;
|
|
56
|
-
default:
|
|
57
|
-
break;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Adds keyboard interaction to tab. The tab traps focus and can be interacted with using the keyboard.
|
|
3
|
-
* @param {string} tabId The id of the tab
|
|
4
|
-
* @param {string} tabItemClass The class of the items that are children of the tab
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { HTMLElement, NodeListOfHTMLElement } from "../../Types"
|
|
8
|
-
|
|
9
|
-
let eventListenersAdded: Set<HTMLElement> = new Set();
|
|
10
|
-
|
|
11
|
-
export function makeTabAccessible(tabId: string, tabItemClass: string): void {
|
|
12
|
-
const tabDiv: HTMLElement = document.querySelector(`#${tabId}`) as HTMLElement
|
|
13
|
-
const tabItems: NodeListOfHTMLElement = tabDiv.querySelectorAll(`.${tabItemClass}`)
|
|
14
|
-
|
|
15
|
-
tabItems.forEach((tabItem: HTMLElement, tabItemIndex: number): void => {
|
|
16
|
-
if (!eventListenersAdded.has(tabItem)) {
|
|
17
|
-
eventListenersAdded.add(tabItem);
|
|
18
|
-
tabItem.addEventListener('keydown', (event: KeyboardEvent) => handleKeyPress(event, tabItems, tabItemIndex));
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
function handleKeyPress(event: KeyboardEvent, tabItems: NodeListOfHTMLElement, tabItemIndex: number): void {
|
|
23
|
-
switch(event.key) {
|
|
24
|
-
case 'ArrowUp':
|
|
25
|
-
case 'ArrowLeft':
|
|
26
|
-
event.preventDefault()
|
|
27
|
-
if (tabItemIndex === 0) {
|
|
28
|
-
tabItems.item(tabItems.length - 1).focus();
|
|
29
|
-
} else {
|
|
30
|
-
tabItems.item(tabItemIndex - 1).focus();
|
|
31
|
-
}
|
|
32
|
-
break;
|
|
33
|
-
case 'ArrowDown':
|
|
34
|
-
case 'ArrowRight':
|
|
35
|
-
event.preventDefault()
|
|
36
|
-
if (tabItemIndex === tabItems.length - 1) {
|
|
37
|
-
tabItems.item(0).focus();
|
|
38
|
-
} else {
|
|
39
|
-
tabItems.item(tabItemIndex + 1).focus();
|
|
40
|
-
}
|
|
41
|
-
break;
|
|
42
|
-
case 'Enter':
|
|
43
|
-
case ' ':
|
|
44
|
-
event.preventDefault()
|
|
45
|
-
if (tabItems.item(tabItemIndex).type === 'radio') {
|
|
46
|
-
tabItems.item(tabItemIndex).checked = true
|
|
47
|
-
break;
|
|
48
|
-
} else if (tabItems.item(tabItemIndex).type === 'checkbox') {
|
|
49
|
-
tabItems.item(tabItemIndex).checked = !tabItems.item(tabItemIndex).checked
|
|
50
|
-
break;
|
|
51
|
-
} else if (tabItems.item(tabItemIndex).tagName === 'BUTTON') {
|
|
52
|
-
tabItems.item(tabItemIndex).click()
|
|
53
|
-
break;
|
|
54
|
-
} else if (tabItems.item(tabItemIndex).tagName === 'A') {
|
|
55
|
-
event.preventDefault()
|
|
56
|
-
window.location.href = tabItems.item(tabItemIndex).href
|
|
57
|
-
break;
|
|
58
|
-
}
|
|
59
|
-
break;
|
|
60
|
-
default:
|
|
61
|
-
break;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|