Skip to content

Commit fe34128

Browse files
committed
make modal more accessible
1 parent 1b245a4 commit fe34128

File tree

1 file changed

+54
-27
lines changed

1 file changed

+54
-27
lines changed
Lines changed: 54 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,62 @@
11
<script>
2-
import { createEventDispatcher } from 'svelte';
2+
import { createEventDispatcher, onDestroy } from 'svelte';
33
44
const dispatch = createEventDispatcher();
5-
6-
const handleClose = () => dispatch('close')
7-
8-
function handleKeydown(event) {
9-
if (event.key == 'Escape') {
10-
handleClose()
11-
} else if (event.key == 'Tab') {
12-
event.preventDefault()
5+
const close = () => dispatch('close');
6+
7+
let modal;
8+
9+
const handle_keydown = e => {
10+
if (e.key === 'Escape') {
11+
close();
12+
return;
1313
}
14-
}
1514
16-
let closeButton
17-
onMount(() => {
18-
closeButton.focus()
19-
})
15+
if (e.key === 'Tab') {
16+
// trap focus
17+
const nodes = modal.querySelectorAll('*');
18+
const active = document.activeElement;
19+
20+
const tabbable = Array.from(nodes).filter(n => n.tabIndex >= 0);
21+
const first = tabbable[0];
22+
const last = tabbable[tabbable.length - 1];
2023
24+
let index = tabbable.indexOf(document.activeElement);
25+
if (index === -1 && e.shiftKey) index = 0;
26+
27+
index += tabbable.length + (e.shiftKey ? -1 : 1);
28+
index %= tabbable.length;
29+
30+
tabbable[index].focus();
31+
e.preventDefault();
32+
}
33+
};
34+
35+
const previously_focused = typeof document !== 'undefined' && document.activeElement;
36+
37+
if (previously_focused) {
38+
onDestroy(() => {
39+
previously_focused.focus();
40+
});
41+
}
2142
</script>
2243

44+
<svelte:window on:keydown={handle_keydown}/>
45+
46+
<div class="modal-background" on:click={close}></div>
47+
48+
<div class="modal" role="dialog" aria-modal="true" bind:this={modal}>
49+
<slot name="header"></slot>
50+
<hr>
51+
<slot></slot>
52+
<hr>
53+
54+
<!-- svelte-ignore a11y-autofocus -->
55+
<button autofocus on:click={close}>close modal</button>
56+
57+
<a href="argh">argh</a>
58+
</div>
59+
2360
<style>
2461
.modal-background {
2562
position: fixed;
@@ -32,7 +69,8 @@
3269
3370
.modal {
3471
position: absolute;
35-
left: 50%; top: 50%;
72+
left: 50%;
73+
top: 50%;
3674
width: calc(100vw - 4em);
3775
max-width: 32em;
3876
max-height: calc(100vh - 4em);
@@ -46,15 +84,4 @@
4684
button {
4785
display: block;
4886
}
49-
</style>
50-
51-
<div class='modal-background' on:click='{handleClose}'></div>
52-
53-
<div class='modal'>
54-
<slot name='header'></slot>
55-
<hr>
56-
<slot></slot>
57-
<hr>
58-
59-
<button on:click='{() => dispatch("close")}' bind:this={closeButton}>close modal</button>
60-
</div>
87+
</style>

0 commit comments

Comments
 (0)