fix(fluid-select): name the listbox from @label - #195
Merged
Merged
Conversation
The listbox is what focus lands on when the popup opens, but it carried no aria-label, so screen readers announced an unnamed element even though the trigger beside it was named. Default it from @Label, above ...attributes so callers can still override. Also pass @Label through to the search input, whose aria-label fallback never received it, and hide the trigger's caret svg from the accessibility tree.
JessWallin
approved these changes
Sep 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Shortcut: [sc-219839]
Problem
fluid-select/list.hbsrendersrole="listbox"with anidandtabindex="-1"but noaria-labeloraria-labelledby. On open,fluid-select.jscallselement.focus({ preventScroll: true })on that list — so the element a screen reader lands on is unnamed, even though the trigger beside it is named correctly from@label.Measured in the computed accessibility tree:
button "Fruit"→listbox (UNNAMED).Neither template lint nor axe catches this: the markup is individually valid, and axe doesn't require a name on a
listbox. It only shows up when you read the computed tree.Two smaller items in the same component:
select.searchrenders aplaceholderand has anaria-label={{or @label "Search options"}}fallback, but@labelwas never passed down — so a searchable select's input is always named the generic "Search options".Fix
Fall back to
@labelon the listbox when the caller passes nothing....attributesalready reaches the list, so placingaria-label={{@label}}above it keeps callers able to override. This clears all 62 canvas call sites without a single call-site change, and makes the localaria-labelworkarounds in select-field and the timezone picker redundant (they still win via...attributes).list.hbs—aria-label={{@label}}above...attributesfluid-select.hbs— passlabel=@labelto the curriedlistandsearchcomponentstrigger.hbs—aria-hidden="true"on the caret svgTesting
Computed tree now reads
listbox "Fruit". Two new integration tests cover the default name and the...attributesoverride; the existing search-combobox test now asserts the@labelpass-through instead of the fallback string. 30/30 fluid-select tests pass.Related
Same shape as the two FluidCheckbox asks sitting unraised in the plan's Upstream status — a component emitting an ARIA structure it doesn't finish wiring.