Skip to content

SliverSemantics #167300

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open

Conversation

Renzo-Olivares
Copy link
Contributor

@Renzo-Olivares Renzo-Olivares commented Apr 16, 2025

Fixes #166785

Pre-launch Checklist

  • I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
  • I read the [Tree Hygiene] wiki page, which explains my responsibilities.
  • I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement].
  • I signed the [CLA].
  • I listed at least one issue that this PR fixes in the description above.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or this PR is [test-exempt].
  • I followed the [breaking change policy] and added [Data Driven Fixes] where supported.
  • All existing and new tests are passing.

@github-actions github-actions bot added framework flutter/packages/flutter repository. See also f: labels. f: scrolling Viewports, list views, slivers, etc. labels Apr 16, 2025
@github-actions github-actions bot added a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) d: api docs Issues with https://api.flutter.dev/ d: examples Sample code and demos labels May 8, 2025
@Renzo-Olivares Renzo-Olivares force-pushed the sliver-semantics branch 4 times, most recently from 02769d5 to 7202c32 Compare May 10, 2025 00:32
@Renzo-Olivares Renzo-Olivares force-pushed the sliver-semantics branch 3 times, most recently from 432ea93 to 88b0c8a Compare June 4, 2025 20:25
@Renzo-Olivares Renzo-Olivares changed the title [WIP] SliverSemantics SliverSemantics Jun 6, 2025
@Renzo-Olivares Renzo-Olivares marked this pull request as ready for review June 6, 2025 17:45
@Renzo-Olivares Renzo-Olivares requested a review from chunhtai June 6, 2025 17:47
});

testWidgets(
'does not merge conflicting actions even if one of them is blocked with Semantics widget',
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'm not too sure if the expected explicitChildNodes: true is the way to solve the issues with this test.

For context this test comes from:

testWidgets('does not merge conflicting actions even if one of them is blocked', (
WidgetTester tester,
) async {
final UniqueKey key = UniqueKey();
await tester.pumpWidget(
MaterialApp(
home: Semantics(
key: key,
container: true,
child: Column(
children: <Widget>[
Semantics(
blockUserActions: true,
label: 'label1',
onTap: () {},
child: const SizedBox(width: 10, height: 10),
),
Semantics(
label: 'label2',
onTap: () {},
child: const SizedBox(width: 10, height: 10),
),
],
),
),
),
);
final SemanticsNode node = tester.getSemantics(find.byKey(key));
expect(
node,
matchesSemantics(
children: <Matcher>[containsSemantics(label: 'label1'), containsSemantics(label: 'label2')],
),
);
});

In the test above the nodes under Column are not merged, but in this sliver test, the nodes under SliverList are merged, unless I use explicitChildNodes true in the SliverSemantics widget above the SliverList. I debugged and found that the cause for this is because SliverList adds semantics indexes with IndexedSemantics. If we do addSemanticIndexes: false, then this test also passes.

In the original test from semantics_test.dart if I add an IndexedSemantics around each child of the Column then we run into the same issue where the nodes under the Column are merged.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Created an issue #170485 and updated test to use SliverToBoxAdapter -> Column for now.

@Renzo-Olivares
Copy link
Contributor Author

Google testing is failing because there already exists a SliverSemantics, I think I will try to migrate those uses to use the frameworks SliverSemantics.

Copy link
Contributor

@chunhtai chunhtai left a comment

Choose a reason for hiding this comment

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

overall approach LGTM, just some suggestions to make code a bit cleaner

/// for their subtree.
mixin SemanticsAnnotationsMixin on RenderObject {
/// Initializes the semantics annotations for this mixin.
void initSemanticsAnnotations({
Copy link
Contributor

Choose a reason for hiding this comment

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

If this is not meant to be developer facing API. I will turn all the parameter to be required just so that one day we add parameter to the list, we won't forget to update all the internal reference

/// A sliver that annotates its subtree with a description of the meaning of
/// the slivers.
///
/// Used by assistive technologies, search engines, and other semantic analysis
Copy link
Contributor

Choose a reason for hiding this comment

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

can this use template to deduplicate the doc between this and Semantics widget

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 think so, but do you think both should point to the same youtube video since the video talks about the Semantics widget. They're essentially used the same way, but it may be confusing to some? What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

yes, I think this is confusing. I think we should exclude the video out of sliver version of doc

///
/// See also:
///
/// * [SemanticsProperties], which contains a complete documentation for each
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe add a link to Semantics widget

Copy link
Contributor

Choose a reason for hiding this comment

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

same for the breadcumb in Semantics widget.

/// to create semantic boundaries that are either writable or not for children.
final bool explicitChildNodes;

/// Whether to replace all child semantics with this node.
Copy link
Contributor

Choose a reason for hiding this comment

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

most of this can be doc string


/// Contains properties used by assistive technologies to make the application
/// more accessible.
final SemanticsProperties properties;
Copy link
Contributor

@chunhtai chunhtai Jun 6, 2025

Choose a reason for hiding this comment

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

can any of these and the Semantics counter part to be factored out into a mixin. Asking this because adding a flag/property in semantics is already cumbersome, would appreciate we don't add another place that needs to be updated...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point! I'll look into ways we can do this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What do you think about this approach? f22a87a (#167300)

A base class used by both Semantics and SliverSemantics called SemanticsBase where SemanticsBase has its own constructor with every field marked as required. This enforces its subclasses to add that field to their constructor whenever a new one is added to SemanticsBase.

In this world, when we add a new field to SemanticsBase and mark it required, an analyzer error will appear pointing us to add the same field to its subclasses Semantics and SliverSemantics.

@Renzo-Olivares Renzo-Olivares requested a review from chunhtai June 11, 2025 16:26
Copy link
Contributor

@chunhtai chunhtai left a comment

Choose a reason for hiding this comment

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

LGTM, would be good if we can make it private, but not blocking the pr merge

/// be enabled using [WidgetsApp.showSemanticsDebugger],
/// [MaterialApp.showSemanticsDebugger], or [CupertinoApp.showSemanticsDebugger].
/// {@endtemplate}
sealed class SemanticsBase extends SingleChildRenderObjectWidget {
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for refactor this out it is a lot less duplicated code now, I wonder if this can be private? not sure whether the api doc still work if we make it private though.

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) d: api docs Issues with https://api.flutter.dev/ d: examples Sample code and demos f: scrolling Viewports, list views, slivers, etc. framework flutter/packages/flutter repository. See also f: labels.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Slivers should have Sliver equivalent of the Semantics widget
2 participants