mirror of
https://github.com/carbon-design-system/carbon-components-svelte.git
synced 2025-09-15 10:21:05 +00:00
Fix: trap tab focus within modal (#716)
* Fix: trap tab focus within modal * Fix: trap tab focus within ComposedModal * change selector criteria for tabbable elements based on react component logic
This commit is contained in:
parent
0d3090b123
commit
ab04bb7564
2 changed files with 51 additions and 3 deletions
|
@ -103,6 +103,33 @@
|
||||||
class:is-visible="{open}"
|
class:is-visible="{open}"
|
||||||
class:bx--modal--danger="{danger}"
|
class:bx--modal--danger="{danger}"
|
||||||
{...$$restProps}
|
{...$$restProps}
|
||||||
|
on:keydown
|
||||||
|
on:keydown="{(e) => {
|
||||||
|
if (open) {
|
||||||
|
if (e.key === 'Escape') {
|
||||||
|
open = false;
|
||||||
|
} else if (e.key === 'Tab') {
|
||||||
|
// taken from github.com/carbon-design-system/carbon/packages/react/src/internal/keyboard/navigation.js
|
||||||
|
const selectorTabbable = `
|
||||||
|
a[href], area[href], input:not([disabled]):not([tabindex='-1']),
|
||||||
|
button:not([disabled]):not([tabindex='-1']),select:not([disabled]):not([tabindex='-1']),
|
||||||
|
textarea:not([disabled]):not([tabindex='-1']),
|
||||||
|
iframe, object, embed, *[tabindex]:not([tabindex='-1']):not([disabled]), *[contenteditable=true]
|
||||||
|
`;
|
||||||
|
|
||||||
|
const tabbable = Array.from(ref.querySelectorAll(selectorTabbable));
|
||||||
|
|
||||||
|
let index = tabbable.indexOf(document.activeElement);
|
||||||
|
if (index === -1 && e.shiftKey) index = 0;
|
||||||
|
|
||||||
|
index += tabbable.length + (e.shiftKey ? -1 : 1);
|
||||||
|
index %= tabbable.length;
|
||||||
|
|
||||||
|
tabbable[index].focus();
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}"
|
||||||
on:click
|
on:click
|
||||||
on:click="{() => {
|
on:click="{() => {
|
||||||
if (!didClickInnerModal && !preventCloseOnClickOutside) open = false;
|
if (!didClickInnerModal && !preventCloseOnClickOutside) open = false;
|
||||||
|
|
|
@ -138,11 +138,32 @@
|
||||||
class:bx--modal--danger="{danger}"
|
class:bx--modal--danger="{danger}"
|
||||||
{...$$restProps}
|
{...$$restProps}
|
||||||
on:keydown
|
on:keydown
|
||||||
on:keydown="{({ key }) => {
|
on:keydown="{(e) => {
|
||||||
if (open) {
|
if (open) {
|
||||||
if (key === 'Escape') {
|
if (e.key === 'Escape') {
|
||||||
open = false;
|
open = false;
|
||||||
} else if (shouldSubmitOnEnter && key === 'Enter') {
|
} else if (e.key === 'Tab') {
|
||||||
|
// trap focus
|
||||||
|
|
||||||
|
// taken from github.com/carbon-design-system/carbon/packages/react/src/internal/keyboard/navigation.js
|
||||||
|
const selectorTabbable = `
|
||||||
|
a[href], area[href], input:not([disabled]):not([tabindex='-1']),
|
||||||
|
button:not([disabled]):not([tabindex='-1']),select:not([disabled]):not([tabindex='-1']),
|
||||||
|
textarea:not([disabled]):not([tabindex='-1']),
|
||||||
|
iframe, object, embed, *[tabindex]:not([tabindex='-1']):not([disabled]), *[contenteditable=true]
|
||||||
|
`;
|
||||||
|
|
||||||
|
const tabbable = Array.from(ref.querySelectorAll(selectorTabbable));
|
||||||
|
|
||||||
|
let index = tabbable.indexOf(document.activeElement);
|
||||||
|
if (index === -1 && e.shiftKey) index = 0;
|
||||||
|
|
||||||
|
index += tabbable.length + (e.shiftKey ? -1 : 1);
|
||||||
|
index %= tabbable.length;
|
||||||
|
|
||||||
|
tabbable[index].focus();
|
||||||
|
e.preventDefault();
|
||||||
|
} else if (shouldSubmitOnEnter && e.key === 'Enter') {
|
||||||
dispatch('submit');
|
dispatch('submit');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue