Skip to content

[Bug]: Webkit on MacOS won't tab between buttons #41808

Description

@radium-v

Version

1.61.1

Steps to reproduce

https://github.com/radium-v/playwright-macos-webkit-button-focus-bug

Create a test which uses keyboard navigation to change focus between <button> elements:

import { test, expect } from '@playwright/test';

test.describe("should focus between buttons", () => {
    test("using `page.keyboard.press`", async ({ page }) => {
        await page.goto("about:blank");

        await page.evaluate(() => {
            for (let i = 0; i < 3; i++) {
                const button = document.createElement("button");
                button.textContent = `Button ${i + 1}`;
                document.body.appendChild(button);
            }
        });

        await page.locator("button").first().focus();
        await expect(page.locator("button").first()).toBeFocused();

        await page.keyboard.press("Tab");
        await expect(page.locator("button").nth(1)).toBeFocused();

        await page.keyboard.press("Tab");
        await expect(page.locator("button").nth(2)).toBeFocused();
    });

    test("using `locator.press`", async ({ page }) => {
        await page.goto("about:blank");

        await page.evaluate(() => {
            for (let i = 0; i < 3; i++) {
                const button = document.createElement("button");
                button.textContent = `Button ${i + 1}`;
                document.body.appendChild(button);
            }
        });

        await page.locator("button").first().focus();
        await expect(page.locator("button").first()).toBeFocused();

        await page.locator("button").first().press("Tab");
        await expect(page.locator("button").nth(1)).toBeFocused();

        await page.locator("button").nth(1).press("Tab");
        await expect(page.locator("button").nth(2)).toBeFocused();
    });
});

Expected behavior

When running the tests in Chromium, Firefox, and WebKit, the focus should move between the three buttons on the page when the Tab key is pressed.

Actual behavior

When running the tests in WebKit on MacOS, the focusability of the buttons is dependent on the OS-level System Setting System Settings > Keyboard > Keyboard navigation. When this toggle is on, the focus moves between buttons as expected and the tests pass. When this toggle is off, the focus does not move between buttons and the tests fail.

Additional context

This issue is similar to #2114 but the referenced Safari setting "Press Tab to highlight each item on a webpage" seems to have no effect on the Playwright Webkit browser. However, there's a MacOS System Settings toggle called "Keyboard navigation" that does affect it, and turning it on will allow tests to pass.

Another interesting quirk is that adding a tabindex to the buttons will allow the tests to pass regardless of the aforementioned MacOS and Safari settings. This can be helpful locally, but adding a tabindex feels like an unnecessary workaround, and would have to be performed every time a <button> is expected to be tabbable.

So far my investigations have led to this workaround:

defaults write org.webkit.Playwright AppleKeyboardUIMode -int 2
npx playwright test --project=webkit
defaults delete org.webkit.Playwright AppleKeyboardUIMode

Environment

System:
  OS: macOS 26.5.2
  CPU: (12) arm64 Apple M3 Pro
  Memory: 423.22 MB / 36.00 GB
Binaries:
  Node: 24.18.0 - /usr/local/bin/node
  Yarn: 1.22.22 - /usr/local/bin/yarn
  npm: 11.16.0 - /usr/local/bin/npm
IDEs:
  VSCode: 1.129.0 - /usr/local/bin/code
Languages:
  Bash: 3.2.57 - /bin/bash
npmPackages:
  @playwright/test: 1.61.1 => 1.61.1

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions