Merge pull request #783 from ing-bank/fix/keyboard-interactio-accordion

fix(accordion): fix keyboard interaction
This commit is contained in:
gerjanvangeest 2020-06-24 16:28:04 +02:00 committed by GitHub
commit 9f6fbb66a1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 40 additions and 38 deletions

View file

@ -2,41 +2,41 @@
"name": "@lion/accordion", "name": "@lion/accordion",
"version": "0.1.1", "version": "0.1.1",
"description": "Vertically stacked list of invokers that can be clicked to reveal or hide content associated with them.", "description": "Vertically stacked list of invokers that can be clicked to reveal or hide content associated with them.",
"license": "MIT",
"author": "ing-bank", "author": "ing-bank",
"homepage": "https://github.com/ing-bank/lion/", "homepage": "https://github.com/ing-bank/lion/",
"license": "MIT",
"publishConfig": {
"access": "public"
},
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/ing-bank/lion.git", "url": "https://github.com/ing-bank/lion.git",
"directory": "packages/accordion" "directory": "packages/accordion"
}, },
"main": "index.js",
"module": "index.js",
"files": [
"*.js",
"docs",
"src",
"test",
"translations"
],
"scripts": { "scripts": {
"prepublishOnly": "../../scripts/npm-prepublish.js", "prepublishOnly": "../../scripts/npm-prepublish.js",
"start": "cd ../../ && yarn dev-server --open packages/tabs/README.md", "start": "cd ../../ && yarn dev-server --open packages/tabs/README.md",
"test": "cd ../../ && yarn test:browser --grep \"packages/tabs/test/**/*.test.js\"", "test": "cd ../../ && yarn test:browser --grep \"packages/tabs/test/**/*.test.js\"",
"test:watch": "cd ../../ && yarn test:browser:watch --grep \"packages/tabs/test/**/*.test.js\"" "test:watch": "cd ../../ && yarn test:browser:watch --grep \"packages/tabs/test/**/*.test.js\""
}, },
"keywords": [
"lion",
"web-components",
"accordion"
],
"main": "index.js",
"module": "index.js",
"files": [
"docs",
"src",
"test",
"translations",
"*.js"
],
"sideEffects": [ "sideEffects": [
"lion-accordion.js" "lion-accordion.js"
], ],
"dependencies": { "dependencies": {
"@lion/core": "0.7.2" "@lion/core": "0.7.2"
},
"keywords": [
"accordion",
"lion",
"web-components"
],
"publishConfig": {
"access": "public"
} }
} }

View file

