input type="number" not mapped to spinbutton role

input[type=number] mapped to AXTextField instead of AXIncrementor/UIAccessibilityTraitAdjustable in Safari (macOS and iOS).

According to ML-AAM 1.0, <input type="number"> is required to map to the ARIA spinbutton role, but it is not being mapped as expected on WebKit (macOS and iOS) to the platform accessibility APIs: the element is reported as AXTextField on macOS and lacks UIAccessibilityTraitAdjustable on iOS. As a consequence, VoiceOver announces the element as a textfield rather than a spinbutton, does not increment with arrow keys on macOS, and does not respond to the swipe up/down gesture on iOS.

This affects every <input type="number"> on the web (quantity steppers, age inputs, year pickers, etc). Authors are currently forced to work around it by reimplementing the spinbutton with role="spinbutton", which force the authors to emulate the native HTML solutions with JavaScript, contradicts the First Rule of ARIA Use and presents another interaction issues in WebKit (will create an issue about this and update this post later).

References:

Reproduction: https://codesandbox.io/p/sandbox/beautiful-hofstadter-vn7nj3

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>spinbutton techniques</title>
  </head>
  <body>
    <main>
      <h1>Spinbutton pattern</h1>
      <section aria-labelledby="html-solution">
        <h2 id="html-solution">HTML solution: spinbutton</h2>
        <label for="qty">Quantity</label>
        <input id="qty" type="number" min="0" max="10" value="1" />
      </section>
    </main>
  </body>
</html>

Expected behavior:

  • AX role on macOS: AXIncrementor (mapped from spinbutton)
  • AX trait on iOS: UIAccessibilityTraitAdjustable
  • VoiceOver on macOS announces "[value], [name of the input], stepper" and then "you are currently on a stepper. To begin interacting with this stepper, press Control-Shift-Down Arrow", after pressing the combo should announce "in stepper" and inmmediately should announce "you are currently in a stepper. To decrease this value, press Control-Option-Down Arrow. To increase this value, press Control-Option-Up Arrow. to exit this stepper, press Control-Option-Shift-Up Arrow"
  • One-finger swipe up/down on iOS increments/decrements the value

Actual behavior on Safari:

  • AX role on macOS: AXTextField
  • AX trait on iOS: standard textfield, no Adjustable
  • VoiceOver announces "[value], insertion at the beginning/end of the text, [name of the input], number field" and then "you are currently on text field. To enter text in this field, type". Omitting the native functionality of a spinbutton
  • One-finger swipe up/down on iOS does nothing

Cross-platform comparison (same HTML, same spec):

  • Firefox + NVDA on Windows:

  • Chrome + NVDA on Windows: same as Firefox
  • Safari + VoiceOver on macOS: broken as described above
  • Safari + VoiceOver on iOS: broken as described above

Environment:

  • macOS: maOS Tahoe 26.4.1
  • Safari: 26.4 (21624.1.16.11.4)
  • iOS: iOS 26.4.2
  • Device: iPhone 15
  • VoiceOver: default settings
input type="number" not mapped to spinbutton role
 
 
Q