diff --git a/core/src/components/accordion-group/accordion-group.tsx b/core/src/components/accordion-group/accordion-group.tsx index fd00f64c9a..8d5c9596b0 100644 --- a/core/src/components/accordion-group/accordion-group.tsx +++ b/core/src/components/accordion-group/accordion-group.tsx @@ -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) { diff --git a/core/src/components/accordion/test/a11y/e2e.ts b/core/src/components/accordion/test/a11y/e2e.ts index 1913f017a6..f25141b93a 100644 --- a/core/src/components/accordion/test/a11y/e2e.ts +++ b/core/src/components/accordion/test/a11y/e2e.ts @@ -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'); }); diff --git a/core/src/components/accordion/test/a11y/index.html b/core/src/components/accordion/test/a11y/index.html index 486660cfe6..0c660ef8dd 100644 --- a/core/src/components/accordion/test/a11y/index.html +++ b/core/src/components/accordion/test/a11y/index.html @@ -86,7 +86,7 @@ Address 1 - + Address 2