Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 436b4f1

Browse files
committed
Revert "[web:a11y] make header a proper <header> (#55747)"
This reverts commit 2fbb0c1.
1 parent 5eb21d2 commit 436b4f1

File tree

6 files changed

+20
-77
lines changed

6 files changed

+20
-77
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43886,7 +43886,6 @@ ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/semantics.dart + ../../../flu
4388643886
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/semantics/accessibility.dart + ../../../flutter/LICENSE
4388743887
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/semantics/checkable.dart + ../../../flutter/LICENSE
4388843888
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/semantics/focusable.dart + ../../../flutter/LICENSE
43889-
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/semantics/header.dart + ../../../flutter/LICENSE
4389043889
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/semantics/heading.dart + ../../../flutter/LICENSE
4389143890
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/semantics/image.dart + ../../../flutter/LICENSE
4389243891
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/semantics/incrementable.dart + ../../../flutter/LICENSE
@@ -46765,7 +46764,6 @@ FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics.dart
4676546764
FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics/accessibility.dart
4676646765
FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics/checkable.dart
4676746766
FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics/focusable.dart
46768-
FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics/header.dart
4676946767
FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics/heading.dart
4677046768
FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics/image.dart
4677146769
FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics/incrementable.dart

lib/web_ui/lib/src/engine.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,6 @@ export 'engine/scene_view.dart';
147147
export 'engine/semantics/accessibility.dart';
148148
export 'engine/semantics/checkable.dart';
149149
export 'engine/semantics/focusable.dart';
150-
export 'engine/semantics/header.dart';
151150
export 'engine/semantics/heading.dart';
152151
export 'engine/semantics/image.dart';
153152
export 'engine/semantics/incrementable.dart';

lib/web_ui/lib/src/engine/semantics.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
export 'semantics/accessibility.dart';
66
export 'semantics/checkable.dart';
77
export 'semantics/focusable.dart';
8-
export 'semantics/header.dart';
98
export 'semantics/heading.dart';
109
export 'semantics/image.dart';
1110
export 'semantics/incrementable.dart';

lib/web_ui/lib/src/engine/semantics/header.dart

Lines changed: 0 additions & 44 deletions
This file was deleted.

lib/web_ui/lib/src/engine/semantics/semantics.dart

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import '../window.dart';
2121
import 'accessibility.dart';
2222
import 'checkable.dart';
2323
import 'focusable.dart';
24-
import 'header.dart';
2524
import 'heading.dart';
2625
import 'image.dart';
2726
import 'incrementable.dart';
@@ -397,17 +396,14 @@ enum SemanticRoleKind {
397396
/// The node's role is to host a platform view.
398397
platformView,
399398

400-
/// Contains a link.
401-
link,
402-
403-
/// Denotes a header.
404-
header,
405-
406399
/// A role used when a more specific role cannot be assigend to
407400
/// a [SemanticsObject].
408401
///
409402
/// Provides a label or a value.
410403
generic,
404+
405+
/// Contains a link.
406+
link,
411407
}
412408

413409
/// Responsible for setting the `role` ARIA attribute, for attaching
@@ -681,18 +677,23 @@ final class GenericRole extends SemanticRole {
681677
return;
682678
}
683679

