Skip to content

a11y: Critical VoiceOver labels for icon/color-only UI#2124

Merged
garthvh merged 2 commits into
meshtastic:mainfrom
bruschill:a11y/pr1-critical-labels
Jul 20, 2026
Merged

a11y: Critical VoiceOver labels for icon/color-only UI#2124
garthvh merged 2 commits into
meshtastic:mainfrom
bruschill:a11y/pr1-critical-labels

Conversation

@bruschill

Copy link
Copy Markdown
Contributor

🔗 Stacked on #2117 (a11y: Localize VoiceOver accessibility strings). This branch builds on that localization foundation because both touch the same regions of MQTTConfig.swift and Localizable.xcstrings. Until #2117 is merged, this PR's diff includes its commits (25 files); once #2117 merges it reduces to just the critical-label additions below (7 files, +87/−6).

What changed?

Adds VoiceOver labels to the highest-impact icon-only / color-only UI so it's no longer invisible to VoiceOver.

  • LoRaSignalStrengthIndicator — the color-only LoRa signal bars announce their strength.
  • MessageText — message security state exposed via stable, Identifiable corner badges (encrypted / verified / store-and-forward).
  • SecurityConfig — the crypto key action buttons (copy/generate) get actionable labels.
  • MQTTConfig — config sliders and the show-password control get labels/values.
  • ChannelForm / AppSettings — icon-only controls and status get spoken labels; plural-aware "%lld days" where a count is announced.
  • Own delta: 7 files changed, +87 / −6; 10 additive Localizable.xcstrings keys.

Why did it change?

Critical, security-relevant UI — message encryption/verification badges, LoRa signal strength, and crypto-key buttons — conveyed meaning through color or an unlabeled icon only, so VoiceOver users couldn't perceive it. These are the most important labels in the initiative.

How is this tested?

Built the Meshtastic scheme for iOS Simulator (iPhone 17 Pro, Xcode 26) → ** BUILD SUCCEEDED **. SwiftLint clean (the message badges were refactored into an Identifiable CornerBadge struct with a stable id to satisfy large_tuple and avoid render churn). Passed a focused Swift/SwiftUI review (both nits — stable badge id, plural-aware %lld days — addressed). A live VoiceOver pass is recommended before merge.

Screenshots/Videos (when applicable)

N/A — no visual change; adds spoken VoiceOver labels/values only.

Checklist

  • My code adheres to the project's coding and style guidelines.
  • I have conducted a self-review of my code.
  • I have commented my code, particularly in complex areas.
  • I have verified whether these changes require updates to the in-app documentation under docs/user/ or docs/developer/. No doc update is needed (VoiceOver labels only, no UI/flow change) — please apply the skip-docs-check label.
  • I have tested the change to ensure that it works as intended.

Wrap hardcoded English accessibility labels/hints/values in String(localized:)
so Xcode extracts them and the app's 18 locales can translate them. Previously
these bound to the non-localizing StringProtocol overload. Adds the 15 missing
source keys to the String Catalog with translator comments.

Chart-mark labels/values are intentionally excluded (handled in a later Charts
a11y PR). Existing NSLocalizedString a11y strings are left as-is.
Expose meaning that was previously conveyed only visually:
- Message status badges (PKI-encrypted lock, XEdDSA-signed shield, store-forward
  envelope) plus detection-sensor and translate overlays now have labels.
- LoRaSignalStrengthIndicator gains label + value, mirroring the BLE indicator.
- Position-precision sliders (MQTT, ChannelForm) announce their value and hide
  the decorative plus/minus marker images from VoiceOver.
- Purge-stale-nodes days slider announces a plural-aware day count.
- Destructive crypto buttons (delete key backup, regenerate private key) get
  labels instead of reading as raw SF Symbol names.

Refactors the message badge tuple into an Identifiable CornerBadge struct
(resolves a large_tuple lint) with a stable id. Adds 10 source keys.
@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@bruschill, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 59 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 60c79971-0395-49ec-9ae4-175ee8fce3cc

📥 Commits

Reviewing files that changed from the base of the PR and between e531f15 and 9d8b1cd.

📒 Files selected for processing (25)
  • Localizable.xcstrings
  • Meshtastic/Views/Helpers/BLESignalStrengthIndicator.swift
  • Meshtastic/Views/Helpers/BatteryGauge.swift
  • Meshtastic/Views/Helpers/ConnectedDevice.swift
  • Meshtastic/Views/Helpers/LoRaSignalStrengthIndicator.swift
  • Meshtastic/Views/Messages/MessageSearchBar.swift
  • Meshtastic/Views/Messages/MessageText.swift
  • Meshtastic/Views/Messages/RetryButton.swift
  • Meshtastic/Views/Messages/TextMessageField/RequestPositionButton.swift
  • Meshtastic/Views/Messages/UserList.swift
  • Meshtastic/Views/Nodes/Helpers/Map/CoverageEstimateForm.swift
  • Meshtastic/Views/Nodes/Helpers/Map/WaypointForm.swift
  • Meshtastic/Views/Nodes/LocalStatsLog.swift
  • Meshtastic/Views/Nodes/MeshMapMK.swift
  • Meshtastic/Views/Nodes/NodeList.swift
  • Meshtastic/Views/Settings/AppSettings.swift
  • Meshtastic/Views/Settings/BackupManagement/BackupManagement.swift
  • Meshtastic/Views/Settings/Channels/ChannelForm.swift
  • Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift
  • Meshtastic/Views/Settings/Config/Module/StatusMessageConfig.swift
  • Meshtastic/Views/Settings/Config/SecurityConfig.swift
  • Meshtastic/Views/Settings/Firmware/Chirpy Game/FirmwareUpdateGameView.swift
  • Meshtastic/Views/Settings/HelpAndDocumentation/AIDocAssistantView.swift
  • Meshtastic/Views/Settings/HelpAndDocumentation/DocBrowserView.swift
  • Meshtastic/Views/Settings/HelpAndDocumentation/DocPageView.swift

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@bruschill bruschill added the skip-docs-check Use this label to skip the automatic docs audit label Jul 19, 2026

@garthvh garthvh left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved after detailed manual review (CodeRabbit was rate-limited and did not run). Additive VoiceOver labels + String(localized:) conversions; no behavior/layout/binding changes; CI green. Part of the a11y series (pr1).

@garthvh
garthvh merged commit 1ce6508 into meshtastic:main Jul 20, 2026
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-docs-check Use this label to skip the automatic docs audit

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants