Merge pull request #713 from MathieuPuech/fix/tab-trap

fix(tabs): tab keyboard navigation trap
This commit is contained in:
gerjanvangeest 2020-05-18 09:57:41 +02:00 committed by GitHub
commit df81970c30
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -16,22 +16,22 @@ const deselectPanel = element => {
element.removeAttribute('selected'); element.removeAttribute('selected');
}; };
const setupButton = ({ element, uid, clickHandler, keydownHandler }) => { const setupButton = ({ element, uid, clickHandler, keydownHandler, keyupHandler }) => {
element.setAttribute('id', `button-${uid}`); element.setAttribute('id', `button-${uid}`);
element.setAttribute('role', 'tab'); element.setAttribute('role', 'tab');
element.setAttribute('aria-controls', `panel-${uid}`); element.setAttribute('aria-controls', `panel-${uid}`);
element.addEventListener('click', clickHandler); element.addEventListener('click', clickHandler);
element.addEventListener('keyup', keydownHandler); element.addEventListener('keyup', keyupHandler);
element.addEventListener('keydown', e => e.preventDefault()); element.addEventListener('keydown', keydownHandler);
}; };
const cleanButton = (element, clickHandler, keydownHandler) => { const cleanButton = ({ element, clickHandler, keydownHandler, keyupHandler }) => {
element.removeAttribute('id'); element.removeAttribute('id');
element.removeAttribute('role'); element.removeAttribute('role');
element.removeAttribute('aria-controls'); element.removeAttribute('aria-controls');
element.removeEventListener('click', clickHandler); element.removeEventListener('click', clickHandler);
element.removeEventListener('keyup', keydownHandler); element.removeEventListener('keyup', keyupHandler);
element.removeEventListener('keydown', e => e.preventDefault()); element.removeEventListener('keydown', keydownHandler);
}; };
const selectButton = (element, firstUpdate = false) => { const selectButton = (element, firstUpdate = false) => {
@ -51,6 +51,19 @@ const deselectButton = element => {
element.setAttribute('tabindex', -1); element.setAttribute('tabindex', -1);
}; };
const handleButtonKeydown = e => {
switch (e.key) {
case 'ArrowDown':
case 'ArrowRight':
case 'ArrowUp':
case 'ArrowLeft':
case 'Home':
case 'End':
e.preventDefault();
/* no default */
}
};
export class LionTabs extends LitElement { export class LionTabs extends LitElement {
static get properties() { static get properties() {
return { return {
@ -143,7 +156,8 @@ export class LionTabs extends LitElement {
button, button,
panel, panel,
clickHandler: this.__createButtonClickHandler(index), clickHandler: this.__createButtonClickHandler(index),
keydownHandler: this.__handleButtonKeydown.bind(this), keydownHandler: handleButtonKeydown,
keyupHandler: this.__handleButtonKeyup.bind(this),
}; };
setupPanel({ element: entry.panel, ...entry }); setupPanel({ element: entry.panel, ...entry });
setupButton({ element: entry.button, ...entry }); setupButton({ element: entry.button, ...entry });
@ -158,7 +172,7 @@ export class LionTabs extends LitElement {
return; return;
} }
this.__store.forEach(entry => { this.__store.forEach(entry => {
cleanButton(entry.button, entry.clickHandler, entry.keydownHandler); cleanButton({ element: entry.button, ...entry });
}); });
} }
@ -168,7 +182,7 @@ export class LionTabs extends LitElement {
}; };
} }
__handleButtonKeydown(e) { __handleButtonKeyup(e) {
switch (e.key) { switch (e.key) {
case 'ArrowDown': case 'ArrowDown':
case 'ArrowRight': case 'ArrowRight':
@ -180,7 +194,6 @@ export class LionTabs extends LitElement {
break; break;
case 'ArrowUp': case 'ArrowUp':
case 'ArrowLeft': case 'ArrowLeft':
e.preventDefault();
if (this.selectedIndex <= 0) { if (this.selectedIndex <= 0) {
this.selectedIndex = this._pairCount - 1; this.selectedIndex = this._pairCount - 1;
} else { } else {
@ -188,11 +201,9 @@ export class LionTabs extends LitElement {
} }
break; break;
case 'Home': case 'Home':
e.preventDefault();
this.selectedIndex = 0; this.selectedIndex = 0;
break; break;
case 'End': case 'End':
e.preventDefault();
this.selectedIndex = this._pairCount - 1; this.selectedIndex = this._pairCount - 1;
break; break;
/* no default */ /* no default */