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

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”.

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.