Skip to content

WIP - Improve Scaffold accessibility by defining a logical traversal order for its slots#184730

Draft
Piinks wants to merge 2 commits intoflutter:masterfrom
Piinks:focusFAB
Draft

WIP - Improve Scaffold accessibility by defining a logical traversal order for its slots#184730
Piinks wants to merge 2 commits intoflutter:masterfrom
Piinks:focusFAB

Conversation

@Piinks
Copy link
Copy Markdown
Contributor

@Piinks Piinks commented Apr 7, 2026

Towards #184077

I need to try another solution first though.


Summary
This PR improves the accessibility of the Scaffold widget by explicitly defining the focus and
semantics traversal order for its various slots. This ensures that users of assistive technologies
(keyboard navigation and screen readers) encounter elements in a logical, top-down order,
prioritizing navigation and primary actions before main content.

Related Issue
Fixes #184077

The Problem
Previously, the traversal order in a Scaffold was determined by the build/layout order within its
internal CustomMultiChildLayout. This often resulted in the body being traversed before the
FloatingActionButton (FAB) or BottomNavigationBar. If the body contained a long scrollable list,
users were effectively "trapped" in the content and forced to navigate through every list item
before they could reach global navigation or the primary page action (FAB).

The Solution: "Chrome-before-Content"
This change implements a "Chrome-before-Content" traversal pattern. By prioritizing the AppBar,
BottomNavigationBar, and FloatingActionButton before the body, users can quickly switch context or
perform primary actions without traversing the entire main content area.

The final defined order is:

  1. MaterialBanner (1.0): Topmost urgent notifications.
  2. AppBar (2.0): Page context and top navigation.
  3. BottomNavigationBar (3.0): Global app-level navigation.
  4. FloatingActionButton (4.0): Primary page-level action.
  5. Body (5.0): Main content area.
  6. BottomSheet (6.0): Supplemental content/actions.
  7. SnackBar (7.0): Transient status feedback.
  8. PersistentFooterButtons (8.0): Secondary actions following the body (e.g., a "Submit" button).

Key Navigation Benefits:

  • Forward Navigation (Tab): Users reach global navigation and the primary FAB immediately after
    the AppBar, before entering the body.
  • Backward Navigation (Shift+Tab): Users can Shift-Tab from the start of the body to quickly jump
    back to the primary action or navigation.

Technical Implementation

  • Scaffold: Wrapped the layout area in a FocusTraversalGroup with OrderedTraversalPolicy and a
    Semantics container to enable sorting.
  • _addIfNonNull: Updated this internal helper to automatically apply FocusTraversalOrder
    (NumericFocusOrder) and Semantics.sortKey (OrdinalSortKey) to each slot.
  • SemanticsTester: Added support for tooltip matching in the includesNodeWith matcher, enabling
    cleaner and more robust semantics tests for widgets like IconButton.

Tests
New Tests

  • packages/flutter/test/material/scaffold_navigation_order_test.dart: Explicitly verifies the
    full forward/backward Tab sequence and the correct assignment of semantics sort keys.

Updated Tests
Several existing regression tests were updated to accommodate the new semantics tree structure
(which now includes sorting nodes):

  • selectable_region_test.dart: Updated to use Material instead of Scaffold to preserve its
    original intent of testing unmerged semantics nodes without interference from Scaffold's
    internal containers.
  • search_test.dart: Refactored to use the improved includesNodeWith matcher, making the tests
    more robust and focused on behavior rather than exact tree depth.
  • floating_action_button_test.dart, bottom_navigation_bar_test.dart,
    flexible_space_bar_test.dart, dropdown_menu_test.dart, and navigation_rail_test.dart: Updated
    to match the new semantics nesting while preserving their original verification logic.

Verified that all updated tests and related suites (app_bar_test.dart, banner_test.dart,
snack_bar_test.dart, scaffold_test.dart) pass.

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

@github-actions github-actions Bot added framework flutter/packages/flutter repository. See also f: labels. f: material design flutter/packages/flutter/material repository. a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) labels Apr 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Google3 Bug]: Illogical keyboard navigation order for FloatingActionButton when placed visually before a long scrollable list

1 participant