maui-accessibility
Installation
SKILL.md
.NET MAUI Accessibility
Critical Platform Gotchas
1. Don't set Description on Label
Setting SemanticProperties.Description on a Label overrides the Text
property for screen readers. The label may be read twice or behave unexpectedly.
<!-- ❌ Stops Text from being read naturally -->
<Label Text="Welcome"
SemanticProperties.Description="Welcome" />
<!-- ✅ Screen reader reads Text automatically -->
<Label Text="Welcome" />
2. Android Entry/Editor: Description breaks TalkBack actions
On Android, setting SemanticProperties.Description on Entry or Editor
causes TalkBack to lose "double tap to edit" action hints.
<!-- ❌ Breaks TalkBack on Android -->
<Entry SemanticProperties.Description="Email address" />
<!-- ✅ Use Placeholder for context instead -->
<Entry Placeholder="Email address" />
3. iOS: Description on parent hides children
On iOS/VoiceOver, setting SemanticProperties.Description on a layout makes the
entire container a single accessible element — child elements become unreachable.
<!-- ❌ Children invisible to VoiceOver -->
<HorizontalStackLayout SemanticProperties.Description="User info">
<Label Text="Name:" />
<Label Text="Alice" />
</HorizontalStackLayout>
<!-- ✅ Let children be individually focusable -->
<HorizontalStackLayout>
<Label Text="Name:" />
<Label Text="Alice" />
</HorizontalStackLayout>
4. Hint conflicts with Entry.Placeholder on Android
On Android, SemanticProperties.Hint and Entry.Placeholder map to the same
Android attribute (contentDescription / hint). Setting both causes one to
override the other. Choose one.
5. HeadingLevel platform differences
- Windows (Narrator): Supports all 9 heading levels (
Level1–Level9). - Android (TalkBack) / iOS (VoiceOver): Only distinguish "heading" vs "not heading". All levels are treated identically.
Use heading levels for semantic correctness — just know the hierarchy only renders on Windows.
Accessibility Checklist
When auditing or retrofitting a page:
- Images: Add
SemanticProperties.Descriptionto meaningful images. SetAutomationProperties.IsInAccessibleTree="false"on decorative ones. - Buttons/Controls: Ensure icon-only buttons have
Description. Text buttons generally don't need it. - Entries/Editors: Use
Placeholderfor context. AddHintonly if extra instruction is needed. AvoidDescription(Android breakage). - Labels: Do not add
Description— letTextspeak for itself. AddHeadingLevelto section headers. - Headings: Mark page title as
Level1, section titles asLevel2, etc. - Grouping: Avoid
Descriptionon layout containers (iOS breakage). UseExcludedWithChildrento hide decorative groups. - Dynamic content: Call
SemanticScreenReader.Announcefor status changes. UseSetSemanticFocusafter navigation or error display. - Tab order: Set
TabIndexon interactive controls for logical order. - Test: Run TalkBack (Android), VoiceOver (iOS/Mac), and Narrator (Windows) to verify reading order and actions.
Related skills