Skip to content

[Enhancement]Add accessibility label support for toolbar back button#35011

Open
Vignesh-SF3580 wants to merge 12 commits intodotnet:net11.0from
Vignesh-SF3580:fix-17984
Open

[Enhancement]Add accessibility label support for toolbar back button#35011
Vignesh-SF3580 wants to merge 12 commits intodotnet:net11.0from
Vignesh-SF3580:fix-17984

Conversation

@Vignesh-SF3580
Copy link
Copy Markdown
Contributor

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Issue Details

There is currently no way to set a custom accessibility label for the toolbar back button independently of the visible text. Screen readers (VoiceOver, TalkBack, Narrator) read the back button’s title, but developers often need a more descriptive label without changing the UI.
This PR addresses that gap for both NavigationPage and Shell across Android, iOS, macCatalyst, and Windows.

Description of Changes

Introduced new BackButtonAccessibilityLabel APIs for both NavigationPage and Shell, allowing developers to customize screen reader announcements independently of the visible back button text.

NavigationPage

  • Added attached property BackButtonAccessibilityLabelProperty with SetBackButtonAccessibilityLabel and GetBackButtonAccessibilityLabel methods
  • The label is set on the parent page and applied to the child page’s back button, following the existing SetBackButtonTitle pattern

Shell

  • Added AccessibilityLabel bindable property to BackButtonBehavior
  • Can be used alongside existing properties like TextOverride and IconOverride

Platform Implementations

Android

  • Applied via ContentDescription on the toolbar navigation icon
  • Implemented through ToolbarExtensions (NavigationPage) and ShellToolbarTracker (Shell)

iOS / macCatalyst

  • Set via AccessibilityLabel on BackBarButtonItem (NavigationPage) and on LeftBarButtonItem / BackBarButtonItem (Shell)
  • Property change handlers added for runtime updates

Windows

  • Applied via AutomationProperties.Name on the back button
  • Uses a save/restore pattern with the Tag property to preserve and restore the default WinUI "Back" announcement

Additional Notes

  • Added 7 unit tests:
    NavigationPage: set, clear, default
    Shell: set, clear, default, dynamic update

  • Updated Public API across all 7 TFM files

Issues Fixed

Fixes #17984

Screenshots

Mac:

Shell NavigationPage

iOS:

Shell NavigationPage

Android:

17984Android.mov

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 17, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 35011

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 35011"

@dotnet-policy-service dotnet-policy-service Bot added the partner/syncfusion Issues / PR's with Syncfusion collaboration label Apr 17, 2026
@Vignesh-SF3580 Vignesh-SF3580 added the community ✨ Community Contribution label Apr 17, 2026
@sheiksyedm sheiksyedm changed the title Add accessibility label support for toolbar back button [Enhancement]Add accessibility label support for toolbar back button Apr 17, 2026
@sheiksyedm sheiksyedm added area-navigation NavigationPage area-controls-shell Shell Navigation, Routes, Tabs, Flyout t/enhancement ☀️ New feature or request t/a11y Relates to accessibility labels Apr 17, 2026
@sheiksyedm sheiksyedm added this to the .NET 11.0-preview4 milestone Apr 17, 2026
@Vignesh-SF3580 Vignesh-SF3580 marked this pull request as ready for review April 17, 2026 13:34
Copilot AI review requested due to automatic review settings April 17, 2026 13:34
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds new APIs to let apps provide a dedicated accessibility label for the toolbar back button (separate from the visible back button title) for both NavigationPage and Shell, and wires it through the relevant toolbars/trackers and platform implementations.

Changes:

  • Introduces NavigationPage.BackButtonAccessibilityLabelProperty (+ Get/SetBackButtonAccessibilityLabel) and BackButtonBehavior.AccessibilityLabel.
  • Plumbs the label into Toolbar.BackButtonAccessibilityLabel, and updates Android/Windows (and partial Tizen) toolbar mappings/platform behavior.
  • Adds unit tests covering default/set/propagation and Shell dynamic update behavior.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
