OTP: fix click-to-focus and overwrite-on-retype by mdo · Pull Request #42524 · twbs/bootstrap · GitHub
Skip to content

OTP: fix click-to-focus and overwrite-on-retype#42524

Open
mdo wants to merge 2 commits into
v6-devfrom
mdo/otp-input-focus-fix
Open

OTP: fix click-to-focus and overwrite-on-retype#42524
mdo wants to merge 2 commits into
v6-devfrom
mdo/otp-input-focus-fix

Conversation

@mdo

@mdo mdo commented Jun 18, 2026

Copy link
Copy Markdown
Member

Summary

The single-input OTP rewrite (#42500) improved accessibility but left two interaction gaps reported after merge:

  1. You couldn't click a slot to focus it. The slots had pointer-events: none and focus always jumped to the end of the value, so the click position was ignored.
  2. Retyping a digit shifted the others along. A native <input> inserts, so editing mid-value pushed the remaining digits down. OTP entry expects overwrite.

Both stem from the same thing: a single, full-width, centered input can't map a click to a slot, and native editing inserts rather than overwrites.

Approach

Keep the single accessible <input> (preserving the one-announced-field, autocomplete="one-time-code", SMS autofill, password-manager, and formatted-paste wins) and make its interaction faithful to the input-otp model:

  • Active slot = a selection range[i, i+1] on a filled slot so the next keystroke overwrites it, [i, i] on an empty one so it appends.
  • beforeinput handler intercepts single-character typing (overwrite + advance) and backspace (clear / step back). Paste, SMS autofill, and IME composition still fall through to the existing bulk input path.
  • Clickable slots — a pointerdown handler focuses the input and positions the caret on the clicked slot, clamped to the first empty slot.
  • Sane focus — Tab/focus() land on the first empty slot instead of the absolute end; a document selectionchange listener keeps the active-slot highlight in sync with the caret.

@mdo mdo requested review from a team as code owners June 18, 2026 17:07
@mdo mdo changed the title OtpInput: fix click-to-focus and overwrite-on-retype OTP: fix click-to-focus and overwrite-on-retype Jun 23, 2026
@mdo mdo added this to v6.0.0 Jun 23, 2026
@github-project-automation github-project-automation Bot moved this to Inbox in v6.0.0 Jun 23, 2026
The single-input rewrite left two interaction gaps: clicking a slot
didn't position the caret there (slots had pointer-events: none and
focus always jumped to the end), and retyping inserted instead of
overwriting, so preceding digits shifted along.

Keep the single accessible input but make its interaction faithful to
the input-otp model:

- Represent the active slot as a selection range so the next keystroke
  overwrites a filled slot or appends to an empty one
- Intercept single-char typing and backspace via beforeinput for
  overwrite semantics; paste/autofill/IME still flow through input
- Make slots clickable (pointerdown) to position the caret, clamped to
  the first empty slot
- Land focus on the first empty slot instead of the end; track the caret
  with a document selectionchange listener
@mdo mdo force-pushed the mdo/otp-input-focus-fix branch from c1fa103 to 0586af7 Compare June 23, 2026 16:39
@coliff

coliff commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Inbox

Development

Successfully merging this pull request may close these issues.

2 participants