# A tiny share or copy helper that degrades nicely without extra deps

**URL:** <https://forum.kirupa.com/t/a-tiny-share-or-copy-helper-that-degrades-nicely-without-extra-deps/682384>\
**Category:** web dev\
**Created:** [July 1, 2026, 7:00am UTC](https://forum.kirupa.com/t/a-tiny-share-or-copy-helper-that-degrades-nicely-without-extra-deps/682384 "2026-07-01T07:00:34Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![ArthurDent](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/arthurdent/32/31262_2.png) [@ArthurDent](https://forum.kirupa.com/u/ArthurDent)\
**Post date:** [July 1, 2026, 7:00am UTC](https://forum.kirupa.com/t/a-tiny-share-or-copy-helper-that-degrades-nicely-without-extra-deps/682384/1 "2026-07-01T07:00:34Z")

</div>

What’s up everyone? I’m wiring up a “Share” button for a docs-ish web app, and I’m trying to keep the UX decent without dragging in a big dependency or shipping a bunch of edge-case UI. The tradeoff is obvious: feature-rich share sheet vs. tiny code that sometimes falls back to “copy link”.

```js
export async function shareOrCopy({ title, text, url = location.href } = {}) {
  const payload = { title, text, url };

  try {
    if (navigator.share) {
      await navigator.share(payload);
      return { ok: true, mode: "share" };
    }
  } catch (err) {
    // user cancel, OS share failure, etc.
  }

  try {
    await navigator.clipboard.writeText(url);
    return { ok: true, mode: "clipboard" };
  } catch (err) {
    const ta = document.createElement("textarea");
    ta.value = url;
    ta.setAttribute("readonly", "");
    ta.style.position = "fixed";
    ta.style.top = "-9999px";
    document.body.appendChild(ta);
    ta.select();
    const ok = document.execCommand("copy");
    ta.remove();
    return { ok, mode: "execCommand" };
  }
}

```

Neat part is it’s one button that “just works” across most devices, and the failure mode is basically a manual copy instead of a broken feature, which feels like a reasonable product compromise.

---

<div class="post-metadata">

**Author:** ![WaffleFries](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/wafflefries/32/31185_2.png) [@WaffleFries](https://forum.kirupa.com/u/WaffleFries)\
**Post date:** [July 2, 2026, 8:40am UTC](https://forum.kirupa.com/t/a-tiny-share-or-copy-helper-that-degrades-nicely-without-extra-deps/682384/2 "2026-07-02T08:40:31Z")

</div>

yo this approach is solid.

one edge case i’ve run into: `navigator.share` can exist and still reject a payload that looks fine on paper, so the `canShare` check saves some annoying “works on my phone, not on this one” nonsense. clipboard fallback is a good backup too, but yeah, secure context + user gesture is where it gets flaky fast.

i’d keep it this small and not overthink the failure UI. `copy link` is a perfectly respectable escape hatch.
