Allow localization of TextField clear button aria-label#3879
Conversation
🦋 Changeset detectedLatest commit: 5754746 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Co-authored-by: jonrohan <54012+jonrohan@users.noreply.github.com>
Co-authored-by: jonrohan <54012+jonrohan@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds support for localizing the TextField clear button’s accessible name by introducing an optional clear_button_label parameter with a default fallback.
Changes:
- Adds
clear_button_labeltoPrimer::Forms::Dsl::TextFieldInputand wires it to the clear buttonaria-label - Updates Lookbook preview + snapshot metadata to demonstrate a custom label
- Adds tests covering default and custom clear button
aria-labelvalues
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
app/lib/primer/forms/dsl/text_field_input.rb |
Adds clear_button_label parameter to the input model. |
app/lib/primer/forms/text_field.html.erb |
Uses clear_button_label (with default) for the clear button aria-label. |
previews/primer/alpha/text_field_preview.rb |
Adds preview param and a new preview example for a custom label. |
test/components/alpha/text_field_test.rb |
Adds assertions for default and custom aria-label values. |
static/previews.json |
Registers the new preview for snapshots/visual regression. |
static/info_arch.json |
Registers the new preview for info architecture metadata. |
.changeset/fifty-cheetahs-explode.md |
Publishes a minor changeset for the new option. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <% end %> | ||
| <% if @input.show_clear_button? %> | ||
| <button type="button" id="<%= @input.clear_button_id %>" class="FormControl-input-trailingAction" aria-label="Clear" data-action="click:primer-text-field#clearContents"> | ||
| <button type="button" id="<%= @input.clear_button_id %>" class="FormControl-input-trailingAction" aria-label="<%= @input.clear_button_label || 'Clear' %>" data-action="click:primer-text-field#clearContents"> |
There was a problem hiding this comment.
clear_button_label will override the default even when it is an empty string, resulting in aria-label="" (no accessible name) and an accessibility regression if a translation returns blank. Consider falling back to the default when the label is blank (e.g., treat blank as nil) or validate/normalize clear_button_label upstream so the rendered aria-label is always non-empty when the clear button is shown.
| <button type="button" id="<%= @input.clear_button_id %>" class="FormControl-input-trailingAction" aria-label="<%= @input.clear_button_label || 'Clear' %>" data-action="click:primer-text-field#clearContents"> | |
| <button type="button" id="<%= @input.clear_button_id %>" class="FormControl-input-trailingAction" aria-label="<%= @input.clear_button_label.presence || 'Clear' %>" data-action="click:primer-text-field#clearContents"> |
| @clear_button_id = system_arguments.delete(:clear_button_id) || SecureRandom.uuid | ||
| @clear_button_label = system_arguments.delete(:clear_button_label) |
There was a problem hiding this comment.
clear_button_label is accepted without any normalization/validation. If callers pass an empty string (common with missing i18n keys), the template will render an empty aria-label. Consider normalizing blank strings to nil (or raising an ArgumentError when show_clear_button is true and the label is blank) to prevent generating an unlabeled button.
What are you trying to accomplish?
The TextField clear button had a hardcoded
aria-label="Clear", preventing localization for non-English users. Added optionalclear_button_labelparameter to enable customization while maintaining backward compatibility.Changes:
clear_button_labelparameter toTextFieldInputaria-label="<%= @input.clear_button_label || 'Clear' %>"Usage:
Integration
List the issues that this change affects.
Related to #3803
Risk Assessment
Rationale: Single optional parameter with fallback to existing value. ERB escaping handles XSS. All tests pass.
What approach did you choose and why?
Followed existing pattern from
CloseButtoncomponent. Optional parameter with fallback maintains backward compatibility. ERB auto-escaping prevents XSS without additional sanitization.Alternative considered: Using
aria("label", system_arguments)pattern was unnecessary since we need a simple string parameter, not nested hash extraction.Anything you want to highlight for special attention from reviewers?
N/A
Accessibility
Merge checklist
Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
accounts.google.com/proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --no-sandbox --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=7448 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/ferrum_user_data_dir_20260124-7420-6r45j4 --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,13077906749086937319,7043892377557521415,262144 --enable-features=NetworkService,NetworkServiceInProcess --disable-features=IsolateOrigins,PaintHolding,TranslateUI,site-per-process --variations-seed-version --trace-process-track-uuid=3190708989122997041(dns block)/opt/google/chrome/chrome /usr/bin/google-chrome --headless --disable-gpu --hide-scrollbars --mute-audio --enable-automation --disable-web-security --disable-session-crashed-bubble --disable-breakpad --disable-sync --no-first-run --use-mock-keychain --keep-alive-for-test --disable-popup-blocking --disable-extensions --disable-component-extensions-with-REDACTED-pages --disable-hang-monitor --disable-features=site-per-process,IsolateOrigins,TranslateUI --disable-translate --disable-REDACTED-networking(dns block)/proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --no-sandbox --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=7842 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/ferrum_user_data_dir_20260124-7814-5gu04k --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,4133958615491614166,16603117403907789,262144 --enable-features=NetworkService,NetworkServiceInProcess --disable-features=IsolateOrigins,PaintHolding,TranslateUI,site-per-process --variations-seed-version --trace-process-track-uuid=3190708989122997041(dns block)clients2.google.com/proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --no-sandbox --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=7448 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/ferrum_user_data_dir_20260124-7420-6r45j4 --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,13077906749086937319,7043892377557521415,262144 --enable-features=NetworkService,NetworkServiceInProcess --disable-features=IsolateOrigins,PaintHolding,TranslateUI,site-per-process --variations-seed-version --trace-process-track-uuid=3190708989122997041(dns block)/opt/google/chrome/chrome /usr/bin/google-chrome --headless --disable-gpu --hide-scrollbars --mute-audio --enable-automation --disable-web-security --disable-session-crashed-bubble --disable-breakpad --disable-sync --no-first-run --use-mock-keychain --keep-alive-for-test --disable-popup-blocking --disable-extensions --disable-component-extensions-with-REDACTED-pages --disable-hang-monitor --disable-features=site-per-process,IsolateOrigins,TranslateUI --disable-translate --disable-REDACTED-networking(dns block)/proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --no-sandbox --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=7842 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/ferrum_user_data_dir_20260124-7814-5gu04k --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,4133958615491614166,16603117403907789,262144 --enable-features=NetworkService,NetworkServiceInProcess --disable-features=IsolateOrigins,PaintHolding,TranslateUI,site-per-process --variations-seed-version --trace-process-track-uuid=3190708989122997041(dns block)content-autofill.googleapis.com/proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --no-sandbox --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=7842 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/ferrum_user_data_dir_20260124-7814-5gu04k --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,4133958615491614166,16603117403907789,262144 --enable-features=NetworkService,NetworkServiceInProcess --disable-features=IsolateOrigins,PaintHolding,TranslateUI,site-per-process --variations-seed-version --trace-process-track-uuid=3190708989122997041(dns block)/opt/google/chrome/chrome /usr/bin/google-chrome --headless --disable-gpu --hide-scrollbars --mute-audio --enable-automation --disable-web-security --disable-session-crashed-bubble --disable-breakpad --disable-sync --no-first-run --use-mock-keychain --keep-alive-for-test --disable-popup-blocking --disable-extensions --disable-component-extensions-with-REDACTED-pages --disable-hang-monitor --disable-features=site-per-process,IsolateOrigins,TranslateUI --disable-translate --disable-REDACTED-networking(dns block)/proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --no-sandbox --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=8079 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/ferrum_user_data_dir_20260124-8052-dfqazs --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,17947037700202989643,3241429548600794507,262144 --enable-features=NetworkService,NetworkServiceInProcess --disable-features=IsolateOrigins,PaintHolding,TranslateUI,site-per-process --variations-seed-version --trace-process-track-uuid=3190708989122997041(dns block)optimizationguide-pa.googleapis.com/proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --no-sandbox --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=7842 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/ferrum_user_data_dir_20260124-7814-5gu04k --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,4133958615491614166,16603117403907789,262144 --enable-features=NetworkService,NetworkServiceInProcess --disable-features=IsolateOrigins,PaintHolding,TranslateUI,site-per-process --variations-seed-version --trace-process-track-uuid=3190708989122997041(dns block)/opt/google/chrome/chrome /usr/bin/google-chrome --headless --disable-gpu --hide-scrollbars --mute-audio --enable-automation --disable-web-security --disable-session-crashed-bubble --disable-breakpad --disable-sync --no-first-run --use-mock-keychain --keep-alive-for-test --disable-popup-blocking --disable-extensions --disable-component-extensions-with-REDACTED-pages --disable-hang-monitor --disable-features=site-per-process,IsolateOrigins,TranslateUI --disable-translate --disable-REDACTED-networking(dns block)/proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --no-sandbox --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=8079 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/ferrum_user_data_dir_20260124-8052-dfqazs --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,17947037700202989643,3241429548600794507,262144 --enable-features=NetworkService,NetworkServiceInProcess --disable-features=IsolateOrigins,PaintHolding,TranslateUI,site-per-process --variations-seed-version --trace-process-track-uuid=3190708989122997041(dns block)safebrowsingohttpgateway.googleapis.com/proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --no-sandbox --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=7448 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/ferrum_user_data_dir_20260124-7420-6r45j4 --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,13077906749086937319,7043892377557521415,262144 --enable-features=NetworkService,NetworkServiceInProcess --disable-features=IsolateOrigins,PaintHolding,TranslateUI,site-per-process --variations-seed-version --trace-process-track-uuid=3190708989122997041(dns block)/opt/google/chrome/chrome /usr/bin/google-chrome --headless --disable-gpu --hide-scrollbars --mute-audio --enable-automation --disable-web-security --disable-session-crashed-bubble --disable-breakpad --disable-sync --no-first-run --use-mock-keychain --keep-alive-for-test --disable-popup-blocking --disable-extensions --disable-component-extensions-with-REDACTED-pages --disable-hang-monitor --disable-features=site-per-process,IsolateOrigins,TranslateUI --disable-translate --disable-REDACTED-networking(dns block)/proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --no-sandbox --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=7842 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/ferrum_user_data_dir_20260124-7814-5gu04k --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,4133958615491614166,16603117403907789,262144 --enable-features=NetworkService,NetworkServiceInProcess --disable-features=IsolateOrigins,PaintHolding,TranslateUI,site-per-process --variations-seed-version --trace-process-track-uuid=3190708989122997041(dns block)www.google.com/proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --no-sandbox --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=7448 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/ferrum_user_data_dir_20260124-7420-6r45j4 --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,13077906749086937319,7043892377557521415,262144 --enable-features=NetworkService,NetworkServiceInProcess --disable-features=IsolateOrigins,PaintHolding,TranslateUI,site-per-process --variations-seed-version --trace-process-track-uuid=3190708989122997041(dns block)/opt/google/chrome/chrome /usr/bin/google-chrome --headless --disable-gpu --hide-scrollbars --mute-audio --enable-automation --disable-web-security --disable-session-crashed-bubble --disable-breakpad --disable-sync --no-first-run --use-mock-keychain --keep-alive-for-test --disable-popup-blocking --disable-extensions --disable-component-extensions-with-REDACTED-pages --disable-hang-monitor --disable-features=site-per-process,IsolateOrigins,TranslateUI --disable-translate --disable-REDACTED-networking(dns block)/proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --no-sandbox --disable-dev-shm-usage --use-angle=swiftshader-webgl --mute-audio --crashpad-handler-pid=7842 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/ferrum_user_data_dir_20260124-7814-5gu04k --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,4133958615491614166,16603117403907789,262144 --enable-features=NetworkService,NetworkServiceInProcess --disable-features=IsolateOrigins,PaintHolding,TranslateUI,site-per-process --variations-seed-version --trace-process-track-uuid=3190708989122997041(dns block)If you need me to access, download, or install something from one of these locations, you can either:
Original prompt
aria-labelis not localized/customizable #3804💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.