src/Controls/tests/Core.UnitTests/ToolbarTests.cs Adds unit tests for NavigationPage back button accessibility label behavior.
src/Controls/tests/Core.UnitTests/ShellToolbarTests.cs Adds unit tests for Shell/BackButtonBehavior.AccessibilityLabel propagation and updates.
src/Controls/src/Core/Toolbar/Toolbar.cs Adds Toolbar.BackButtonAccessibilityLabel property used by platform toolbars.
src/Controls/src/Core/Toolbar/Toolbar.Android.cs Adds handler mapping to refresh the back button when accessibility label changes (Android).
src/Controls/src/Core/Toolbar/Toolbar.Windows.cs Adds handler mapping to refresh the back button when accessibility label changes (Windows).
src/Controls/src/Core/Toolbar/Toolbar.Tizen.cs Adds Tizen mapping stub for accessibility label.
src/Controls/src/Core/Toolbar/Toolbar.Mapper.cs Registers the new mapping for BackButtonAccessibilityLabel.
src/Controls/src/Core/Platform/Android/Extensions/ToolbarExtensions.cs Sets Android NavigationContentDescription with priority for the new accessibility label.
src/Controls/src/Core/Platform/Windows/Extensions/ToolbarExtensions.cs Sets Windows AutomationProperties.Name for Narrator based on the new accessibility label with save/restore behavior.
src/Controls/src/Core/NavigationPage/NavigationPage.cs Adds attached property and accessor methods for NavigationPage back button accessibility label.
src/Controls/src/Core/NavigationPage/NavigationPageToolbar.cs Propagates the attached accessibility label into the toolbar when navigation stack changes.
src/Controls/src/Core/Shell/BackButtonBehavior.cs Adds AccessibilityLabel bindable property to BackButtonBehavior.
src/Controls/src/Core/ShellToolbar.cs Pulls BackButtonBehavior.AccessibilityLabel into Toolbar.BackButtonAccessibilityLabel.
src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellToolbarTracker.cs Applies custom accessibility label to the Android Shell toolbar navigation content description.
src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellPageRendererTracker.cs Applies custom accessibility label to iOS Shell navigation items/back button items.
src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs Applies back button accessibility label via UIBarButtonItem.AccessibilityLabel for NavigationPage on iOS/macCatalyst.
src/Controls/src/Core/PublicAPI/netstandard/PublicAPI.Unshipped.txt Adds new API entries for NavigationPage/Shell back button accessibility label APIs (netstandard).
src/Controls/src/Core/PublicAPI/net/PublicAPI.Unshipped.txt Adds new API entries for NavigationPage/Shell back button accessibility label APIs (net).
src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt Adds new API entries for NavigationPage/Shell back button accessibility label APIs (Android).
src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt Adds new API entries for NavigationPage/Shell back button accessibility label APIs (iOS).
src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt Adds new API entries for NavigationPage/Shell back button accessibility label APIs (MacCatalyst).
src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt Adds new API entries for NavigationPage/Shell back button accessibility label APIs (Windows).
src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Unshipped.txt Adds new API entries for NavigationPage/Shell back button accessibility label APIs (Tizen).

Comment thread src/Controls/src/Core/PublicAPI/netstandard/PublicAPI.Unshipped.txt Outdated
Comment thread src/Controls/src/Core/PublicAPI/net/PublicAPI.Unshipped.txt Outdated
Comment thread src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt Outdated
Comment thread src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt Outdated
Comment thread src/Controls/tests/Core.UnitTests/ToolbarTests.cs Outdated
Comment thread src/Controls/tests/Core.UnitTests/ShellToolbarTests.cs Outdated
Comment thread src/Controls/src/Core/Toolbar/Toolbar.Tizen.cs
@PureWeen
Copy link
Copy Markdown
Member

PureWeen commented Apr 17, 2026

Multi-Model Code Review: PR #35011

[Enhancement] Add accessibility label support for toolbar back button


Re-Review (April 20) — After Author Fixes

Three independent reviewers re-analyzed the updated diff. Status of each prior finding below.


CI Status

⚠️ FAILING (pre-existing) — 3 failing integration test jobs confirmed pre-existing on net11.0 base branch:

  • AOT windows — ❌ also fails on base branch commit 01e6e37
  • AOT macOS — ❌ also fails on base branch commit 01e6e37
  • Samples macOS — ❌ also fails on base branch commit f6fcd68

Build Analysis failure is a downstream consequence. Evaluate PR Tests/activation is GitHub Actions infrastructure. None of these failures are caused by this PR.

All PR-relevant checks pass: ✅ Build (Debug+Release, macOS+Windows), ✅ Pack, ✅ Helix Unit Tests, ✅ 18 Integration Test jobs (Build, Blazor, MultiProject, RunOnAndroid, RunOniOS ×8, WindowsTemplates, Samples Windows).


Prior Review Status

