radix-ui / primitives

Radix Primitives is an open-source UI component library for building high-quality, accessible design systems and web apps. Maintained by @workos.
https://radix-ui.com/primitives
MIT License
15.67k stars 806 forks source link

[Dropdown Menu] WCAG2.2 SC 2.5.2 violation - Dropdown Menu opens on `onPointerDown` #3124

Open bolonio opened 1 month ago

bolonio commented 1 month ago

Bug report

The Radix Dropdown Menu component opens on onPointerDown (which means as soon as a mouse navigation user presses the triggering element of the dropdown menu), but there is not available a function on the up-event, or a mechanism to abort the function before completion or to undo the function after completion. You can take a look at the Understanding SC 2.5.2: Pointer Cancellation (Level A) article for more information.

The intent of this success criterion is to make it easier for users to prevent accidental or erroneous pointer input. People with various disabilities can inadvertently initiate touch or mouse events with unwanted results. Each of the following subsections roughly aligns with the bullets of this Success Criterion, and outlines a means of allowing users to cancel pointer operations.

Source: Understanding SC 2.5.2: Pointer Cancellation (Level A)

Current behavior

  1. A mouse navigation user clicks (and holds) the triggering element of the dropdown menu.
  2. Without releasing, moves the mouse outside of both the triggering element or the dropdown menu area.
  3. The dropdown menu is not closed (cancelling the function).

CleanShot 2024-09-18 at 15 40 57

Expected behavior

  1. A mouse navigation user clicks (and holds) the triggering element of the dropdown menu.
  2. The dropdown menu is not yet open.
  3. The user releases the mouse click while still hovering the triggering element of the dropdown menu.
  4. The dropdown menu opens.

CleanShot 2024-09-18 at 15 45 29

You can see the behaviour in the W3C Menu Button Pattern or in the W3C Menu Bar Pattern

CleanShot 2024-09-18 at 15 42 00

or moving the mouse outside of the dropdown menu triggering and content should cancel the onPointerDown function.

  1. A mouse navigation user clicks (and holds) the triggering element of the dropdown menu.
  2. The dropdown menu opens.
  3. Without releasing, moves the mouse outside of both the triggering element or the dropdown menu area.
  4. The dropdown menu closes.
  5. The user releases the mouse click while hovering outside of both the triggering element or the dropdown menu area.
  6. The dropdown menu is still closed.

Reproducible example

Radix Dropdown Menu component

Suggested solution

Change the opening of the dropdown menu to onPointerUp or onClick instead of using onPointerDown.

Additional context

Here there are some examples of Radix components which meet the criteria, such as:

Note: It might be related to https://github.com/radix-ui/primitives/issues/2700 (not 100% sure about it though)

Your environment

Software Name(s) Version
Radix Package(s) @radix-ui/react-dropdown-menu ^2.0.5
React n/a 18.2.0
Browser Google Chrome 128.0.6613.138
Assistive tech
Node n/a
npm/yarn
Operating System MacOS 14.6.1
bolonio commented 2 weeks ago

There's a possible "workaround" that might work (from the side of the consumer), but unfortunately it will only work for mouse users, it breaks the keyboard navigation. I'm still investigating if there's a nicer workaround for both cases.