@ -13,14 +13,14 @@ const setupInvoker = ({ element, uid, index, clickHandler, keydownHandler }) =>
element.firstElementChild.setAttribute('id', `invoker-${uid}`); element.firstElementChild.setAttribute('id', `invoker-${uid}`);
element.firstElementChild.setAttribute('aria-controls', `content-${uid}`); element.firstElementChild.setAttribute('aria-controls', `content-${uid}`);
element.firstElementChild.addEventListener('click', clickHandler); element.firstElementChild.addEventListener('click', clickHandler);
element.firstElementChild.addEventListener('keyup', keydownHandler); element.firstElementChild.addEventListener('keydown', keydownHandler);
}; };
const cleanInvoker = (element, clickHandler, keydownHandler) => { const cleanInvoker = (element, clickHandler, keydownHandler) => {
element.firstElementChild.removeAttribute('id'); element.firstElementChild.removeAttribute('id');
element.firstElementChild.removeAttribute('aria-controls'); element.firstElementChild.removeAttribute('aria-controls');
element.firstElementChild.removeEventListener('click', clickHandler); element.firstElementChild.removeEventListener('click', clickHandler);
element.firstElementChild.removeEventListener('keyup', keydownHandler); element.firstElementChild.removeEventListener('keydown', keydownHandler);
}; };
const focusInvoker = element => { const focusInvoker = element => {
@ -190,18 +190,14 @@ export class LionAccordion extends LitElement {
case 'ArrowDown': case 'ArrowDown':
case 'ArrowRight': case 'ArrowRight':
e.preventDefault(); e.preventDefault();
if (this.focusedIndex + 1 >= this._pairCount) { if (this.focusedIndex + 2 <= this._pairCount) {
this.focusedIndex = 0;
} else {
this.focusedIndex += 1; this.focusedIndex += 1;
} }
break; break;
case 'ArrowUp': case 'ArrowUp':
case 'ArrowLeft': case 'ArrowLeft':
e.preventDefault(); e.preventDefault();
if (this.focusedIndex <= 0) { if (this.focusedIndex >= 1) {
this.focusedIndex = this._pairCount - 1;
} else {
this.focusedIndex -= 1; this.focusedIndex -= 1;
} }
break; break;

View file

@ -199,10 +199,12 @@ describe('<lion-accordion>', () => {
const invokers = el.querySelectorAll('[slot=invoker]'); const invokers = el.querySelectorAll('[slot=invoker]');
el.focusedIndex = 0; el.focusedIndex = 0;
invokers[0].firstElementChild.dispatchEvent( invokers[0].firstElementChild.dispatchEvent(
new KeyboardEvent('keyup', { key: 'ArrowRight' }), new KeyboardEvent('keydown', { key: 'ArrowRight' }),
); );
expect(el.focusedIndex).to.equal(1); expect(el.focusedIndex).to.equal(1);
invokers[0].firstElementChild.dispatchEvent(new KeyboardEvent('keyup', { key: 'ArrowDown' })); invokers[0].firstElementChild.dispatchEvent(
new KeyboardEvent('keydown', { key: 'ArrowDown' }),
);
expect(el.focusedIndex).to.equal(2); expect(el.focusedIndex).to.equal(2);
}); });
@ -219,9 +221,11 @@ describe('<lion-accordion>', () => {
`); `);
const invokers = el.querySelectorAll('[slot=invoker]'); const invokers = el.querySelectorAll('[slot=invoker]');
el.focusedIndex = 2; el.focusedIndex = 2;
invokers[2].firstElementChild.dispatchEvent(new KeyboardEvent('keyup', { key: 'ArrowLeft' })); invokers[2].firstElementChild.dispatchEvent(
new KeyboardEvent('keydown', { key: 'ArrowLeft' }),
);
expect(el.focusedIndex).to.equal(1); expect(el.focusedIndex).to.equal(1);
invokers[1].firstElementChild.dispatchEvent(new KeyboardEvent('keyup', { key: 'ArrowUp' })); invokers[1].firstElementChild.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowUp' }));
expect(el.focusedIndex).to.equal(0); expect(el.focusedIndex).to.equal(0);
}); });
@ -235,18 +239,18 @@ describe('<lion-accordion>', () => {
</lion-accordion> </lion-accordion>
`); `);
const invokers = el.querySelectorAll('[slot=invoker]'); const invokers = el.querySelectorAll('[slot=invoker]');
invokers[1].firstElementChild.dispatchEvent(new KeyboardEvent('keyup', { key: 'Home' })); invokers[1].firstElementChild.dispatchEvent(new KeyboardEvent('keydown', { key: 'Home' }));
expect(el.focusedIndex).to.equal(0); expect(el.focusedIndex).to.equal(0);
}); });
it('selects last invoker on [end]', async () => { it('selects last invoker on [end]', async () => {
const el = await fixture(basicAccordion); const el = await fixture(basicAccordion);
const invokers = el.querySelectorAll('[slot=invoker]'); const invokers = el.querySelectorAll('[slot=invoker]');
invokers[0].firstElementChild.dispatchEvent(new KeyboardEvent('keyup', { key: 'End' })); invokers[0].firstElementChild.dispatchEvent(new KeyboardEvent('keydown', { key: 'End' }));
expect(el.focusedIndex).to.equal(2); expect(el.focusedIndex).to.equal(2);
}); });
it('selects first invoker on [arrow-right] if on last invoker', async () => { it('stays on last invoker on [arrow-right]', async () => {
const el = await fixture(html` const el = await fixture(html`
<lion-accordion focusedIndex="2"> <lion-accordion focusedIndex="2">
<h2 slot="invoker"><button>invoker 1</button></h2> <h2 slot="invoker"><button>invoker 1</button></h2>
@ -259,12 +263,12 @@ describe('<lion-accordion>', () => {
`); `);
const invokers = el.querySelectorAll('[slot=invoker]'); const invokers = el.querySelectorAll('[slot=invoker]');
invokers[2].firstElementChild.dispatchEvent( invokers[2].firstElementChild.dispatchEvent(
new KeyboardEvent('keyup', { key: 'ArrowRight' }), new KeyboardEvent('keydown', { key: 'ArrowRight' }),
); );
expect(el.focusedIndex).to.equal(0); expect(el.focusedIndex).to.equal(2);
}); });
it('selects last invoker on [arrow-left] if on first invoker', async () => { it('stays on first invoker on [arrow-left]', async () => {
const el = await fixture(html` const el = await fixture(html`
<lion-accordion> <lion-accordion>
<h2 slot="invoker"><button>invoker 1</button></h2> <h2 slot="invoker"><button>invoker 1</button></h2>
@ -276,8 +280,10 @@ describe('<lion-accordion>', () => {
</lion-accordion> </lion-accordion>
`); `);
const invokers = el.querySelectorAll('[slot=invoker]'); const invokers = el.querySelectorAll('[slot=invoker]');
invokers[0].firstElementChild.dispatchEvent(new KeyboardEvent('keyup', { key: 'ArrowLeft' })); invokers[0].firstElementChild.dispatchEvent(
expect(el.focusedIndex).to.equal(2); new KeyboardEvent('keydown', { key: 'ArrowLeft' }),
);
expect(el.focusedIndex).to.equal(null);
}); });
}); });