onFilterStateChange({ ...filterState, resourceTypes: new Set() })}
- className={`network-filters-resource-type ${isAllSelected ? 'selected' : ''}`}
- role='tab'
- tabIndex={isAllSelected ? 0 : -1}
- aria-selected={isAllSelected}
+ className={`network-filters-resource-type ${filterState.resourceTypes.size === 0 ? 'selected' : ''}`}
>
All
@@ -77,7 +64,6 @@ export const NetworkFilters = ({ filterState, onFilterStateChange }: {
}}
className={`network-filters-resource-type ${filterState.resourceTypes.has(resourceType) ? 'selected' : ''}`}
role='tab'
- tabIndex={filterState.resourceTypes.has(resourceType) ? 0 : -1}
aria-selected={filterState.resourceTypes.has(resourceType)}
>
{resourceType}
diff --git a/packages/web/src/components/tabbedPane.tsx b/packages/web/src/components/tabbedPane.tsx
index b0084b4abc6d5..e2d53e1ffb63e 100644
--- a/packages/web/src/components/tabbedPane.tsx
+++ b/packages/web/src/components/tabbedPane.tsx
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import { clsx, handleTabListKeyDown } from '../uiUtils';
+import { clsx } from '../uiUtils';
import './tabbedPane.css';
import { Toolbar } from './toolbar';
import * as React from 'react';
@@ -45,9 +45,24 @@ export const TabbedPane: React.FunctionComponent<{
mode = 'default';
const handleKeyDown = (e: React.KeyboardEvent) => {
- const nextIndex = handleTabListKeyDown(e, tabListRef.current);
- if (nextIndex !== -1)
- setSelectedTab?.(tabs[nextIndex].id);
+ const tabElements = Array.from(tabListRef.current?.querySelectorAll('[role="tab"]') ?? []) as HTMLElement[];
+ const currentIndex = tabElements.findIndex(el => el === document.activeElement);
+ if (currentIndex === -1)
+ return;
+ let nextIndex = currentIndex;
+ if (e.key === 'ArrowRight')
+ nextIndex = (currentIndex + 1) % tabElements.length;
+ else if (e.key === 'ArrowLeft')
+ nextIndex = (currentIndex - 1 + tabElements.length) % tabElements.length;
+ else if (e.key === 'Home')
+ nextIndex = 0;
+ else if (e.key === 'End')
+ nextIndex = tabElements.length - 1;
+ else
+ return;
+ e.preventDefault();
+ tabElements[nextIndex].focus();
+ setSelectedTab?.(tabs[nextIndex].id);
};
return
diff --git a/packages/web/src/uiUtils.ts b/packages/web/src/uiUtils.ts
index bd2c73344e8e8..48b68f91e0a8a 100644
--- a/packages/web/src/uiUtils.ts
+++ b/packages/web/src/uiUtils.ts
@@ -210,27 +210,6 @@ export function scrollIntoViewIfNeeded(element: Element | undefined) {
element?.scrollIntoView();
}
-export function handleTabListKeyDown(e: React.KeyboardEvent, tabListElement: HTMLElement | null): number {
- const tabElements = Array.from(tabListElement?.querySelectorAll('[role="tab"]') ?? []) as HTMLElement[];
- const currentIndex = tabElements.findIndex(el => el === document.activeElement);
- if (currentIndex === -1)
- return -1;
- let nextIndex = currentIndex;
- if (e.key === 'ArrowRight')
- nextIndex = (currentIndex + 1) % tabElements.length;
- else if (e.key === 'ArrowLeft')
- nextIndex = (currentIndex - 1 + tabElements.length) % tabElements.length;
- else if (e.key === 'Home')
- nextIndex = 0;
- else if (e.key === 'End')
- nextIndex = tabElements.length - 1;
- else
- return -1;
- e.preventDefault();
- tabElements[nextIndex].focus();
- return nextIndex;
-}
-
const kControlCodesRe = '\\u0000-\\u0020\\u007f-\\u009f';
export const kWebLinkRe = new RegExp('(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}:\\/\\/|www\\.)[^\\s' + kControlCodesRe + '"]{2,}[^\\s' + kControlCodesRe + '"\')}\\],:;.!?]', 'ug');
diff --git a/tests/playwright-test/ui-mode-test-network-tab.spec.ts b/tests/playwright-test/ui-mode-test-network-tab.spec.ts
index 29d2bcd88eab4..406336e75cae2 100644
--- a/tests/playwright-test/ui-mode-test-network-tab.spec.ts
+++ b/tests/playwright-test/ui-mode-test-network-tab.spec.ts
@@ -478,51 +478,3 @@ test('should preserve selection during test run', async ({ runUITest, server },
await page.waitForTimeout(1000);
await expect(headersPanel).toBeVisible();
});
-
-test('should support keyboard navigation for resource type filters', async ({ runUITest, server }) => {
- server.setRoute('/api/endpoint', (_, res) => res.setHeader('Content-Type', 'application/json').end());
-
- const { page } = await runUITest({
- 'network-tab.test.ts': `
- import { test, expect } from '@playwright/test';
- test('network tab test', async ({ page }) => {
- await page.goto('${server.PREFIX}/network-tab/network.html');
- await page.evaluate(() => (window as any).donePromise);
- });
- `,
- });
-
- await page.getByRole('treeitem', { name: 'network tab test' }).dblclick();
- await expect(page.getByTestId('workbench-run-status')).toContainText('Passed');
-
- await page.getByRole('tab', { name: 'Network' }).click();
-
- const filters = page.locator('.network-filters-resource-types');
-
- // Focus the "All" tab and navigate with arrow keys.
- await filters.getByText('All', { exact: true }).focus();
- await page.keyboard.press('ArrowRight');
- await expect(filters.getByText('Fetch', { exact: true })).toBeFocused();
-
- await page.keyboard.press('ArrowRight');
- await expect(filters.getByText('HTML', { exact: true })).toBeFocused();
-
- await page.keyboard.press('ArrowRight');
- await expect(filters.getByText('JS', { exact: true })).toBeFocused();
-
- // ArrowLeft goes back.
- await page.keyboard.press('ArrowLeft');
- await expect(filters.getByText('HTML', { exact: true })).toBeFocused();
-
- // Home jumps to first tab.
- await page.keyboard.press('Home');
- await expect(filters.getByText('All', { exact: true })).toBeFocused();
-
- // End jumps to last tab.
- await page.keyboard.press('End');
- await expect(filters.getByText('Image', { exact: true })).toBeFocused();
-
- // Wraps around from last to first.
- await page.keyboard.press('ArrowRight');
- await expect(filters.getByText('All', { exact: true })).toBeFocused();
-});