-
Notifications
You must be signed in to change notification settings - Fork 3.4k
[url_launcher] fix: Link widget Tab traversal #9815
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
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request aims to fix a TAB traversal issue on the web for the Link widget by adding excludeSemantics: true
to the wrapping Semantics
widget. This prevents the child widget's semantics from conflicting and creating extra focusable DOM nodes. A new integration test is added to verify this behavior.
My review focuses on the new test case. I've found a bug where SemanticsHandle.dispose()
is called twice, and I've also questioned a skipped assertion that seems critical for verifying the fix. I've provided a code suggestion to address both points.
packages/url_launcher/url_launcher_web/example/integration_test/link_widget_test.dart
Outdated
Show resolved
Hide resolved
Thanks for tackling this issue! Unfortunately, @chunhtai do you have suggestions on how to make this work? Maybe making the child |
Isn't |
I don't think the original use case makes sense. If their end goal is to create a link that looks like a button, they should style it themselves instead of wrapping button with a link. The original issue is like doing <a href="https://www.w3schools.com"><button type="button" onclick="alert('Hello world!')">Click Me!</button></a> |
on I forgot it doesn't register ontap. yeah in this case, Link is not a full fledged The problem is elevated button itself will create a semantics container. You mentioned mergesemantics doesn't work, do you know which part it is not working? |
This is actually exactly the use case that the In the past, people did: SomeButton(
onPressed: () {
launchUrl("https://www.w3schools.com");
},
child: Text("Click here"),
) and complained that they didn't get a proper web link behavior (cmd+click, context menu, etc). So we wanted people to do this instead: Link(
uri: Uri.parse("https://www.w3schools.com"),
builder: (ctx, onPressed) => SomeButton(
onPressed: onPressed,
child: Text("Click here"),
),
) which lets them use all existing buttons and widgets, and makes them behave like real web links. |
If you do this on the web
you will also need two tabs |
Yes, the problem is that when you merge them, the semantics's Uri of the link gets lost. It looks like the engine is removing it. Likely because the child of the Link widget has its semantics button and is is taking precedence over the link's semantics properties. Interesting enough, the Link's semantics Will share the semantics tree diff here in a few hours |
I can think of several way.
|
@chunhtai any way you could help me with the fix in Flutter's framework/engine? Initially I though by adding the missing I would say, I'm now bakc to square zero as I ran out of ideas, would appreciate some hints on where to start |
Where are you stuck? it does look like we missed the absorb for the link url. |
In your comment |
I believe that would be here: |
Hmm, I actualy did tried changing that already, couldn't notice any difference on the semantic tree 🤔 perhaps my testing env wasn't using the correct engine path... I will try again, thanks! |
@pedromassango I'm not sure how familiar you are with engine development, so I may be stating the obvious 🙂 After you make changes in engine sources, you have to rebuild the engine using |
Yeah, I totally missed this, let me try again. btw, I am mostly familiar with the framework & pretty new to the engine |
Ok, this is ready for review, I still would love the Link widget to merge the semantics itself, if you allow for it. Reason being without this, the framework/engine fix is somewhat useless and we would still need to educate customers in how to "workaround the issue". By letting |
Finally have a draft PR for the engine: flutter/flutter#174473. Pleas have a look! Turns out I was missing the commands #9815 (comment) to very my fixes 🫠 |
Tries to fix the TAB traversal issue on web by ensuring the semantics of the
Link
are merged with its children. The buttons are treated as LINKS only and this prevents semantic conflicts that would create extra focusable DOM nodes.With
MergeSemantics
, the semantics tree was not generated properly, e.glinkUrl
value gets removed from the final semantics tree. This is being fixed in the engine, see flutter/flutter#174473flutter/flutter#157689
Required engine fix PR:
flutter/flutter#174473
Pre-Review Checklist
[shared_preferences]
pubspec.yaml
with an appropriate new version according to the [pub versioning philosophy], or I have commented below to indicate which [version change exemption] this PR falls under1.CHANGELOG.md
to add a description of the change, [following repository CHANGELOG style], or I have commented below to indicate which [CHANGELOG exemption] this PR falls under1.///
).If you need help, consider asking for advice on the #hackers-new channel on [Discord].
Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the
gemini-code-assist
bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.Footnotes
Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. ↩ ↩2 ↩3