# Prior Finding Status Agreement
1 🔴 Missing PublicAPI entries for Toolbar + MapBackButtonAccessibilityLabel FIXED 2/3
2 🟡 Shell iOS BackBarButtonItem without visible title FIXED 2/3
3 🟡 iOS AutomationId/AccessibilityLabel inconsistency FIXED 2/3
4 🟡 Test coverage gaps ⚠️ PARTIALLY 3/3
5 🟢 Windows Tag-based save/restore null edge case STILL PRESENT 2/3
6 🟢 iOS NavigationRenderer visual side effect docs N/A 2/3

✅ Finding 1: PublicAPI Entries — FIXED

All Toolbar.BackButtonAccessibilityLabel get/set entries now present across all 7 TFMs. MapBackButtonAccessibilityLabel mapper entries added to net-android, net-windows, net-tizen (correctly absent from net-ios/net-maccatalyst since the mapper is #if ANDROID || WINDOWS || TIZEN). readonly keyword present on BackButtonBehavior.AccessibilityLabelProperty. Entry formatting matches existing BackButtonTitle/MapBackButtonTitle pattern.

✅ Finding 2: Shell iOS Title Fallback — FIXED

ShellPageRendererTracker.UpdateBackButtonTitle now falls back to previousNavItem.Title when only an accessibility label is set:

else if (barButtonItem.Title is null)
{
    // Preserve default back button title when only accessibility label is set
    barButtonItem.Title = previousNavItem.Title;
}

This prevents the chevron-only display and aligns with NavigationRenderer behavior.

✅ Finding 3: AutomationId/AccessibilityLabel Inconsistency — FIXED

The else branch in UpdateLeftToolbarItems now applies the custom accessibility label when AutomationId is set:

else
{
    NavigationItem.LeftBarButtonItem.AccessibilityIdentifier = image.AutomationId;
    if (hasCustomLabel)
    {
        NavigationItem.LeftBarButtonItem.AccessibilityLabel = customAccessibilityLabel;
    }
}

iOS and Android now both apply the custom label regardless of AutomationId presence.

⚠️ Finding 4: Test Coverage — PARTIALLY ADDRESSED

7 unit tests cover set/get, default null, toolbar propagation, and dynamic update for both NavigationPage and Shell. Author correctly notes that verifying native back button accessibility properties requires device tests, which aren't currently supported for toolbar back button properties (consistent with BackButtonTitle which also has no device tests).

Still missing but acceptable:

  • No clear/reset unit test (set label → null → verify toolbar resets)
  • No interaction test (both BackButtonTitle + BackButtonAccessibilityLabel set simultaneously)

❌ Finding 5: Windows Tag Save/Restore — STILL PRESENT (2/3 reviewers)

The save/restore pattern has a theoretical edge case: if AutomationProperties.GetName(backButton) returns null on first save (WinUI's "Back" announcement typically comes from the AutomationProperties.Name, but if it's set via the template's x:Uid or other mechanism):

  1. First set: Tag is not string → true → Tag = null (GetName returned null)
  2. Subsequent mapper call: null is not string → true again → Tag = GetName(backButton) → saves the custom label as the "default"
  3. Clear: restores the custom label instead of the original

Practical impact: Low — WinUI's NavigationView back button typically has AutomationProperties.Name = "Back" set by the default template. A one-line fix would eliminate the risk entirely:

backButton.Tag = AutomationProperties.GetName(backButton) ?? string.Empty;

➖ Finding 6: iOS Visual Side Effect — N/A

Inherent iOS platform behavior; no documentation change needed. The Shell path was actually improved — it reuses existing BackBarButtonItem via ??= instead of creating a new one.


New Findings

🟢 MINOR: Shell iOS Stale TextOverride When Cleared While AccessibilityLabel Retained (1/3 reviewers)

File: ShellPageRendererTracker.csUpdateBackButtonTitle
Issue: If TextOverride is set to "Custom" alongside AccessibilityLabel, then TextOverride is cleared to null while keeping AccessibilityLabel, the back button title remains "Custom" instead of reverting to the page's default title.

Mechanism: The fallback else if (barButtonItem.Title is null) only triggers for newly-created items. When the existing BackBarButtonItem already has Title = "Custom" from the previous TextOverride, the null check is false and the title is never reset.

Practical impact: Very niche — requires setting both properties then clearing only one. The fix would be:

barButtonItem.Title = text ?? previousNavItem.Title ?? string.Empty;

Test Coverage Assessment

The 7 unit tests adequately cover the model layer (property binding, toolbar propagation, dynamic updates). All platform rendering paths rely on the existing patterns for BackButtonTitle which are already covered by the existing test infrastructure. The author's rationale for not adding device tests is valid and consistent with how BackButtonTitle is tested.


Recommendation

Approve — The 3 blocking findings from the prior review are all fixed. The remaining items are minor:

  • Finding 5 (Windows Tag edge case) is theoretical with low practical impact
  • The new Shell stale-TextOverride finding is very niche
  • Test coverage is reasonable given existing patterns

The CI failures are confirmed pre-existing on net11.0 and unrelated to this PR. All PR-relevant checks pass (builds, unit tests, 18 integration test jobs).

This is a well-implemented accessibility feature that follows existing MAUI patterns consistently across all platforms. Good work by the contributor.


First Review (April 17) — Historical

Three independent reviewers analyzed the original diff. 6 findings were reported.

# Severity Issue
1 🔴 CRITICAL Missing PublicAPI entries for Toolbar.BackButtonAccessibilityLabel + mapper methods
2 🟡 MODERATE Shell iOS: BackBarButtonItem loses visible title when only accessibility label set
3 🟡 MODERATE Cross-platform inconsistency: AutomationId vs AccessibilityLabel priority
4 🟡 MODERATE Test coverage gaps
5 🟢 MINOR Windows Tag-based save/restore edge case
6 🟢 MINOR iOS NavigationRenderer visual side effect

Copy link
Copy Markdown
Contributor

@kubaflo kubaflo left a comment

Choose a reason for hiding this comment

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

Could you please review Shane's comment?

@Vignesh-SF3580
Copy link
Copy Markdown
Contributor Author

Could you please review Shane's comment?

@PureWeen @kubaflo Based on the review comments, I have addressed the valid concerns.

  • Added missing Toolbar.BackButtonAccessibilityLabel get/set entries across all 7 TFMs, included mapper entries for the platform TFMs (net-android, net-tizen, net-windows), and corrected the readonly modifier on BackButtonBehavior.AccessibilityLabelProperty. All entries now follow the same pattern as BackButtonTitle / MapBackButtonTitle in PublicAPI.Shipped.txt.
  • Fixed Shell iOS title fallback by updating ShellPageRendererTracker.UpdateBackButtonTitle(). When the back button title is null (i.e., only AccessibilityLabel is set), it now falls back to the previous page’s title. This prevents the chevron-only display and aligns with the existing NavigationRenderer behavior.
  • Fixed AutomationId / AccessibilityLabel inconsistency by adding accessibility label assignment in the else branch of UpdateLeftToolbarItems(), ensuring AccessibilityLabel is applied even when AutomationId is set on BackButtonBehavior.
  • The PR includes 7 unit tests covering all propagation scenarios — Propagates_To_Toolbar for both NavigationPage and Shell, Propagates_BackButtonBehavior for Shell, and dynamic update tests. Verifying accessibility labels on native back button controls (e.g., Android ContentDescription, iOS UIBarButtonItem.AccessibilityLabel) requires device tests with direct native view access, which is not currently supported for toolbar back button properties. The existing BackButtonTitle feature also does not include device tests for the same reason.
  • Ensured null safety by using null-coalescing (backButtonAccessibilityLabel ?? ""), so AppBarButton.Tag is never null. Android’s ContentDescription setter also safely handles null.
  • UIBarButtonItem.AccessibilityLabel is an accessibility-only property and does not affect the visual appearance of the back button. This aligns with the existing BackButtonTitle behavior.

@sheiksyedm
Copy link
Copy Markdown
Contributor

/azp run maui-pr-uitests , maui-pr-devicetests

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 2 pipeline(s).

@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Apr 22, 2026

⚠️ Merge Conflict Detected — This PR has merge conflicts with its target branch. Please rebase onto the target branch and resolve the conflicts.

1 similar comment
@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Apr 22, 2026

⚠️ Merge Conflict Detected — This PR has merge conflicts with its target branch. Please rebase onto the target branch and resolve the conflicts.

@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Apr 22, 2026

⚠️ Merge Conflict Detected — This PR has merge conflicts with its target branch. Please rebase onto the target branch and resolve the conflicts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-controls-shell Shell Navigation, Routes, Tabs, Flyout area-navigation NavigationPage community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration t/a11y Relates to accessibility t/enhancement ☀️ New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants