fix(accordion-group): only allow keyboard interaction if header is focused (#25091)

This commit is contained in:
Amanda Smith
2022-04-12 13:57:18 -05:00
committed by GitHub
parent a0054a7cbd
commit e1b555f286
3 changed files with 30 additions and 1 deletions

View File

@ -101,6 +101,17 @@ export class AccordionGroup implements ComponentInterface {
return;
}
/**
* Make sure focus is in the header, not the body, of the accordion. This ensures
* that if there are any interactable elements in the body, their keyboard
* interaction doesn't get stolen by the accordion. Example: using up/down keys
* in ion-textarea.
*/
const activeAccordionHeader = activeElement.closest('ion-accordion [slot="header"]');
if (!activeAccordionHeader) {
return;
}
const accordionEl =
activeElement.tagName === 'ION-ACCORDION' ? activeElement : activeElement.closest('ion-accordion');
if (!accordionEl) {

View File

@ -5,6 +5,11 @@ const getActiveElementText = async (page) => {
return page.evaluate((el) => el?.innerText, activeElement);
};
const getActiveInputID = async (page) => {
const activeElement = await page.evaluateHandle(() => document.activeElement);
return page.evaluate((el) => el?.closest('ion-input')?.id, activeElement);
};
test('accordion: a11y', async () => {
const page = await newE2EPage({
url: '/src/components/accordion/test/a11y?ionic:_testing=true',
@ -42,4 +47,17 @@ test('accordion: keyboard navigation', async () => {
await page.keyboard.press('ArrowUp');
expect(await getActiveElementText(page)).toEqual('Shipping Address');
// open Shipping Address accordion and move focus to the input inside it
await page.keyboard.press('Enter');
await page.waitForChanges();
await page.keyboard.press('Tab');
const activeID = await getActiveInputID(page);
expect(activeID).toEqual('address1');
// ensure keyboard interaction doesn't move focus from body
await page.keyboard.press('ArrowDown');
const activeIDAgain = await getActiveInputID(page);
expect(activeIDAgain).toEqual('address1');
});

View File

@ -86,7 +86,7 @@
<ion-list slot="content">
<ion-item>
<ion-label>Address 1</ion-label>
<ion-input type="text"></ion-input>
<ion-input id="address1" type="text"></ion-input>
</ion-item>
<ion-item>
<ion-label>Address 2</ion-label>