Shopify / Shopify/dawn

Quantity +/- buttons decrement when activated by a screen reader (2.1.1)

Open Beginner friendly
#3,972 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Liquid
Stars
3.1k
Forks
4.5k
PR merge metrics
No merged PRs in 30d

Description

Describe the current behavior

Version: Dawn v15.4.0

Description

QuantityInput.onButtonClick in assets/global.js branches on
event.target.name with no third branch, so any activation whose target is a
descendant of the button falls through to stepDown(). Pressing the PLUS
button with a screen reader running therefore DECREASES the quantity.

if (event.target.name === 'plus') { … this.input.stepUp(); }
else { this.input.stepDown(); }

The same flaw appears in the 'minus' min-reset comparison a few lines below,
which silently never fires on the same path.

Why it only reproduces with assistive technology

The button's accessible name lives on a .visually-hidden span. That span is
1×1 with pointer-events: auto, while .svg-wrapper and the icon carry
pointer-events: none. A mouse click at the button's centre therefore
hit-tests to the BUTTON and works correctly — but a screen reader activates
the element carrying the accessible name, and the span legitimately wins that
hit test. Measured with NVDA + Firefox, isTrusted: true, so this is a real
OS-level click, not synthetic dispatch:

target: SPAN | class: visually-hidden | target.name: undefined | button.name: plus  | isTrusted: true
target: SPAN | class: visually-hidden | target.name: undefined | button.name: minus | isTrusted: true

event.target.closest('button').name resolves correctly in every case.

Dawn already does this correctly elsewhere. The slider handlers in the
same file use event.currentTarget.name five times (approx. lines 814, 896,
900, 903, 909). Only the quantity handler uses event.target.name.

Impact: WCAG 2.1.1 Keyboard (Level A). Neither Enter nor Space works;
the control is operable by mouse and not by keyboard under a screen reader.

Fix

event.currentTarget.name at both comparisons — the listener is bound
directly to each button, so currentTarget is the button.

Describe the expected behavior

Version information (Dawn, browsers and operating systems)

  • Dawn Version: 7.0.1
  • Chrome Version 108.0.5359.124
  • macOS Version 13.1

Possible solution

Additional context/screenshots

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in assets/global.js at QuantityInput.onButtonClick and compare the quantity handler with the slider handlers that use currentTarget.name. Verify activation when the event target is the visually-hidden span, then confirm that plus increases and minus decreases quantity, including the min-reset behavior, under screen-reader keyboard activation.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
accessibility, frontend
Issue type
Bug
Difficulty
1/5
Estimated time
Under an hour
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
92/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.