
Maui Accessibility
- 31 installs
- 163 repo stars
- Updated July 6, 2026
- davidortinau/maui-skills
Makes .NET MAUI apps accessible with screen reader support via SemanticProperties, heading levels, AutomationProperties, and programmatic focus and announcements.
About
Guides making .NET MAUI apps accessible through SemanticProperties, heading levels, AutomationProperties visibility control, and programmatic focus and announcements. A developer uses it when adding screen reader and accessibility support to a MAUI app.
- Screen reader support via SemanticProperties and heading levels
- Programmatic focus control and announcements
Maui Accessibility by the numbers
- 31 all-time installs (skills.sh)
- Ranked #661 of 1,039 Mobile Development skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/davidortinau/maui-skills --skill maui-accessibilityAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 31 |
|---|---|
| repo stars | ★ 163 |
| Last updated | July 6, 2026 |
| Repository | davidortinau/maui-skills ↗ |
What it does
Makes .NET MAUI apps accessible with screen reader support via SemanticProperties, heading levels, AutomationProperties, and programmatic focus and announcements.
Files
.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:
1. Images: Add SemanticProperties.Description to meaningful images. Set AutomationProperties.IsInAccessibleTree="false" on decorative ones. 2. Buttons/Controls: Ensure icon-only buttons have Description. Text buttons generally don't need it. 3. Entries/Editors: Use Placeholder for context. Add Hint only if extra instruction is needed. Avoid `Description` (Android breakage). 4. Labels: Do not add Description — let Text speak for itself. Add HeadingLevel to section headers. 5. Headings: Mark page title as Level1, section titles as Level2, etc. 6. Grouping: Avoid Description on layout containers (iOS breakage). Use ExcludedWithChildren to hide decorative groups. 7. Dynamic content: Call SemanticScreenReader.Announce for status changes. Use SetSemanticFocus after navigation or error display. 8. Tab order: Set TabIndex on interactive controls for logical order. 9. Test: Run TalkBack (Android), VoiceOver (iOS/Mac), and Narrator (Windows) to verify reading order and actions.
Accessibility API Reference
SemanticProperties (Attached Properties)
Set on any VisualElement to provide screen reader context.
| Property | Purpose |
|---|---|
SemanticProperties.Description | Accessible name read by screen reader |
SemanticProperties.Hint | Extra context (e.g. "Double tap to activate") |
SemanticProperties.HeadingLevel | Heading landmark: None, Level1–Level9 |
XAML
<Button Text="Save"
SemanticProperties.Description="Save your changes"
SemanticProperties.Hint="Double tap to save the current document" />
<Label Text="Settings"
SemanticProperties.HeadingLevel="Level1" />C#
var btn = new Button { Text = "Save" };
SemanticProperties.SetDescription(btn, "Save your changes");
SemanticProperties.SetHint(btn, "Double tap to save the current document");
var heading = new Label { Text = "Settings" };
SemanticProperties.SetHeadingLevel(heading, SemanticHeadingLevel.Level1);Programmatic Focus & Announcements
SetSemanticFocus
Move screen reader focus to an element after a UI change:
errorLabel.Text = "Username is required";
errorLabel.SetSemanticFocus();SemanticScreenReader.Announce
Push a live announcement without moving focus:
SemanticScreenReader.Announce("File uploaded successfully");Use Announce for transient status updates. Use SetSemanticFocus when the user must interact with the target element.
AutomationProperties
Control whether an element appears in the accessibility tree.
| Property | Effect |
|---|---|
AutomationProperties.IsInAccessibleTree | false hides the element from screen readers |
AutomationProperties.ExcludedWithChildren | true hides the element and all descendants |
<!-- Decorative image — hide from screen reader -->
<Image Source="bg.png"
AutomationProperties.IsInAccessibleTree="false" />
<!-- Container with purely decorative content -->
<Grid AutomationProperties.ExcludedWithChildren="true">
<Image Source="pattern.png" />
</Grid>Deprecated AutomationProperties → SemanticProperties
| Deprecated | Replacement |
|---|---|
AutomationProperties.Name | SemanticProperties.Description |
AutomationProperties.HelpText | SemanticProperties.Hint |
Avoid the deprecated properties in new code. They may not work consistently across platforms and will be removed in a future release.