684-
// Assign one of two roles to the element: group or text.
680+
// Assign one of three roles to the element: group, heading, text.
685681
//
686682
// - "group" is used when the node has children, irrespective of whether the
687683
// node is marked as a header or not. This is because marking a group
688684
// as a "heading" will prevent the AT from reaching its children.
685+
// - "heading" is used when the framework explicitly marks the node as a
686+
// heading and the node does not have children.
689687
// - If a node has a label and no children, assume is a paragraph of text.
690688
// In HTML text has no ARIA role. It's just a DOM node with text inside
691689
// it. Previously, role="text" was used, but it was only supported by
692690
// Safari, and it was removed starting Safari 17.
693691
if (semanticsObject.hasChildren) {
694692
labelAndValue!.preferredRepresentation = LabelRepresentation.ariaLabel;
695693
setAriaRole('group');
694+
} else if (semanticsObject.hasFlag(ui.SemanticsFlag.isHeader)) {
695+
labelAndValue!.preferredRepresentation = LabelRepresentation.domText;
696+
setAriaRole('heading');
696697
} else {
697698
labelAndValue!.preferredRepresentation = LabelRepresentation.sizedSpan;
698699
removeAttribute('role');
@@ -1260,24 +1261,11 @@ class SemanticsObject {
12601261
bool get isTextField => hasFlag(ui.SemanticsFlag.isTextField);
12611262

12621263
/// Whether this object represents a heading element.
1263-
///
1264-
/// Typically, a heading is a prominent piece of text that describes what the
1265-
/// rest of the screen or page is about.
1266-
///
1267-
/// Not to be confused with [isHeader].
12681264
bool get isHeading => headingLevel != 0;
12691265

1270-
/// Whether this object represents an interactive link.
1266+
/// Whether this object represents an editable text field.
12711267
bool get isLink => hasFlag(ui.SemanticsFlag.isLink);
12721268

1273-
/// Whether this object represents a header.
1274-
///
1275-
/// A header is a group of widgets that introduce the content of the screen
1276-
/// or a page.
1277-
///
1278-
/// Not to be confused with [isHeading].
1279-
bool get isHeader => hasFlag(ui.SemanticsFlag.isHeader);
1280-
12811269
/// Whether this object needs screen readers attention right away.
12821270
bool get isLiveRegion =>
12831271
hasFlag(ui.SemanticsFlag.isLiveRegion) &&
@@ -1691,8 +1679,6 @@ class SemanticsObject {
16911679
return SemanticRoleKind.route;
16921680
} else if (isLink) {
16931681
return SemanticRoleKind.link;
1694-
} else if (isHeader) {
1695-
return SemanticRoleKind.header;
16961682
} else {
16971683
return SemanticRoleKind.generic;
16981684
}
@@ -1710,7 +1696,6 @@ class SemanticsObject {
17101696
SemanticRoleKind.platformView => SemanticPlatformView(this),
17111697
SemanticRoleKind.link => SemanticLink(this),
17121698
SemanticRoleKind.heading => SemanticHeading(this),
1713-
SemanticRoleKind.header => SemanticHeader(this),
17141699
SemanticRoleKind.generic => GenericRole(this),
17151700
};
17161701
}

lib/web_ui/test/engine/semantics/semantics_test.dart

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,7 @@ class MockSemanticsEnabler implements SemanticsEnabler {
736736
}
737737

738738
void _testHeader() {
739-
test('renders a header with a label and uses a sized span for label', () {
739+
test('renders heading role for headers', () {
740740
semantics()
741741
..debugOverrideTimestampFunction(() => _testTime)
742742
..semanticsEnabled = true;
@@ -752,13 +752,19 @@ void _testHeader() {
752752

753753
owner().updateSemantics(builder.build());
754754
expectSemanticsTree(owner(), '''
755-
<header><span>Header of the page</span></header>
755+
<sem role="heading">Header of the page</sem>
756756
''');
757757

758758
semantics().semanticsEnabled = false;
759759
});
760760

761-
test('renders a header with children and uses aria-label', () {
761+
// When a header has child elements, role="heading" prevents AT from reaching
762+
// child elements. To fix that role="group" is used, even though that causes
763+
// the heading to not be announced as a heading. If the app really needs the
764+
// heading to be announced as a heading, the developer can restructure the UI
765+
// such that the heading is not a parent node, but a side-note, e.g. preceding
766+
// the child list.
767+
test('uses group role for headers when children are present', () {
762768
semantics()
763769
..debugOverrideTimestampFunction(() => _testTime)
764770
..semanticsEnabled = true;
@@ -782,7 +788,7 @@ void _testHeader() {
782788

783789
owner().updateSemantics(builder.build());
784790
expectSemanticsTree(owner(), '''
785-
<header aria-label="Header of the page"><sem-c><sem></sem></sem-c></header>
791+
<sem role="group" aria-label="Header of the page"><sem-c><sem></sem></sem-c></sem>
786792
''');
787793

788794
semantics().semanticsEnabled = false;

0 commit comments

Comments
 (0)