Skip to content

a11y audit: roles, live regions, content descriptions, and template principles#91

Merged
mapgie merged 1 commit into
mainfrom
claude/goflow-a11y-audit-A900j
Jun 2, 2026
Merged

a11y audit: roles, live regions, content descriptions, and template principles#91
mapgie merged 1 commit into
mainfrom
claude/goflow-a11y-audit-A900j

Conversation

@mapgie
Copy link
Copy Markdown
Owner

@mapgie mapgie commented Jun 2, 2026

$(cat <<'EOF'

Summary

Full accessibility audit of the GoFlo codebase covering five dimensions, with fixes applied across 12 files plus the project template.

  • Content descriptions on icon-only buttons: SpeedDial SmallFABs now carry contentDescription = label on the FAB container itself, so TalkBack announces the action (e.g. "Mood", "Log Period") rather than silence when an icon-only FAB is focused.
  • Keyboard/switch-access roles: All raw .clickable {} elements that had no semantic role now declare .semantics { role = Role.Button } (navigation list items, history cards, stats year picker, chart-type selector, archive section header, alarm permission banner, settings nav items) or Role.RadioButton (category icon picker, themed colour swatches, extended-palette swatches, export format rows). The Export dialog also sets RadioButton(onClick = null) on the inner RadioButton to prevent the double-focus pattern.
  • Status change announcements: PIN entry error text now uses liveRegion = LiveRegionMode.Assertive so TalkBack immediately interrupts to announce "Incorrect PIN". The PinDots indicator uses liveRegion = LiveRegionMode.Polite with a digit-count contentDescription so each keypress is announced. The backspace key gets contentDescription = "Delete" on both PIN screens. Expand/collapse controls gain stateDescription to announce the resulting state.
  • Dynamic text scaling: No hardcoded sp values in Composables; existing Material typography system already handles this correctly. Documented in template.
  • Focus order: Documented in template; no structural changes needed beyond role fixes.

What changed and why

File Change
HomeScreen.kt Modifier.semantics { contentDescription = label } on SpeedDial SmallFAB
ManageScreen.kt Role.Button on both ListItem clickables
StatsWarningBanner.kt Role.Button + stateDescription on expand/collapse Row
HistoryScreen.kt Role.Button on period card clickable
StatsScreen.kt Role.Button on year picker and chart-type selector
ManageCategoriesScreen.kt Role.Button/stateDescription on archive header; Role.RadioButton+selected+contentDescription on icon and colour pickers; Role.Button+contentDescription on custom-colour slot
SettingsScreen.kt Role.Button on SettingsNavItem
RemindersScreen.kt Role.Button on alarm permission ListItem
LockScreen.kt Live region on error text and PinDots; contentDescription = "Delete" on ⌫ button
PinSetupScreen.kt Same as LockScreen
ExportOptionsDialog.kt Role.RadioButton on format rows; RadioButton(onClick = null)
template_requirements.md Accessibility section expanded with five explicit principles
LESSONS.md Three new a11y lessons added

Test plan

  • Activate TalkBack; navigate the home screen speed dial with swipe — each FAB should be announced by name ("Log Period", category name)
  • Use keyboard/switch access on Manage screen — both list items (What You Track, Reminders) should be focusable and announced as buttons
  • Navigate the Stats screen with TalkBack — chart type cards are announced as buttons; year picker rows are buttons
  • On ManageCategories, expand the Archived section — TalkBack should announce "Archived (N), Collapsed" then "Expanded" after tap
  • Open category icon/colour picker — each swatch should be announced as a radio button with its name/hex
  • On LockScreen, type a digit — PinDots should announce "1 of 4 digits entered"; enter wrong PIN — TalkBack interrupts with "Incorrect PIN"
  • On LockScreen, focus the backspace key — TalkBack should say "Delete, button"
  • Export dialog — format rows are announced as radio buttons; JSON/CSV each focus as a single element (no double-focus)
  • Increase system font size to largest; verify no text is clipped on any screen

https://claude.ai/code/session_01AeVcEqKNsCwEG6iSF4MYt4
EOF
)


Generated by Claude Code

…rinciples

- Add contentDescription to SpeedDial SmallFABs (HomeScreen) so TalkBack
  reads the action name rather than nothing when an icon-only FAB is focused.
- Add semantics Role.Button to all raw .clickable{} elements that had no
  role: Manage screen list items, history period cards, stats year picker and
  chart-type selector, archive section header, alarm permission banner, and
  SettingsNavItem.
- Add semantics Role.RadioButton to category icon picker cells, themed colour
  swatches, and extended-palette swatches in the colour picker.
- Set stateDescription on expand/collapse controls (StatsWarningBanner,
  archive header) so TalkBack announces the current expanded/collapsed state.
- Add liveRegion = LiveRegionMode.Assertive to PIN error text on LockScreen
  and PinSetupScreen so incorrect-PIN feedback is announced immediately.
- Add liveRegion = LiveRegionMode.Polite plus contentDescription to PinDots
  on both PIN screens so digit count is announced as each key is pressed.
- Add contentDescription = "Delete" to the ⌫ TextButton on both PIN keypads
  so TalkBack reads the action rather than the raw Unicode symbol.
- Set RadioButton(onClick = null) in ExportOptionsDialog and move the role to
  the wrapping Row, eliminating the duplicate-focus pattern.
- Expand template_requirements.md Accessibility section with five principles:
  content descriptions, keyboard/switch roles, dynamic text scaling, focus
  order, and live-region announcements.
- Add three a11y lessons to LESSONS.md covering .clickable role semantics,
  liveRegion for status changes, and icon-only FAB labelling.

https://claude.ai/code/session_01AeVcEqKNsCwEG6iSF4MYt4
@mapgie mapgie marked this pull request as ready for review June 2, 2026 14:15
@mapgie mapgie merged commit 546b498 into main Jun 2, 2026
4 checks passed
@mapgie mapgie deleted the claude/goflow-a11y-audit-A900j branch June 2, 2026 14:15
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.

2 participants