Repository navigation
Conversation
A checkbox rendered without a label and without an explicit accessibility_label exposed an empty accessible name, so UIA consumers could not tell two of them apart in a list. Resolve the announced name as: the explicit accessibility_label, then the visible label, then the element id. The id fallback keeps every checkbox addressable and distinguishable.
huacnlee
left a comment
There was a problem hiding this comment.
Thanks for picking up #3381 — the missing name is a real gap. I don't think the element id is the right fallback, though.
1. It overrides names that already work. A checkbox may carry its text as children instead of .label(...) (has_content counts children). With no explicit label, AccessKit names Role::CheckBox from its descendant Role::Label nodes (accesskit_consumer::Node::labelled_by → LabelledBy::FromDescendants), and GPUI text elements are Role::Label. So today
Checkbox::new("agree").child("I agree to the terms")is announced as "I agree to the terms". With this PR the label is always set explicitly, so it becomes "agree".
2. An id is not a name. Ids are developer identifiers: unlocalized, and Integer, NamedInteger and Uuid ids are read out as "3", "row-5" or a UUID. It also hides the problem from audit tools: Accessibility Insights stops flagging the missing name while users still hear nothing meaningful. Our own setting/fields/bool.rs shows it: every bool setting is Checkbox::new("check"), so they would all be announced "check", still indistinguishable. Button, Switch and Radio don't fall back to the id either.
3. The test only covers the private helper, not the name in the AccessKit tree, so it can't catch (1).
Suggested direction (the issue's second option):
- Drop the id fallback, and document on
Checkbox::accessibility_label(and the en/zh-CN docs) that a checkbox without visible text must set it. - Fix the internal unnamed usage: pass the setting's title as
accessibility_labelfor theCheckbox/Switchinsetting/fields/bool.rs.
Fixes #3381.
What
A
Checkboxbuilt without.label(...)or.accessibility_label(...)reported an empty accessible name, so UIA (and VoiceOver) consumers could
not tell two unnamed checkboxes in a list apart. The checked state was
already reported correctly — only the name was missing.
How
Checkbox::rendernow resolves the announced name in one place,accessible_name: an explicitaccessibility_labelwins, then thevisible label, and finally the element id. The id fallback gives every
control a distinguishing, non-empty name, which is the first suggestion
in the issue (and mirrors how
Buttonderives its name from its label).No public API changed:
accessible_nameis private and the builder APIis untouched.
Tests
an_unlabeled_checkbox_is_named_after_its_idcovers the id fallback,an explicit name, and the visible label.
cargo test -p gpui-component— 657 lib tests + 48 integration tests, all green.cargo clippy -p gpui-component --all-targets -- --deny warningscargo fmt --checkAI assistance
The change and its test were drafted with an AI coding agent, then
reviewed, compiled and tested locally before submitting.