You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* fix(fields): stop the textarea character counter re-announcing on every keystroke (#3408)
The counter block was three things at once: the visible {n}/{max} digits, the
carrier of the translated sentence (#3406) and the aria-live region itself. So
every re-render was an announcement. Measured on origin/main (zh, maxLength
500, a 52-character sentence typed one character at a time): 52 keystrokes ->
52 distinct announcements, 979 spoken characters, ~19x the text being written,
each one interrupting the screen reader's echo of the letter just pressed. The
textarea also carried no aria-describedby, so focusing the field said nothing
about the cap.
Split into the GOV.UK character-count shape:
- the visible digits are aria-hidden and decorative;
- fields.textarea.characterCount moved onto the textarea's aria-describedby
(appended to the host's, never replacing it) and is read once on focus;
- a separate visually-hidden aria-live="polite" region carries a new
near-limit warning, fields.textarea.charactersRemaining (ten packs), gated
to the last 10% / 20 characters of the cap -- whichever comes first -- and
debounced by 1s.
The same 52-keystroke probe now announces 0 times; a run typing all the way
onto a 500-character cap announces 5.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
* refactor(fields): derive the counter status region's silence instead of clearing it in an effect (#3408)
`react-hooks/set-state-in-effect` was right: the synchronous `setStatus('')`
re-rendered on every keystroke the region spends staying quiet, which is most
of them. The settled sentence is now written only by the debounce timer, and
what renders is `settledStatus === pendingStatus ? pendingStatus : ''` -- so
leaving the warning band is silent immediately, with no cascading render.
Not `pendingStatus ? settledStatus : ''`: delete out of the band and type back
in, and that spelling re-announces the count from before the excursion a full
second before the timer corrects it. A wrong number spoken is worse than a
right one spoken twice. Pinned by a new case.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
* style(fields): blank line between the threshold helper and the widget (#3408)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
---------
Co-authored-by: Claude <noreply@anthropic.com>
`TextAreaField`'s character counter no longer re-announces itself on every keystroke. Measured on `main` in a zh session with `maxLength: 500`, typing a 52-character sentence one character at a time produced 52 distinct screen-reader announcements totalling 979 spoken characters — roughly 19x the text being written, each one cutting off the reader's echo of the letter just typed. The counter element was simultaneously the visible `{n}/{max}` digits, the carrier of the translated sentence and the `aria-live` region itself, so "re-render" and "announce" were the same event; the field also had no `aria-describedby`, so focusing it said nothing about the cap at all (#3408).
7
+
8
+
It is now the three-node shape the GOV.UK Design System character-count component uses: the visible digits are `aria-hidden` and purely decorative; the counter sentence (`fields.textarea.characterCount`, unchanged in all ten packs) has moved onto the textarea's `aria-describedby`, so focus reads "Character count: 12 of 500" once and then stays quiet; and a separate visually-hidden `aria-live="polite"` region carries a new near-limit warning, `fields.textarea.charactersRemaining` (new in all ten packs), which stays silent until the value is inside the last 10% or last 20 characters of the cap — whichever the typist reaches first — and updates only after typing pauses for a second. The same 52-keystroke probe now produces zero announcements; a run that types all the way onto a 500-character cap produces five. Any `aria-describedby` the host already supplied (the form renderer's description and error-message ids) is appended to, never replaced.
9
+
10
+
No metadata change: the counter still renders exactly when the field declares `maxLength` (or the legacy `max_length`), and a widget rendered with no `I18nProvider` still shows the same English sentences.
0 commit comments