Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
a341b26
Add support for setting the heading level for web semantics (#97894)
victorgalo Apr 23, 2023
eff0206
Add support for setting the heading level for web semantics (#97894)
victorgalo Apr 24, 2023
7f8ef2c
Merge branch 'main' into add-semantics-heading-level
victorgalo Apr 24, 2023
9029d63
Add support for setting the heading level for web semantics (#97894)
victorgalo Apr 24, 2023
260d4bd
Add support for setting the heading level for web semantics (#97894)
victorgalo Apr 30, 2023
baea4c1
Merge branch 'main' into add-semantics-heading-level
victorgalo Apr 30, 2023
bf0fe7f
Merge branch 'main' into add-semantics-heading-level
victorgalo Sep 9, 2023
b773f81
Merge branch 'main' into add-semantics-heading-level
victorgalo Sep 9, 2023
90de9fc
Remove trailing spaces
victorgalo Sep 9, 2023
c9ac350
Merge branch 'main' into add-semantics-heading-level
victorgalo Sep 9, 2023
c8ccd31
Add export for new Heading role
victorgalo Sep 9, 2023
0241f07
Fix references for new Heading role
victorgalo Sep 10, 2023
6298a5f
Remove unused import
victorgalo Sep 10, 2023
36c5fd6
Fix PR comments (41435)
victorgalo Sep 19, 2023
30153e0
Remove trailing whitespace
victorgalo Sep 19, 2023
5460388
Add support for setting the heading level for web semantics (#97894)
victorgalo Sep 20, 2023
a526070
Add support for setting the heading level for web semantics (#97894)
victorgalo Sep 20, 2023
dceef3c
Add support for setting the heading level for web semantics (#97894)
victorgalo Sep 21, 2023
3a6e45d
Add support for setting the heading level for web semantics (#97894)
victorgalo Sep 24, 2023
b9bfb88
Add support for setting the heading level for web semantics (#97894)
victorgalo Sep 24, 2023
664c1e4
Change headingLevel to not be nullable
victorgalo Nov 12, 2023
e6a8c6a
Merge branch 'main' into add-semantics-heading-level
victorgalo Nov 12, 2023
470f67f
Change headingLevel to be non nullable
victorgalo Nov 12, 2023
a56c398
Change headingLevel to be non nullable
victorgalo Nov 12, 2023
b31bd9f
Change headingLevel to be non nullable
victorgalo Nov 12, 2023
8305e4b
Change headingLevel to be non nullable
victorgalo Nov 12, 2023
d860f21
Make headingLevel temporarily optional until framework part is uploaded
victorgalo Nov 13, 2023
a16a8f7
Merge branch 'main' into add-semantics-heading-level
victorgalo Nov 13, 2023
70efe89
Merge branch 'main' into add-semantics-heading-level
victorgalo Dec 2, 2023
ddeaefc
Change headingLevel to be non nullable
victorgalo Dec 4, 2023
bcd3205
remove trailing whitespaces
victorgalo Dec 4, 2023
9d25b32
Merge branch 'main' into add-semantics-heading-level
victorgalo Dec 4, 2023
268e31c
Change default value for headingLevel to 0
victorgalo Jan 19, 2024
a7bb630
Merge branch 'main' into add-semantics-heading-level
victorgalo Jan 19, 2024
0f72806
Change default value for headingLevel to 0
victorgalo Jan 21, 2024
79e4728
Add focusAsRouteDefault implementation to Heading primary role
victorgalo Jan 21, 2024
4b69d9f
Change default value for headingLevel to 0
victorgalo Jan 21, 2024
c83039b
Merge branch 'main' into add-semantics-heading-level
victorgalo Feb 11, 2024
b351c1e
Merge branch 'main' into add-semantics-heading-level
victorgalo Mar 13, 2024
5705912
Fix unit test for semantics heading level attribute
victorgalo Mar 13, 2024
89ef536
Merge branch 'main' into add-semantics-heading-level
victorgalo Mar 14, 2024
e60c0a7
Change constructor for Heading role
victorgalo Mar 14, 2024
bb787e0
Fix unit test for semantics heading level
victorgalo Mar 15, 2024
7199da1
Merge branch 'main' into add-semantics-heading-level
victorgalo Mar 15, 2024
76b65f6
Merge branch 'main' into add-semantics-heading-level
victorgalo Mar 15, 2024
ee38434
Merge branch 'main' into add-semantics-heading-level
victorgalo Mar 18, 2024
41f77aa
Merge branch 'main' into add-semantics-heading-level
victorgalo Mar 29, 2024
e38e3f3
Fix PR comments (41435)
victorgalo Sep 19, 2023
1e570fb
Change headingLevel to not be nullable
victorgalo Nov 12, 2023
ac1ec5e
Change default value for headingLevel to 0
victorgalo Jan 19, 2024
0b9efa6
Remove duplicated definition after fixing rebase conflicts
victorgalo Mar 29, 2024
4a54812
Merge branch 'main' into add-semantics-heading-level
victorgalo May 10, 2024
6d8d511
Remove unnecessary check for Heading primary role
victorgalo May 10, 2024
2586dbc
Merge branch 'main' into add-semantics-heading-level
victorgalo May 12, 2024
fc0a3a5
Merge branch 'main' into add-semantics-heading-level
chunhtai May 16, 2024
ca2d289
Remove duplicated case in switch statement
victorgalo May 17, 2024
5e05f24
Merge branch 'main' into add-semantics-heading-level
victorgalo May 17, 2024
9231840
Merge branch 'main' into add-semantics-heading-level
victorgalo May 17, 2024
c52b545
Merge branch 'main' into add-semantics-heading-level
victorgalo May 17, 2024
33a246c
Merge branch 'main' into add-semantics-heading-level
victorgalo May 18, 2024
1b0e241
Merge branch 'main' into add-semantics-heading-level
chunhtai May 29, 2024
e918e20
Merge branch 'main' into add-semantics-heading-level
victorgalo Jun 1, 2024
4383464
Change semantics headingLevel attribute to be not required until fram…
victorgalo Jun 1, 2024
5186055
fix lint
chunhtai Jun 4, 2024
af5e70a
Merge branch 'main' into add-semantics-heading-level
chunhtai Jun 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add support for setting the heading level for web semantics (#97894)
  • Loading branch information
victorgalo committed Apr 23, 2023
commit a341b2693b6e23241e8a116523bbfc16924dc3a3
3 changes: 2 additions & 1 deletion lib/ui/fixtures/ui_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@ void sendSemanticsUpdate() {
transform: transform,
childrenInTraversalOrder: childrenInTraversalOrder,
childrenInHitTestOrder: childrenInHitTestOrder,
additionalActions: additionalActions);
additionalActions: additionalActions,
headingLevel: -1);
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: consider using a trailing comma at the end of long argument lists.

_semanticsUpdate(builder.build());
}

Expand Down
8 changes: 6 additions & 2 deletions lib/ui/semantics.dart
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,7 @@ class SemanticsUpdateBuilder extends NativeFieldWrapperClass1 {
required Int32List childrenInTraversalOrder,
required Int32List childrenInHitTestOrder,
required Int32List additionalActions,
required int headingLevel,
Copy link
Contributor

Choose a reason for hiding this comment

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

same

}) {
assert(_matrix4IsValid(transform));
_updateNode(
Expand Down Expand Up @@ -836,6 +837,7 @@ class SemanticsUpdateBuilder extends NativeFieldWrapperClass1 {
childrenInTraversalOrder,
childrenInHitTestOrder,
additionalActions,
headingLevel,
);
}
@Native<
Expand Down Expand Up @@ -875,7 +877,8 @@ class SemanticsUpdateBuilder extends NativeFieldWrapperClass1 {
Handle,
Handle,
Handle,
Handle)>(symbol: 'SemanticsUpdateBuilder::updateNode')
Handle,
Int32)>(symbol: 'SemanticsUpdateBuilder::updateNode')
external void _updateNode(
int id,
int flags,
Expand Down Expand Up @@ -911,7 +914,8 @@ class SemanticsUpdateBuilder extends NativeFieldWrapperClass1 {
Float64List transform,
Int32List childrenInTraversalOrder,
Int32List childrenInHitTestOrder,
Int32List additionalActions);
Int32List additionalAction,
int headingLevel);

/// Update the custom semantics action associated with the given `id`.
///
Expand Down
1 change: 1 addition & 0 deletions lib/ui/semantics/semantics_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ struct SemanticsNode {
std::vector<int32_t> childrenInTraversalOrder;
std::vector<int32_t> childrenInHitTestOrder;
std::vector<int32_t> customAccessibilityActions;
int32_t headingLevel = -1;
};

// Contains semantic nodes that need to be updated.
Expand Down
5 changes: 4 additions & 1 deletion lib/ui/semantics/semantics_update_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ void SemanticsUpdateBuilder::updateNode(
const tonic::Float64List& transform,
const tonic::Int32List& childrenInTraversalOrder,
const tonic::Int32List& childrenInHitTestOrder,
const tonic::Int32List& localContextActions) {
const tonic::Int32List& localContextActions,
int headingLevel) {
FML_CHECK(scrollChildren == 0 ||
(scrollChildren > 0 && childrenInHitTestOrder.data()))
<< "Semantics update contained scrollChildren but did not have "
Expand Down Expand Up @@ -116,6 +117,8 @@ void SemanticsUpdateBuilder::updateNode(
localContextActions.data(),
localContextActions.data() + localContextActions.num_elements());
nodes_[id] = node;

node.headingLevel = headingLevel;
}

void SemanticsUpdateBuilder::updateCustomAction(int id,
Expand Down
3 changes: 2 additions & 1 deletion lib/ui/semantics/semantics_update_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ class SemanticsUpdateBuilder
const tonic::Float64List& transform,
const tonic::Int32List& childrenInTraversalOrder,
const tonic::Int32List& childrenInHitTestOrder,
const tonic::Int32List& customAccessibilityActions);
const tonic::Int32List& customAccessibilityActions,
int headingLevel);

void updateCustomAction(int id,
std::string label,
Expand Down
2 changes: 2 additions & 0 deletions lib/web_ui/lib/semantics.dart
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ class SemanticsUpdateBuilder {
required Int32List childrenInTraversalOrder,
required Int32List childrenInHitTestOrder,
required Int32List additionalActions,
required int headingLevel,
Copy link
Contributor

Choose a reason for hiding this comment

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

same here

}) {
if (transform.length != 16) {
throw ArgumentError('transform argument must have 16 entries.');
Expand Down Expand Up @@ -313,6 +314,7 @@ class SemanticsUpdateBuilder {
childrenInHitTestOrder: childrenInHitTestOrder,
additionalActions: additionalActions,
platformViewId: platformViewId,
headingLevel: headingLevel,
));
}

Expand Down
4 changes: 4 additions & 0 deletions lib/web_ui/lib/src/engine/semantics/label_and_value.dart
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ class LabelAndValue extends RoleManager {
semanticsObject.setAriaRole('group', true);
} else if (semanticsObject.hasFlag(ui.SemanticsFlag.isHeader)) {
semanticsObject.setAriaRole('heading', true);
if (semanticsObject.headingLevel != -1) {
semanticsObject.setAriaLevel(semanticsObject.headingLevel);
}
} else {
semanticsObject.setAriaRole('text', true);
}
Expand All @@ -98,6 +101,7 @@ class LabelAndValue extends RoleManager {
void _cleanUpDom() {
semanticsObject.element.removeAttribute('aria-label');
semanticsObject.clearAriaRole();
semanticsObject.clearAriaLevel();
}

@override
Expand Down
27 changes: 27 additions & 0 deletions lib/web_ui/lib/src/engine/semantics/semantics.dart
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ class SemanticsNodeUpdate {
required this.childrenInTraversalOrder,
required this.childrenInHitTestOrder,
required this.additionalActions,
required this.headingLevel,
});

/// See [ui.SemanticsUpdateBuilder.updateNode].
Expand Down Expand Up @@ -321,6 +322,9 @@ class SemanticsNodeUpdate {

/// See [ui.SemanticsUpdateBuilder.updateNode].
final double thickness;

/// See [ui.SemanticsUpdateBuilder.updateNode].
final int headingLevel;
}

/// Identifies one of the roles a [SemanticsObject] plays.
Expand Down Expand Up @@ -758,6 +762,15 @@ class SemanticsObject {
_dirtyFields |= _platformViewIdIndex;
}

/// See [ui.SemanticsUpdateBuilder.updateNode].
int get headingLevel => _headingLevel;
int _headingLevel = -1;

static const int _headingLevelIndex = 1 << 24;
void _markHeadingLevelDirty() {
_dirtyFields |= _headingLevelIndex;
}

/// A unique permanent identifier of the semantics node in the tree.
final int id;

Expand Down Expand Up @@ -978,6 +991,11 @@ class SemanticsObject {
_markTooltipDirty();
}

if (_headingLevel != update.headingLevel) {
_headingLevel = update.headingLevel;
_markHeadingLevelDirty();
}

if (_textDirection != update.textDirection) {
_textDirection = update.textDirection;
_markTextDirectionDirty();
Expand Down Expand Up @@ -1224,6 +1242,15 @@ class SemanticsObject {
element.removeAttribute('role');
}

void setAriaLevel(int ariaLevel) {
element.setAttribute('aria-level', ariaLevel);
}

/// Removes the `aria-level` HTML attribue, if any.
void clearAriaLevel() {
element.removeAttribute('aria-level');
}

/// Role managers.
///
/// The [_roleManagers] map needs to have a stable order for easier debugging
Expand Down
25 changes: 25 additions & 0 deletions lib/web_ui/test/engine/semantics/semantics_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,29 @@ void _testHeader() {
semantics().updateSemantics(builder.build());
expectSemanticsTree('''
<sem role="group" aria-label="Header of the page" style="$rootSemanticStyle"><sem-c><sem></sem></sem-c></sem>
''');

semantics().semanticsEnabled = false;
});

test('renders aria-level tag for headers with heading level', () {
semantics()
..debugOverrideTimestampFunction(() => _testTime)
..semanticsEnabled = true;

final ui.SemanticsUpdateBuilder builder = ui.SemanticsUpdateBuilder();
updateNode(
builder,
flags: 0 | ui.SemanticsFlag.isHeader.index,
headingLevel: 1,
label: 'Header of the page',
transform: Matrix4.identity().toFloat64(),
rect: const ui.Rect.fromLTRB(0, 0, 100, 50),
);
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's also test that we can update it and clear aria-level when it's gone (assuming having the heading role without aria-level is a meaningful state).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hey @yjbanov, I'd say i's not a meaningful state, aria-level is required for "heading" role. Do you think I still should add it?.

Copy link
Contributor

Choose a reason for hiding this comment

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

Nope, if it's not an expected state, we don't need to test it.


semantics().updateSemantics(builder.build());
expectSemanticsTree('''
<sem role="heading" aria-label="Header of the page" aria-level="1" style="$rootSemanticStyle"></sem>
''');

semantics().semanticsEnabled = false;
Expand Down Expand Up @@ -2125,6 +2148,7 @@ void updateNode(
Int32List? childrenInTraversalOrder,
Int32List? childrenInHitTestOrder,
Int32List? additionalActions,
int headingLevel = -1,
}) {
transform ??= Float64List.fromList(Matrix4.identity().storage);
childrenInTraversalOrder ??= Int32List(0);
Expand Down Expand Up @@ -2163,6 +2187,7 @@ void updateNode(
childrenInTraversalOrder: childrenInTraversalOrder,
childrenInHitTestOrder: childrenInHitTestOrder,
additionalActions: additionalActions,
headingLevel: headingLevel,
);
}

Expand Down
2 changes: 2 additions & 0 deletions lib/web_ui/test/engine/semantics/semantics_tester.dart
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ class SemanticsTester {
Float64List? transform,
Int32List? additionalActions,
List<SemanticsNodeUpdate>? children,
int? headingLevel,
}) {
// Flags
if (hasCheckedState ?? false) {
Expand Down Expand Up @@ -325,6 +326,7 @@ class SemanticsTester {
childrenInTraversalOrder: childIds,
childrenInHitTestOrder: childIds,
additionalActions: additionalActions ?? Int32List(0),
headingLevel: headingLevel ?? -1,
);
_nodeUpdates.add(update);
return update;
Expand Down
4 changes: 4 additions & 0 deletions shell/platform/embedder/fixtures/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ void a11y_main() async {
decreasedValueAttributes: <StringAttribute>[],
tooltip: 'tooltip',
additionalActions: Int32List(0),
headingLevel: -1
)
..updateNode(
id: 84,
Expand Down Expand Up @@ -207,6 +208,7 @@ void a11y_main() async {
additionalActions: Int32List(0),
childrenInHitTestOrder: Int32List(0),
childrenInTraversalOrder: Int32List(0),
headingLevel: -1
)
..updateNode(
id: 96,
Expand Down Expand Up @@ -240,6 +242,7 @@ void a11y_main() async {
decreasedValueAttributes: <StringAttribute>[],
tooltip: 'tooltip',
additionalActions: Int32List(0),
headingLevel: -1
)
..updateNode(
id: 128,
Expand Down Expand Up @@ -273,6 +276,7 @@ void a11y_main() async {
tooltip: 'tooltip',
childrenInHitTestOrder: Int32List(0),
childrenInTraversalOrder: Int32List(0),
headingLevel: -1
)
..updateCustomAction(
id: 21,
Expand Down