Skip to content

fix(gui): give MenuRow-based list rows an accessible name - #1448

Open
4ni1ak wants to merge 2 commits into
AprilNEA:masterfrom
4ni1ak:fix/menurow-accessibility-label
Open

4ni1ak wants to merge 2 commits into
AprilNEA:masterfrom
4ni1ak:fix/menurow-accessibility-label

Conversation

@4ni1ak

@4ni1ak 4ni1ak commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Summary

  • NVDA (and presumably other screen readers) announces many OpenLogi list-row controls with no name at all, or only a generic role.

Root cause

MenuRow (crates/openlogi-desktop/src/ui/components.rs) renders its content as arbitrary child elements (ParentElement/children: Vec<AnyElement>). Unlike Switch, which derives an accessible name from its own label text automatically, MenuRow has no such fallback — it needs an explicit accessible name set via GPUI's generic aria_label() (InteractiveElement/StatefulInteractiveElement), which some call sites already do correctly (features/mouse/picker.rs, features/action_ring/editor.rs) and most simply never called.

I initially added a bespoke accessibility_label() builder to MenuRow itself before realizing GPUI already provides aria_label() generically on anything implementing StatefulInteractiveElement (which MenuRow already does) — reverted that in favor of the pattern this codebase already uses elsewhere, for consistency.

Changes

Added .aria_label(...) (reusing text already computed for each row's visible content — no new locale strings) to the MenuRow call sites that were missing it:

  • features/keyboard/editors.rs — workflow step rows (type label: "Type Text" / "Press Key" / etc.)
  • features/keyboard/function_row.rs — per-key power-user action rows (Type Text / AppleScript / Shell / Workflow)
  • features/mouse/inspector.rs — gesture-direction rows and thumbwheel preset rows
  • features/profiles/picker.rs — app-catalog rows (the app's display name)
  • features/profiles/shell.rs — the profile-removal menu item
  • ui/gallery.rs — the demo rows in the component gallery, per this crate's own rule that a changed reusable component's gallery entry must be updated in the same commit

Left alone: features/mouse/picker.rs and features/action_ring/editor.rs (already correct), and the two #[cfg(test)] harness call sites (test scaffolding, not shipped UI).

Scope note

I found (but did not fix) an adjacent, larger gap: gpui-component's Slider widget has no accessibility_label/aria_label support at all, at either the base or component layer — so every slider in this app (DPI, SmartShift threshold, thumbwheel/scroll sensitivity, camera controls) is unlabeled by the underlying library, not by anything in this repo's own code. Fixing that needs an upstream change to gpui-kit, out of scope here.

Testing

  • cargo fmt --all -- --check, cargo clippy -p openlogi-desktop --all-targets -- -D warnings, cargo test -p openlogi-desktop — all green (219 passed, including the gallery render test covering the two rows I touched there).
  • Not runtime-tested with NVDA or on Windows (neither available to me) — this is a compile-checked wiring fix using GPUI's own accessibility API; I did not verify the resulting announcement text end-to-end with a real screen reader.

Fixes #1226 (partially — the Slider gap noted above remains and would need a separate, upstream-dependent fix)

MenuRow renders its content as arbitrary child elements, which — unlike
Switch, which derives an accessible name from its own label text —
carries no accessible name on its own; a caller has to set one via the
generic aria_label() builder GPUI already provides. Most call sites
never did, so NVDA announced only the generic button role with no
name for direction pickers, thumbwheel presets, the app catalog,
per-key power-user actions, and the profile-removal menu item.
@4ni1ak
4ni1ak requested a review from AprilNEA as a code owner September 17, 2026 02:22
@greptile-apps

greptile-apps Bot commented Sep 17, 2026

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

The PR appears safe to merge; the prior accessibility finding is resolved and no new actionable defects remain.

Summary

This PR gives previously unnamed MenuRow controls explicit accessible names and updates the labels identified in the prior review to include distinguishing secondary information.

  • Workflow-step labels now combine the step type with its visible payload preview.
  • Gesture labels combine direction and assigned action; application labels combine display name and stable identifier.
  • Remaining keyboard, mouse, profile, and gallery rows receive labels derived from their visible text.

Reviews (2) · Last reviewed commit: "fix(gui): include distinguishing seconda..."

Comment thread crates/openlogi-desktop/src/features/keyboard/editors.rs Outdated
The explicit aria_label on workflow-step rows, gesture-direction rows,
and application rows in the profile picker only announced each row's
primary title, dropping the secondary text sighted users see (the
step's payload, the direction's assigned action, the app's stable
identifier) — so a screen reader couldn't distinguish rows that look
identical otherwise (two "Type Text" steps, two apps sharing a display
name).

- WorkflowStepRow: extracted step_preview_text() so the aria_label and
  the visible preview text stay in sync.
- Gesture direction rows: append the assigned action's localized label.
- Profile picker application rows: append the app's stable identifier.

Addresses the Greptile P1 finding on AprilNEA#1448.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Windows accessibility: NVDA encounters unnamed or silent controls

1 participant