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
Prev Previous commit
Next Next commit
Fix PR comments (41435)
  • Loading branch information
victorgalo committed Sep 19, 2023
commit 36c5fd6211b899e17fb5d0e4fe1a448ed345b743
5 changes: 5 additions & 0 deletions lib/ui/semantics.dart
Original file line number Diff line number Diff line change
Expand Up @@ -786,6 +786,11 @@ abstract class SemanticsUpdateBuilder {
/// z-direction starting at `elevation`. Basically, in the z-direction the
/// node starts at `elevation` above the parent and ends at `elevation` +
/// `thickness` above the parent.
///
/// The `headingLevel` describes that this node is a heading, additionally
/// indicates the hierarchy level this node represents as a heading. A value
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: I'd replace "additionally indicates" with just "and"

/// of -1 indicates that this node is not a heading. A value of 1 or greater
/// indicates that this node is a heading at the specified level.
Copy link
Contributor

Choose a reason for hiding this comment

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

Should the parameter have an upper bound, and perhaps an assert that ensures that the upper bound is satisfied? It would also be useful to link to these pages:

Another important thing to document is how it applies across platforms (seems like it's a noop outside web).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree, it should have an upper bound, not sure if I put the assert in the correct place, can you please check it out?. I also added more details in the doc.

void updateNode({
required int id,
required int flags,
Expand Down
2 changes: 1 addition & 1 deletion lib/web_ui/lib/semantics.dart
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ class SemanticsUpdateBuilder {
required Int32List childrenInTraversalOrder,
required Int32List childrenInHitTestOrder,
required Int32List additionalActions,
required int headingLevel,
int? headingLevel,
}) {
if (transform.length != 16) {
throw ArgumentError('transform argument must have 16 entries.');
Expand Down
21 changes: 16 additions & 5 deletions lib/web_ui/lib/src/engine/semantics/heading.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,26 @@ import 'semantics.dart';
/// level (h1 ... h6).
class Heading extends PrimaryRoleManager {
Heading(SemanticsObject semanticsObject)
: super.withBasics(PrimaryRole.heading, semanticsObject);
: super.withBasics(PrimaryRole.heading, semanticsObject) {
addHeadingRole();
}

@override
void update() {
super.update();
Copy link
Contributor

Choose a reason for hiding this comment

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

We can return early if the heading level field is not dirty.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I added it.


if (semanticsObject.headingLevel != -1) {
semanticsObject.setAriaRole('heading');
semanticsObject.element.setAttribute('aria-level', semanticsObject.headingLevel);
}
if (semanticsObject.headingLevel != -1) {
addHeadingLevel(semanticsObject.headingLevel);
} else {
addHeadingLevel(1);
}
}

void addHeadingRole() {
semanticsObject.setAriaRole('heading');
}

void addHeadingLevel(int headingLevel) {
semanticsObject.element.setAttribute('aria-level', headingLevel);
}
}
8 changes: 4 additions & 4 deletions lib/web_ui/lib/src/engine/semantics/semantics.dart
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ class SemanticsNodeUpdate {
required this.childrenInTraversalOrder,
required this.childrenInHitTestOrder,
required this.additionalActions,
required this.headingLevel,
this.headingLevel,
});

/// See [ui.SemanticsUpdateBuilder.updateNode].
Expand Down Expand Up @@ -330,7 +330,7 @@ class SemanticsNodeUpdate {
final double thickness;

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

/// Identifies [PrimaryRoleManager] implementations.
Expand Down Expand Up @@ -1097,7 +1097,7 @@ class SemanticsObject {
/// Whether this object represents an editable text field.
bool get isTextField => hasFlag(ui.SemanticsFlag.isTextField);

/// Whether this object represents a heading element
/// Whether this object represents a heading element.
bool get isHeading => headingLevel != -1;

/// Whether this object needs screen readers attention right away.
Expand Down Expand Up @@ -1528,8 +1528,8 @@ class SemanticsObject {
PrimaryRole.dialog => Dialog(this),
PrimaryRole.image => ImageRoleManager(this),
PrimaryRole.platformView => PlatformViewRoleManager(this),
PrimaryRole.generic => GenericRole(this),
PrimaryRole.heading => Heading(this),
PrimaryRole.generic => GenericRole(this),
};
}

Expand Down
48 changes: 34 additions & 14 deletions lib/web_ui/test/engine/semantics/semantics_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -670,25 +670,45 @@ void _testHeader() {
semantics().semanticsEnabled = false;
});

test('renders aria-level tag for headers with heading level', () {
test('renders aria-level tag for headings 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),
);
// State 1: render element with an initial headingLevel.
{
final ui.SemanticsUpdateBuilder builder = ui.SemanticsUpdateBuilder();
updateNode(
builder,
headingLevel: 2,
label: 'Heading of the page',
transform: Matrix4.identity().toFloat64(),
rect: const ui.Rect.fromLTRB(0, 0, 100, 50),
);

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

// State 2: when the new state "clears" the headingLevel, a default value
// of 1 is assigned, as the aria-level is a required attribute for the
// heading role.
{
final ui.SemanticsUpdateBuilder builder = ui.SemanticsUpdateBuilder();
updateNode(
builder,
label: 'Heading of the page',
transform: Matrix4.identity().toFloat64(),
rect: const ui.Rect.fromLTRB(0, 0, 100, 50),
);

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

semantics().semanticsEnabled = false;
});
Expand Down