Skip to content

Arrow keys on radio buttons are backwards #1198

@joshferrell

Description

@joshferrell

Reproduction example

https://codesandbox.io/p/devbox/github/joshferrell/user-event-radio-demo/tree/main/

Prerequisites

Create a series of radio inputs

<label><input type="radio" name="group" value="a" />A</label>
<label><input type="radio" name="group" value="d" />D</label>
<label><input type="radio" name="group" value="e" />E</label>

Create a test that confirms radio behavior using the userEvent keyboard function

describe('Radio implementation', () => {
    test.each([
      {
        name: "per [ArrowDown]",
        focus: 'A',
        key: "[ArrowDown]",
        expectedTarget: 'D',
      },
      {
        name: "per [ArrowLeft]",
        focus: 'D',
        key: "[ArrowLeft]",
        expectedTarget: 'A',
      },
      {
        name: "per [ArrowRight]",
        focus: 'A',
        key: "[ArrowRight]",
        expectedTarget: 'D',
      },
      {
        name: "per [ArrowUp]",
        focus: 'D',
        key: "[ArrowUp]",
        expectedTarget: 'A',
      },
      {
        name: "forward around the corner",
        focus: 'E',
        key: "[ArrowRight]",
        expectedTarget: 'A',
      },
      {
        name: "backward around the corner",
        focus: 'A',
        key: "[ArrowUp]",
        expectedTarget: 'E',
      },
    ])('$name', async ({ focus, key, expectedTarget }) => {
      const user = userEvent.setup()
        render(<App />)
        screen.getByLabelText(focus).focus()
        await user.keyboard(key)
        expect(screen.getByLabelText(expectedTarget)).toHaveFocus()
    })
})

Expected behavior

Behavior

Arrow Right

If A is selected and ArrowRight is pressed, D should be selected
If E is selected and ArrowRight is pressed, A should be selected

Arrow Down

If A is selected and ArrowDown is pressed, D should be selected
If E is selected and ArrowDown is pressed, A should be selected

Arrow Left

If D is selected and ArrowLeft is pressed, A should be selected
If A is selected and ArrowLeft is pressed, E should be selected

Arrow Up

If D is selected and ArrowUp is pressed, A should be selected
If A is selected and ArrowUp is pressed, E should be selected

Actual behavior

Behavior

Arrow Right

If A is selected and ArrowRight is pressed, E is selected
If E is selected and ArrowRight is pressed, D is selected

Arrow Down

If A is selected and ArrowDown is pressed, D is selected
If E is selected and ArrowDown is pressed, A is selected

Arrow Left

If D is selected and ArrowLeft is pressed, E is selected
If A is selected and ArrowLeft is pressed, D is selected

Arrow Up

If D is selected and ArrowUp is pressed, A is selected
If A is selected and ArrowUp is pressed, E is selected

User-event version

14.5.2

Environment

Testing Library framework: @testing-library/[email protected] and @testing-library/user-event:14.5.2

JS framework: [email protected]

Test environment: [email protected]
Also ran in the user-event test suite and had the same issue

DOM implementation: [email protected]

Additional context

There are two issues with the current implementation of the keyboard event and handling radios.

  1. The walk radio function does not quit the for loop if it finds the next element
  2. Arrow Down and Arrow Up directions are inverted.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions