feat: Add Web Share API support#24325
Open
Artur- wants to merge 5 commits into
Open
Conversation
Artur-
added a commit
to vaadin/use-cases
that referenced
this pull request
May 13, 2026
Six use cases exercising Page#shareSupportSignal() and Page#share(...) from vaadin/flow#24325: share this page, copy-link fallback, custom message, per-item share in a list, completion feedback, and invite link. Includes browserless tests, Fly deployment config, and an API-GAPS.md noting the file-share / canShare / test-simulator gaps surfaced while building the demos.
Member
Author
|
This should be based on trigger/action type API |
caalador
reviewed
May 18, 2026
Reshape Web Share around the trigger/action framework: a new ShareAction extending PromiseAction renders the navigator.share() call inside a trigger handler, so it inherits the user gesture the API requires (Page .executeJs() through a server round-trip cannot). A public WebShare facade mirrors Clipboard's onClick(button).share(content) shape, with ShareContent as a multi-format payload builder accepting either string literals or HasValue components for title, text, and url. A WebShare.supportSignal() mirrors Geolocation.availabilityHintSignal() and is seeded from a new v-ws bootstrap parameter through ExtendedClientDetails into a UIInternals ValueSignal<WebShareSupport>.
# Conflicts: # flow-client/src/main/frontend/Flow.ts # flow-server/src/main/java/com/vaadin/flow/component/internal/UIInternals.java # flow-server/src/main/java/com/vaadin/flow/component/page/ExtendedClientDetails.java
Return a cached read-only wrapper from the WebShare support signal accessor instead of calling asReadonly() afresh on every read, matching the WakeLock and PageVisibility signals and the signal design guideline. A fresh asReadonly() per call yields an unstable identity and needless allocations.
WebShare.ts already has a named export (isShareSupported), so the
trailing 'export {}' is redundant and the client build's eslint rule
@typescript-eslint/no-useless-empty-export rejects it, failing CI.
Also pass the share-slot captures as Object[] to JsFunction.of to avoid
the non-varargs varargs-call compiler warning.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary
WebSharefacade for the browser's Web Share API:WebShare.onClick(button).share(ShareContent.create().title("...").text("...").url("..."))opens the native share sheet when the user clicks, optionally reporting the outcome back to the server throughonShared/onErrorcallbacks.ShareActionextendingPromiseAction), sonavigator.share()executes inside the client-side click handler and inherits the transient user gesture the API requires — a server round-trip viaPage.executeJs()would lose the activation and the browser would reject the call.WebShare.supportSignal()exposes feature detection as a read-only signal, seeded during the bootstrap handshake via a newv-wsparameter (Flow.ts→ExtendedClientDetails→ aValueSignal<WebShareSupport>onUIInternals), so views can decide whether to show a share affordance before any view code runs.Details
ShareContentis a builder withtitle/text/urlslots; each slot accepts either a string literal or aHasValuecomponent, in which case the component'svalueproperty is read on the client at gesture time. At least one slot must be set — the Web Share API rejects an empty payload, so this is validated server-side.onErrordeliberately fires for theAbortErrorthe browser reports when the user dismisses the share sheet without picking a target, not only for true failures; this matches browser semantics and is documented on the callback.UNKNOWNonly before the first handshake, then a stableSUPPORTED/UNSUPPORTEDfor the rest of the session. The read-only wrapper is cached onUIInternalsfor stable identity.navigator.share({...})payload composition (literal and property-backed slots, partial payloads, promise observation wrapping) and the signal seeding.API Changes: feature/web-share vs origin/main
6 classes affected — 5 new public types, 2 methods added to an existing class.
com.vaadin.flow.component.internal.UIInternals
com.vaadin.flow.component.trigger.internal.ShareAction
com.vaadin.flow.component.webshare.ShareContent
com.vaadin.flow.component.webshare.WebShare
com.vaadin.flow.component.webshare.WebShareBinding
com.vaadin.flow.component.webshare.WebShareSupport