Skip to content

docs: hide placeholder select options from assistive tech - #42739

Open
Hashim1999164 wants to merge 1 commit into
twbs:mainfrom
Hashim1999164:docs/select-placeholder-aria-hidden-37614
Open

docs: hide placeholder select options from assistive tech#42739
Hashim1999164 wants to merge 1 commit into
twbs:mainfrom
Hashim1999164:docs/select-placeholder-aria-hidden-37614

Conversation

@Hashim1999164

@Hashim1999164 Hashim1999164 commented Jul 23, 2026

Copy link
Copy Markdown

Summary

  • Adds aria-hidden="true" to default placeholder <option> elements in form documentation examples.
  • Covers select, floating-labels, layout, input-group, validation docs, cheatsheet examples, and the floating-label visual test page.

Motivation

When a select receives focus, assistive technologies can vocalize the placeholder option text (for example, "Open this select menu") even though the visible <label> or aria-label already describes the control. Hiding placeholder options from the accessibility tree avoids redundant announcements.

Fixes #37614

Test plan

  • Verified placeholder options in updated docs include aria-hidden="true"
  • Left real selected values (for example, month dropdowns) unchanged

Add aria-hidden="true" to default placeholder options in form docs so screen readers do not vocalize hint text when focus enters a select.

Fixes twbs#37614
@greptile-apps

greptile-apps Bot commented Jul 23, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds aria-hidden="true" to placeholder <option> elements across Bootstrap's form documentation examples and visual test pages, aiming to prevent assistive technologies from announcing redundant placeholder text (e.g., "Open this select menu") when a labeled select receives focus.

  • The approach is applied uniformly across standard dropdowns, floating labels, input groups, layout examples, validation forms, and the RTL cheatsheet — but without differentiating between standard collapsed dropdowns (where the intent is reasonable) and always-expanded multiple/size selects (where hiding a visible, navigable option from AT is an accessibility anti-pattern).
  • For validation selects that already carry disabled value="", the added aria-hidden on the currently selected option risks suppressing the value announcement when AT focuses the control, and the existing disabled attribute already provides the needed non-interactivity signal at the HTML level.
  • Broader concern: screen readers on Windows (NVDA, JAWS) often access native <select> elements via OS-level accessibility APIs (IAccessible2/UIA) rather than the ARIA tree, so aria-hidden on <option> children may be silently ignored across major AT/browser pairings, making the documented pattern ineffective in practice.

Confidence Score: 3/5

Not safe to merge as-is — the change propagates a pattern that may silently fail on major screen readers, and actively introduces an accessibility inconsistency in expanded listbox selects.

The multiple and size select examples in select.mdx now hide a visible, navigable option from AT while keeping it selectable for mouse/sighted users. Across all files, the fix relies on aria-hidden propagating through OS-level accessibility APIs for native select controls, which is not guaranteed on Windows screen readers. The validation examples add aria-hidden to the currently-selected option, risking suppression of value announcements if browsers do honor the attribute.

select.mdx (multiple and size select examples), validation.mdx (selected+disabled placeholder options), and floating-labels.mdx all need a second look before merging.

Important Files Changed

Filename Overview
site/src/content/docs/forms/select.mdx Adds aria-hidden="true" to all placeholder options including those in multiple and size selects where options are permanently visible, creating AT inconsistency; also raises broader concerns about aria-hidden support on native option elements.
site/src/content/docs/forms/validation.mdx Adds aria-hidden="true" to placeholder options that already carry disabled and value="" — may suppress AT value-announcement for the currently selected option, and the attribute interaction with native OS accessibility APIs is inconsistent.
site/src/content/docs/forms/floating-labels.mdx Applies aria-hidden="true" to placeholder options in standard (non-multiple, non-size) floating-label selects; rationale is sound but relies on inconsistently supported ARIA propagation for native OS widgets.
site/src/content/docs/forms/input-group.mdx Adds aria-hidden="true" to "Choose..." placeholder options in input-group selects; same AT-support uncertainty applies.
site/src/content/docs/forms/layout.mdx Applies aria-hidden="true" to "Choose..." placeholder options in layout examples; change is mechanical and consistent with the rest of the PR.
js/tests/visual/floating-label.html Mirrors the floating-labels doc change across multiple visual test select variants including disabled and long-text placeholder options.
site/src/assets/examples/cheatsheet/index.astro Adds aria-hidden="true" to placeholder options in the cheatsheet examples, including the validation "Choose..." option that already has disabled value="".
site/src/assets/examples/cheatsheet-rtl/index.astro RTL cheatsheet mirror of the LTR cheatsheet changes; same pattern applied to Arabic placeholder options.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Select element receives AT focus] --> B{Select type?}
    B -->|Standard dropdown| C[Select collapsed - AT announces label + current value]
    B -->|multiple or size select| D[Listbox always expanded - all options visible]
    C --> E{aria-hidden on selected option?}
    D --> F[User navigates options with arrow keys]
    E -->|No - baseline| G[AT announces current option text normally]
    E -->|Yes - this PR| H{Browser honors aria-hidden on option?}
    H -->|Yes - ARIA tree path| I[AT skips option - current value silent]
    H -->|No - OS API path| J[aria-hidden ignored - AT still announces option]
    F --> K[Option visible but silent to AT]
    K --> L[WCAG 1.3.1 concern: info available visually but not to AT]
