From f4cb8943e1474f5d0dd271bed751b491e705aa2e Mon Sep 17 00:00:00 2001 From: Rohan <45748283+r100-stack@users.noreply.github.com> Date: Tue, 29 Oct 2024 12:10:06 -0400 Subject: [PATCH] `TablePaginator` fix keyboard navigation out of sync (#2318) --- .../src/core/Table/TablePaginator.tsx | 17 ++++++++- testing/e2e/app/routes/Table/spec.ts | 38 +++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/packages/itwinui-react/src/core/Table/TablePaginator.tsx b/packages/itwinui-react/src/core/Table/TablePaginator.tsx index 72370f1c5ca..ba8ccceafd7 100644 --- a/packages/itwinui-react/src/core/Table/TablePaginator.tsx +++ b/packages/itwinui-react/src/core/Table/TablePaginator.tsx @@ -275,6 +275,7 @@ export const TablePaginator = (props: TablePaginatorProps) => { & Required> & { focusedIndex: number; + setFocusedIndex: React.Dispatch>; totalPagesCount: number; currentPage: number; }; @@ -350,6 +352,7 @@ type TablePaginatorPageButtonsProps = Pick< const TablePaginatorPageButtons = (props: TablePaginatorPageButtonsProps) => { const { focusedIndex, + setFocusedIndex, totalPagesCount, onPageChange, currentPage, @@ -370,7 +373,10 @@ const TablePaginatorPageButtons = (props: TablePaginatorPageButtonsProps) => { styleType='borderless' size={buttonSize} data-iui-active={index === currentPage} - onClick={() => onPageChange(index)} + onClick={() => { + setFocusedIndex(index); + onPageChange(index); + }} aria-current={index === currentPage} aria-label={localization.goToPageLabel?.(index + 1)} tabIndex={tabIndex} @@ -378,7 +384,14 @@ const TablePaginatorPageButtons = (props: TablePaginatorPageButtonsProps) => { {index + 1} ), - [focusedIndex, currentPage, localization, buttonSize, onPageChange], + [ + focusedIndex, + buttonSize, + currentPage, + localization, + setFocusedIndex, + onPageChange, + ], ); const pageList = React.useMemo( diff --git a/testing/e2e/app/routes/Table/spec.ts b/testing/e2e/app/routes/Table/spec.ts index e8219903b7e..05c05bd5767 100644 --- a/testing/e2e/app/routes/Table/spec.ts +++ b/testing/e2e/app/routes/Table/spec.ts @@ -638,6 +638,44 @@ test.describe('Table Paginator', () => { await page.waitForTimeout(300); }); + test('should handle focus of page buttons when focusActivationMode is manual', async ({ + page, + }) => { + await page.goto( + '/Table?exampleType=withTablePaginator&focusActivationMode=manual', + ); + + const paginatorButtons = page.locator('#paginator button', { + hasText: /[0-9]+/, + }); + + await paginatorButtons.nth(8).click(); + await expect(paginatorButtons.nth(8)).toBeFocused(); + + // Confirm that arrow keys move focus from _previously focused page_. + await page.keyboard.press('ArrowRight'); + await expect(paginatorButtons.nth(9)).toBeFocused(); + await expect(paginatorButtons.nth(1)).not.toBeFocused(); + + // Clicking current page itself focuses that page button. + await paginatorButtons.nth(8).click(); + await expect(paginatorButtons.nth(8)).toBeFocused(); + + // Confirm that arrow keys move focus from _previously focused page_. + await page.keyboard.press('ArrowRight'); + await expect(paginatorButtons.nth(9)).toBeFocused(); + await expect(paginatorButtons.nth(10)).not.toBeFocused(); + + // Clicking non-current page focuses that page button. + await paginatorButtons.nth(4).click(); + await expect(paginatorButtons.nth(4)).toBeFocused(); + + // Confirm that arrow keys move focus from _previously focused page_. + await page.keyboard.press('ArrowLeft'); + await expect(paginatorButtons.nth(3)).toBeFocused(); + await expect(paginatorButtons.nth(8)).not.toBeFocused(); + }); + //#region Helpers for table paginator tests const setContainerSize = async (page: Page, value: string | undefined) => { await page.locator('#container').evaluate(