ShareButton
Shares a link through the system's share sheet, or copies it where the browser has none, and says which.
Demo
On a phone or a Mac this opens the system's share sheet; elsewhere it copies the link.
Get it
It needs theme.qwe, as every component does; or take the whole kit, quillo-ui.qwe. Each component brings its own styles to the pages that show it.
$ curl -O https://quillolang.org/components/ui/theme.qwe$ curl -O https://quillolang.org/components/ui/share_button.qwemain.qwe
import ui/theme.qwe use theme_cssuse ui/share_button.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>Example
The code of the preview above.
demos/share_button.qwe
component ShareButtonDemoLive() { state how = null <div.demo-row> <ShareButton url="https://quillolang.org/components/" title="Quillo UI" text="A UI kit for Quillo." on_share={(h) => { how = h }}/> <span.demo-note>{how == null ? "Not shared yet." : `Last: ${how}.`}</span> </div>}view ShareButtonDemo() = <div.demo-stack> <ShareButtonDemoLive/> <div.demo-row> <ShareButton label="Share this page" variant="soft" size="sm"/> <ShareButton label="Share" variant="solid" url="https://quillolang.org/"/> <ShareButton label="Share" variant="ghost" size="lg" url="https://quillolang.org/docs/"/> </div> <p.demo-note>On a phone or a Mac this opens the system's share sheet; elsewhere it copies the link.</p> </div>Source
ui/share_button.qwe
// ShareButton: shares a link through the system's share sheet (navigator.share: to// Messages, Mail, AirDrop, apps on a phone) and, where the browser has none, copies// the link to the clipboard and says "Link copied" for a moment (to screen readers// too). Closing the share sheet without sharing says nothing.//// <ShareButton url="https://example.com/posts/7" title="A post worth reading"/>// <ShareButton label="Share this page" text="Have a look at this." variant="soft" size="sm"/>//// url: the link (this page's address by default). title and text: sent along with// it where the share sheet takes them. label ("Share"): the button's text.// shared ("Shared"), copied ("Link copied") and failed ("Could not share"): what it// says for a moment after. variant: "outline" (default), "soft", "ghost" or "solid";// size: "sm", "md" or "lg". It is styled as a Button when button_css is on the page.// on_share(how): inside one of your components, called with "shared" or "copied".import ui/theme.qwe use ui_clslet share_button_css = css`.ui-share-button svg { flex: none; width: 16px; height: 16px; }.ui-share-button-labels { display: inline-grid; }.ui-share-button-labels > span { grid-area: 1 / 1; text-align: center; }.ui-share-button:not(.ui-share-button-ok) .ui-share-button-done, .ui-share-button:not(.ui-share-button-copied) .ui-share-button-copy,.ui-share-button:not(.ui-share-button-bad) .ui-share-button-fail, .ui-share-button-ok .ui-share-button-label, .ui-share-button-copied .ui-share-button-label,.ui-share-button-bad .ui-share-button-label { visibility: hidden; }.ui-share-button-ok svg, .ui-share-button-copied svg { color: var(--ui-success); }`component ShareButton(url: str? = null, title: str? = null, text: str? = null, label: str = "Share", shared: str = "Shared", copied: str = "Link copied", failed: str = "Could not share", variant: str = "outline", size: str = "md", on_share = null, class: str? = null) { style global share_button_css state result = "" // "", "ok", "copied" or "bad" if result != "" { every(1800, () => { result = "" }) } let said = match result { "ok" => shared "copied" => copied "bad" => failed _ => "" } let copy = (link: str) => { if js("isSecureContext") != true { result = "bad" } else { js("navigator.clipboard.writeText", link).then((_ = null) => { result = "copied" on_share && on_share("copied") }, (_ = null) => { result = "bad" }) } } <span> <button type="button" class={ui_cls(["ui-btn", `ui-btn-${variant}`, size != "md" && `ui-btn-${size}`, "ui-share-button", result != "" && `ui-share-button-${result}`, class])} @click={() => { let link = url ?? js("location.href") let data = { url: link, title: title ?? js("document.title"), text } let nav = js("navigator") if nav.share != null && (nav.canShare == null || nav.canShare(data) == true) { nav.share(data).then((_ = null) => { result = "ok" on_share && on_share("shared") }, (e = null) => { // Closing the sheet is an AbortError: nothing to say. Anything else: copy instead. if e == null || str(e.name) != "AbortError" { copy(link) } }) } else { copy(link) } }}> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> {result == "ok" || result == "copied" ? <path d="M20 6 9 17l-5-5"/> : <path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8M16 6l-4-4-4 4M12 2v13"/>} </svg> <span.ui-share-button-labels> <span.ui-share-button-label>{label}</span> <span.ui-share-button-done aria-hidden="true">{shared}</span> <span.ui-share-button-copy aria-hidden="true">{copied}</span> <span.ui-share-button-fail aria-hidden="true">{failed}</span> </span> </button> <span.ui-sr role="status">{said}</span> </span>}Related
BookmarkButtonA save-for-later toggle whose bookmark fills when pressed, with or without its label.8 views · 8 downloadsFollowButtonFollow becomes Following once pressed, and says Unfollow on hover, as the social sites do.5 views · 7 downloadsLikeButtonA heart that toggles with a count that follows it, a real toggle for screen readers and forms.5 views · 4 downloadsVoteButtonsUp and down votes around a score that follows them, as on a forum, in a column or a row.5 views · 6 downloadsButtonA button, or a link that looks like one: four variants, three tones, three sizes, loading.7 views · 7 downloadsButtonGroupButtons joined edge to edge into one control, or spaced in a row; across or upright.6 views · 6 downloads
Thread
Thread 0 posts
On ShareButton: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.