Merge pull request #713 from MathieuPuech/fix/tab-trap
fix(tabs): tab keyboard navigation trap
This commit is contained in:
commit
df81970c30
1 changed files with 23 additions and 12 deletions
|
|
@ -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 */
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue