fix(a11y): dialog names, aria-pressed, labels, avatar alt, placeholder contrast (#278) #436

Merged
jared merged 1 commits from fix/a11y-axe-findings into lotus 2026-10-19 17:06:38 -04:00
Owner

Fixes #278 (the Lotus-specific axe-core findings, plus the avatar alt from the upstream list).

Before → after (axe, WCAG 2.1 A/AA, critical and serious only; local stack):

page before after
room image-alt, placeholder contrast 2.66:1 none
Room Settings → General image-alt none
→ Permissions aria-allowed-attr ×27, image-alt none
→ Emojis & Stickers label (pack name), image-alt none
→ Export label ×2 (From/To), image-alt none
inbox → Invites aria-allowed-attr ×3, image-alt none

Changes

  • Dialog names: Modal500 takes a label. Room Settings ("<room> settings"), Space Settings and the two Settings dialogs now have accessible names.
  • aria-selected on plain buttons → aria-pressed: inbox filter chips, date/time picker chips, and the verification, pack-usage and notification-mode menu items. The Permissions power chips open a menu, so they get aria-haspopup="menu" + aria-expanded instead.
  • Labels: the room pack "Name" and the Export "From"/"To" are now <label for> their inputs.
  • Avatar alt: UserAvatar defaults to alt="" (decorative next to a name or inside a labelled button). Callers that pass alt keep it.
  • Placeholder contrast: the #222 fix (opacity P300 = 0.75) never took effect, because Slate puts an inline opacity: 0.333 on the placeholder. The inline value is now dropped, so the class applies; axe passes.
  • Nested <p> in RoomQuality: already fixed by #291 (SettingTile descriptions are <div>s).
  • CI: e2e/a11y.spec.ts now also audits Room Settings → Permissions, Emojis & Stickers and Export, checks the dialog's name, and audits the inbox. All 7 tests pass locally against a production build.

Not done (the issue's "inherited from upstream, fix when convenient"): keyboard-focusable timeline scroll region, Explore heading order, h1/main landmarks. They're structural and would want their own pass.

🤖 Generated with Claude Code

https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5

Fixes #278 (the Lotus-specific axe-core findings, plus the avatar `alt` from the upstream list). **Before → after** (axe, WCAG 2.1 A/AA, critical and serious only; local stack): | page | before | after | |---|---|---| | room | image-alt, placeholder contrast 2.66:1 | none | | Room Settings → General | image-alt | none | | → Permissions | **aria-allowed-attr ×27**, image-alt | none | | → Emojis & Stickers | **label** (pack name), image-alt | none | | → Export | **label ×2** (From/To), image-alt | none | | inbox → Invites | **aria-allowed-attr ×3**, image-alt | none | **Changes** - **Dialog names:** `Modal500` takes a `label`. Room Settings ("`<room>` settings"), Space Settings and the two Settings dialogs now have accessible names. - **`aria-selected` on plain buttons → `aria-pressed`:** inbox filter chips, date/time picker chips, and the verification, pack-usage and notification-mode menu items. The Permissions power chips open a menu, so they get `aria-haspopup="menu"` + `aria-expanded` instead. - **Labels:** the room pack "Name" and the Export "From"/"To" are now `<label for>` their inputs. - **Avatar alt:** `UserAvatar` defaults to `alt=""` (decorative next to a name or inside a labelled button). Callers that pass `alt` keep it. - **Placeholder contrast:** the #222 fix (opacity P300 = 0.75) never took effect, because Slate puts an inline `opacity: 0.333` on the placeholder. The inline value is now dropped, so the class applies; axe passes. - **Nested `<p>` in RoomQuality:** already fixed by #291 (`SettingTile` descriptions are `<div>`s). - **CI:** `e2e/a11y.spec.ts` now also audits Room Settings → Permissions, Emojis & Stickers and Export, checks the dialog's name, and audits the inbox. All 7 tests pass locally against a production build. **Not done** (the issue's "inherited from upstream, fix when convenient"): keyboard-focusable timeline scroll region, Explore heading order, `h1`/`main` landmarks. They're structural and would want their own pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
jared added 1 commit 2026-10-19 15:36:06 -04:00
fix(a11y): axe findings: dialog names, aria-pressed, labels, avatar alt, placeholder contrast (#278)
CI / Build & Quality Checks (pull_request) Successful in 1m47s
CI / Trigger Desktop Build (pull_request) Skipped
CI / Docker image build & smoke test (pull_request) Skipped
CI / Secret scan (gitleaks) (pull_request) Successful in 7s
CI / Playwright smoke (e2e) (pull_request) Successful in 12m18s
885ec7c82e
- Modal500 takes a label: Room/Space Settings ("<name> settings") and
  Settings dialogs have accessible names.
- aria-selected on plain buttons (inbox filter chips, date/time picker
  chips, verification/usage/notification menu items) -> aria-pressed; the
  Permissions power chips open a menu -> aria-haspopup + aria-expanded.
- Labels tied to the room pack name input and the Export From/To dates.
- UserAvatar defaults to alt="" (decorative next to a name / in a
  labelled button) unless a caller passes one.
- Composer placeholder: Slate's inline opacity 0.333 overrode the #222
  AA-contrast class (2.66:1); it is dropped so the class (0.75) applies.
- e2e/a11y.spec.ts also audits Room Settings → Permissions, Emojis &
  Stickers and Export, checks the dialog name, and audits the inbox.

Fixes #278

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
jared merged commit 5d2d7ca63c into lotus 2026-10-19 17:06:38 -04:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: LotusGuild/cinny#436