fix(accordion): navigating with tab confuses the arrow key navigation (#2056)

* fix(accordion): Handle focusin event, when tabbing to an invoker

* fix(accordion): Add changeset

* fix(accordion): Test if the index equals to the focusedIndex
This commit is contained in:
Gyulai Levente 2023-09-11 14:43:52 +02:00 committed by GitHub
parent 9b9485dbaa
commit 857d47a933
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 35 additions and 2 deletions

View file

@ -0,0 +1,5 @@
---
'@lion/ui': patch
---
Handle focusin event in invokers in LionAccordion. Fix tabbing issues.

View file

@ -10,6 +10,7 @@ import { uuid } from '@lion/ui/core.js';
* @property {HTMLElement} content content node
* @property {(event: Event) => unknown} clickHandler executed on click event
* @property {(event: Event) => unknown} keydownHandler executed on keydown event
* @property {(event: Event) => unknown} focusHandler executed on focusin event
*/
/**
@ -197,6 +198,7 @@ export class LionAccordion extends LitElement {
content,
clickHandler: this.__createInvokerClickHandler(index),
keydownHandler: this.__handleInvokerKeydown.bind(this),
focusHandler: this.__createInvokerFocusHandler(index),
};
this._setupContent(entry);
this._setupInvoker(entry);
@ -248,6 +250,19 @@ export class LionAccordion extends LitElement {
};
}
/**
* @param {number} index
* @private
*/
__createInvokerFocusHandler(index) {
return () => {
if (index === this.focusedIndex) {
return;
}
this.focusedIndex = index;
};
}
/**
* @param {Event} e
* @private
@ -304,7 +319,7 @@ export class LionAccordion extends LitElement {
* @protected
*/
_setupInvoker(entry) {
const { invoker, uid, index, clickHandler, keydownHandler } = entry;
const { invoker, uid, index, clickHandler, keydownHandler, focusHandler } = entry;
invoker.style.setProperty('order', `${index + 1}`);
const firstChild = invoker.firstElementChild;
if (firstChild) {
@ -312,6 +327,7 @@ export class LionAccordion extends LitElement {
firstChild.setAttribute('aria-controls', `content-${uid}`);
firstChild.addEventListener('click', clickHandler);
firstChild.addEventListener('keydown', keydownHandler);
firstChild.addEventListener('focusin', focusHandler);
}
}
@ -320,13 +336,14 @@ export class LionAccordion extends LitElement {
* @protected
*/
_cleanInvoker(entry) {
const { invoker, clickHandler, keydownHandler } = entry;
const { invoker, clickHandler, keydownHandler, focusHandler } = entry;
const firstChild = invoker.firstElementChild;
if (firstChild) {
firstChild.removeAttribute('id');
firstChild.removeAttribute('aria-controls');
firstChild.removeEventListener('click', clickHandler);
firstChild.removeEventListener('keydown', keydownHandler);
firstChild.removeEventListener('focusin', focusHandler);
}
}

View file

@ -213,6 +213,17 @@ describe('<lion-accordion>', () => {
el.focusedIndex = 1;
expect(spy).to.have.been.calledOnce;
});
it('tabbing sets the focusedIndex correctly', async () => {
const el = /** @type {LionAccordion} */ (await fixture(basicAccordion));
const invokers = getInvokers(el);
el.focusedIndex = 0;
expect(el.focusedIndex).to.equal(0);
invokers[2].firstElementChild?.dispatchEvent(new Event('focusin'));
expect(el.focusedIndex).to.equal(2);
invokers[1].firstElementChild?.dispatchEvent(new Event('focusin'));
expect(el.focusedIndex).to.equal(1);
});
});
describe('Accordion Contents (slot=content)', () => {