Fix AppBar web accessibility: prevent more items announcements
diff --git a/packages/flutter/lib/src/material/app_bar.dart b/packages/flutter/lib/src/material/app_bar.dart index 6d8ac31..019cb42 100644 --- a/packages/flutter/lib/src/material/app_bar.dart +++ b/packages/flutter/lib/src/material/app_bar.dart
@@ -1074,6 +1074,7 @@ TargetPlatform.iOS || TargetPlatform.macOS => null, }, header: true, + explicitChildNodes: !kIsWeb, child: title, ); } @@ -1196,12 +1197,12 @@ children: <Widget>[ Semantics( sortKey: widget.useDefaultSemanticsOrder ? const OrdinalSortKey(1.0) : null, - explicitChildNodes: true, + explicitChildNodes: !kIsWeb, child: widget.flexibleSpace, ), Semantics( sortKey: widget.useDefaultSemanticsOrder ? const OrdinalSortKey(0.0) : null, - explicitChildNodes: true, + explicitChildNodes: !kIsWeb, // Creates a material widget to prevent the flexibleSpace from // obscuring the ink splashes produced by appBar children. child: Material(type: MaterialType.transparency, child: appBar), @@ -1240,7 +1241,10 @@ (theme.useMaterial3 ? theme.colorScheme.surfaceTint : null), shape: widget.shape ?? appBarTheme.shape ?? defaults.shape, animateColor: widget.animateColor, - child: Semantics(explicitChildNodes: true, child: appBar), + child: Semantics( + explicitChildNodes: !kIsWeb, + child: appBar, + ), ), ), );
diff --git a/packages/flutter/test/material/app_bar_test.dart b/packages/flutter/test/material/app_bar_test.dart index 386c7ea..479e0fa 100644 --- a/packages/flutter/test/material/app_bar_test.dart +++ b/packages/flutter/test/material/app_bar_test.dart
@@ -1388,8 +1388,13 @@ SemanticsFlag.isHeader, SemanticsFlag.namesRoute, ], - label: 'Title', - textDirection: TextDirection.ltr, + children: <TestSemantics>[ + TestSemantics( + id: 10, + label: 'Title', + textDirection: TextDirection.ltr, + ), + ], ), ], ), @@ -1474,8 +1479,13 @@ SemanticsFlag.isHeader, SemanticsFlag.namesRoute, ], - label: 'Title', - textDirection: TextDirection.ltr, + children: <TestSemantics>[ + TestSemantics( + id: 8, + label: 'Title', + textDirection: TextDirection.ltr, + ), + ], ), ], ), @@ -3625,4 +3635,32 @@ }, ); }); + + testWidgets('AppBar uses explicitChildNodes: !kIsWeb for web accessibility', ( + WidgetTester tester, + ) async { + // Regression test for https://github.com/flutter/flutter/issues/176332 + // AppBar wraps content with Semantics(explicitChildNodes: !kIsWeb) to prevent + // screen readers on web from announcing "X more items" when navigating. + + final SemanticsTester semantics = SemanticsTester(tester); + + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + appBar: AppBar(leading: const BackButton(), title: const Text('Book Details')), + ), + ), + ); + + // The fix creates a parent-child structure where the title's text is in a + // child node and the parent has the isHeader flag (explicitChildNodes: true). + final SemanticsNode titleNode = tester.getSemantics(find.text('Book Details')); + final SemanticsNode? parent = titleNode.parent; + + expect(parent, isNotNull); + expect(parent!.hasFlag(SemanticsFlag.isHeader), isTrue); + + semantics.dispose(); + }); }