Loading

Comments Outside Diff (1)

  1. site/src/content/docs/forms/select.mdx, line 36-43 (link)

    P1 aria-hidden on expanded listbox option creates AT inconsistency

    The multiple and size="3" select controls render as always-expanded listboxes where every option is simultaneously visible on-screen. Adding aria-hidden="true" to the first option means a sighted user can see and click it, while a screen reader user navigating the list with arrow keys will skip it silently — a visible, selectable item that AT cannot perceive. This violates WCAG 1.3.1 (Info and Relationships), where information conveyed visually must also be programmatically available. The safer fix for these two specific examples is to remove the misleading "Open this select menu" option entirely or replace it with a non-selected, genuinely descriptive first option.

Reviews (1): Last reviewed commit: "docs: hide placeholder select options fr..." | Re-trigger Greptile

Comment on lines 9 to 14
Custom `<select>` menus need only a custom class, `.form-select` to trigger the custom styles. Custom styles are limited to the `<select>`’s initial appearance and cannot modify the `<option>`s due to browser limitations.

<Example code={`<select class="form-select" aria-label="Default select example">
<option selected>Open this select menu</option>
<option selected aria-hidden="true">Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 aria-hidden on <option> has inconsistent AT support

Screen readers on Windows (NVDA, JAWS) traditionally access native <select> elements through OS-level accessibility APIs (IAccessible2/UIA) rather than the ARIA accessibility tree. The degree to which those APIs propagate aria-hidden on individual <option> children varies by browser/AT pairing. There's real risk that the attribute is silently ignored by major screen readers in practice, leaving the documentation teaching a pattern that may not behave as described. A more broadly supported technique for a non-selectable placeholder is disabled hidden value="" on the <option>, which signals non-selectability at the HTML level rather than relying on ARIA propagation through a native OS widget. This applies across every changed file in this PR.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point on the uneven AT support. The intent here is only to stop the placeholder from being read out as a real choice in the options list; visual rendering is unchanged. If the team prefers, I can scope this down to the select.mdx examples only, or drop it entirely in favor of documenting the disabled+hidden placeholder pattern instead. Happy to go either way.

Comment on lines 69 to 73
<div class="col-md-3">
<label for="validationCustom04" class="form-label">State</label>
<select class="form-select" id="validationCustom04" required>
<option selected disabled value="">Choose...</option>
<option selected disabled value="" aria-hidden="true">Choose...</option>
<option>...</option>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 aria-hidden on the currently-selected option may suppress value announcement

In these validation examples the placeholder option is both selected and the current value of the control. When AT focuses the <select>, it typically announces the currently selected option text. If that option is aria-hidden="true" and the browser does propagate the attribute, AT would have nothing to announce as the current value — users would know they're on a select control but not what it currently says. The disabled value="" already present on these options communicates non-selectability at the HTML level; the additional aria-hidden is both redundant and potentially harmful to the value-announcement flow.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is the stronger concern, since the placeholder is also the current value here and hiding it could leave the control announcing nothing on focus. I can revert the validation.mdx changes so aria-hidden is only used where the placeholder is not the selected value, if that is the direction the team wants.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

in docs/forms/select, the default selected option tag should have an aria-hidden="true"

2 participants