Selector: isLabelHidden hides the label without associating it — trigger has no accessible name
- Dominant language
- TypeScript
- Stars
- 13k
- Forks
- 1.1k
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 690
Description
## Bug: `Selector` with `isLabelHidden` hides the label without associating it — the trigger has no accessible name
**Package:** `@astryxdesign/core@0.5.4`
**Component:** `Selector`
### What happens
`` renders its trigger as:
```html
No project
```
There is no `aria-label` and no `aria-labelledby` pointing back at the visually-hidden label. The trigger's accessible name falls back to its own text content — which is the **currently selected value**, not the field's label.
### Why this is a real-world problem, not a nitpick
In an app with many `Selector` instances on a list (one per row), every trigger with the same current value announces as the *same* accessible name. Concretely: a to-do list with a "Project" selector on every row, where 122 rows have no project selected, produced **122 buttons all named "No project"** to a screen reader — indistinguishable from one another. A "You" default-assignee selector on 118 rows had the same problem.
Passing a more descriptive `label` does **not** help, because `label` is never wired to `aria-label`/`aria-labelledby` on the trigger when `isLabelHidden` is set — only the sighted-visible label element disappears.
### Repro
```tsx
import { Selector } from "@astryxdesign/core/Selector";
{}}
options={[{ value: UNSET, label: "No project" }, { value: "p1", label: "Alpha" }]}
/>
```
Inspect the rendered ``: no `aria-label`, no `aria-labelledby`.
### Expected
When `isLabelHidden` is set, the label should still be associated with the trigger — either:
- render the label element visually-hidden (e.g. `sr-only`) and set `aria-labelledby` to its id, or
- set `aria-label={label}` on the trigger directly.
Either would make `label` do what its name implies even when hidden from sight.
### Current workaround
Pass an explicit `aria-label` prop through `Selector`'s prop spread (it does forward unclaimed props to the trigger, so this works today):
```tsx
```
This works, but it means `label` is effectively decorative/ignored whenever `isLabelHidden` is true, which isn't documented and is easy to miss — we only found it by inspecting the live DOM.
### Version
`@astryxdesign/core@0.5.4`
Contributor guide
Assessment
This issue has not been assessed yet.