Tips & Tricks (Diperbarui: 7/6/2026)

Bikin tombol berbagi dengan navigator.share: browser tak didukung dialihkan ke salin

Dari kegagalan tombol berbagi diam di separuh perangkat: cara pakai navigator.share, syarat HTTPS dan tap, plus fallback salin.

Bikin tombol berbagi dengan navigator.share: browser tak didukung dialihkan ke salin

Saya minta dibikinkan “tombol berbagi”, dan ketika tombol jadinya saya pencet di PC sendiri, tidak terjadi apa-apa.

Tidak ada error. Bahkan tidak terasa seperti baru saja diklik. Saya kira itu bug, jadi hampir satu jam saya melototi log, sampai akhirnya sadar: di Chrome desktop saya, fitur itu memang tidak ada sejak awal. Begitu saya buka di ponsel, share sheet OS muncul dengan rapi.

Inilah bagian paling merepotkan dari Web Share API. Di perangkat yang mendukung, ia berguna seperti sihir; di perangkat yang tidak, ia jadi “kekosongan”. Dan karena diam tanpa reaksi, sulit menyadari bahwa ada yang rusak. Hari ini kita angkat tombol ini dari kondisi “mati di separuh perangkat” menjadi kondisi “selalu memberi reaksi di semua perangkat”.

Poin penting

  • navigator.share() membuka share sheet standar OS. Kuat di ponsel, tetapi lingkungan tak didukung seperti Chrome desktop itu hal biasa.
  • Pemanggilannya punya dua syarat: wajib HTTPS (atau localhost) dan hanya jalan tepat setelah aksi pengguna seperti klik atau tap.
  • Saat tak didukung atau gagal, alihkan tombol yang sama ke salin ke clipboard. Jangan menghilangkan tombolnya.
  • Untuk berbagi file, cek dulu dengan navigator.canShare({ files }) sebelum mengoper. Mengoper langsung bisa membuat eksepsi.
  • AbortError yang hanya berarti pengguna menutup sheet jangan diperlakukan sebagai kegagalan. Menampilkan toast merah hanya membingungkan.

Sebenarnya navigator.share itu melakukan apa

Di ponsel, saat kamu mau “berbagi” sesuatu, muncul sheet dari bawah berisi deretan WhatsApp, email, catatan, Slack, AirDrop, dan seterusnya, kan? Memanggil sheet itu langsung dari halaman web adalah tugas Web Share API. Intinya satu fungsi: navigator.share().

Apa enaknya? Kamu tidak perlu menyusun sendiri daftar aplikasi tujuan berbagi.

Cara lama, kamu menaruh ikon SNS satu per satu: X, Facebook, WhatsApp, dan seterusnya. Tapi dengan cara itu, aplikasi yang benar-benar ingin dipakai pengguna (catatan pribadi, atau Slack kantor) biasanya terlewat. Dengan navigator.share(), aplikasi yang terpasang di perangkat orang itu langsung jadi pilihannya. Pekerjaan menyusun ikon kamu serahkan sepenuhnya ke OS.

Data yang dioper sederhana, cukup satu objek seperti ini.

navigator.share({
  title: "Judul artikel",
  text: "Kalimat pengantar singkat",
  url: "https://example.com/article",
});

Tiga hal dasar: title, text, url. Kamu juga boleh hanya mengoper url saja, atau text saja. Bagaimana aplikasi penerima menampilkannya terserah aplikasi itu, jadi anggap saja tugasmu cuma “mengoper bahan”. Argumen lengkapnya bisa kamu cek di Navigator.share() MDN sebagai sumber primer yang akurat.

Pahami dulu lingkungan yang jalan dan yang tidak

Hal paling penting adalah membulatkan tekad bahwa Web Share API bukan fitur yang jalan di mana saja. Seperti yang membuat saya tersandung, Chrome desktop belum mendukung (saat tulisan ini dibuat). Safari dan keluarga mobile umumnya bisa. Karena itu aturan mainnya: selalu cek “ada atau tidak” sebelum memanggil.

Deteksinya cuma begini. Periksa apakah navigator.share ada sebagai fungsi.

if (typeof navigator.share === "function") {
  // lingkungan yang bisa membuka share sheet
}

Selain itu, pemanggilannya punya dua syarat. Tanpa tahu ini, akan terjadi kecelakaan tipe “di lokal jalan tapi di produksi tidak” atau “tombol tampil tapi dipencet malah eksepsi”. MDN pun menuliskannya secara jelas sebagai syarat penggunaan Web Share API.

SyaratIsiKecelakaan yang sering terjadi
secure contextHanya jalan di HTTPS atau localhostLingkungan uji http:// atau akses lewat IP langsung jadi diam
Wajib aksi penggunaDitolak jika bukan tepat setelah klik/tapMencoba membuka berbagi otomatis bersamaan tampilnya layar lalu gagal
Validitas dataBentuk url atau dukungan file yang dioper harus memenuhi syaratURL tidak valid atau file tak didukung memicu eksepsi
Permissions PolicyDi dalam iframe tidak bisa jika induk tak mengizinkan web-shareDiam-diam tidak jalan di lingkungan embed

Dengan melihat window.isSecureContext, kamu bisa memastikan apakah halaman saat ini adalah secure context lewat nilai true / false. Saat pengembangan kamu bisa menguji di localhost, lalu hanya di URL produksi mengalihkan ke UI salin, sebagai pemisahan kasus.

Bisa copy-paste langsung: versi lengkap berbagi lalu salin saat gagal

Inilah bagian utamanya. Saya tampilkan struktur minimal yang langsung jalan baik di HTML biasa, Astro, situs statis, maupun PWA. Konsepnya tiga tahap.

  1. Jika navigator.share ada, buka share sheet dengannya.
  2. Jika pengguna membatalkan (AbortError), kembalikan seolah tidak terjadi apa-apa.
  3. Jika tak didukung atau gagal, salin ke clipboard dari tombol yang sama.

Pertama, tombol dan teks kecil untuk menyampaikan status. Dengan aria-live, screen reader akan membacakan perubahan status.

<button data-share type="button">Bagikan artikel ini</button>
<p data-share-status aria-live="polite"></p>

Berikutnya skripnya. Dibuat agar alurnya bisa diikuti dengan membaca komentarnya.

// Bahan untuk dibagikan. Ganti title / text / url per halaman
const payload = {
  title: document.title,
  text: "Catatan implementasi tombol berbagi dengan navigator.share.",
  url: window.location.href,
};

const button = document.querySelector("[data-share]");
const statusEl = document.querySelector("[data-share-status]");

// Fungsi kecil yang hanya mengganti teks status
function setStatus(message) {
  if (statusEl) statusEl.textContent = message;
}

// Satu blok teks untuk dioper ke aplikasi tujuan (dipakai saat fallback salin)
function buildText(data) {
  return [data.title, data.text, data.url].filter(Boolean).join("\n\n");
}

// Fallback: salin ke clipboard. Kalau itu pun gagal, beralih ke salin manual
async function copyFallback(data) {
  const text = buildText(data);
  if (navigator.clipboard && window.isSecureContext) {
    await navigator.clipboard.writeText(text);
    setStatus("Tautan tersalin. Tempelkan ke chat atau media sosial.");
    return;
  }
  window.prompt("Salin teks ini", text);
  setStatus("Salin teks yang ditampilkan lalu bagikan.");
}

button?.addEventListener("click", async () => {
  // Normalkan url ke URL absolut agar tidak tersesat di tujuan berbagi
  const data = { ...payload, url: new URL(payload.url, location.href).href };

  // 1. Jika lingkungan mendukung, buka share sheet
  if (typeof navigator.share === "function") {
    try {
      await navigator.share(data);
      setStatus("Share sheet dibuka.");
      return;
    } catch (error) {
      // 2. Pengguna hanya menutup. Ini bukan kegagalan, jadi kembalikan diam-diam
      if (error.name === "AbortError") {
        setStatus("");
        return;
      }
      // Eksepsi selain itu dialirkan ke fallback salin
      console.warn("navigator.share gagal. Beralih ke salin.", error);
    }
  }

  // 3. Tak didukung atau gagal -> salin
  try {
    await copyFallback(data);
  } catch (error) {
    console.error("Salin juga gagal.", error);
    setStatus("Gagal menyalin. Salin URL dari address bar.");
  }
});

Ingat satu hal saja. Bahkan di lingkungan tanpa navigator.share, tombol yang sama tetap hidup sebagai “salin”. Kalau kamu menghilangkan tombol lewat percabangan kondisi, pengguna akan menyimpulkan “fitur ini tidak ada” dan tidak pernah mencarinya lagi. Dengan membiarkannya tetap ada, kamu menyerap perbedaan antar-browser sekaligus selalu mengantar orang yang menekan ke langkah berikutnya.

Saat dipindah ke React atau Vue pun, isi handler click ini bisa dipakai apa adanya. Cukup ganti statusEl.textContent dengan setState. Buat yang ingin mendalami izin clipboard dan pengujiannya, di artikel terpisah implementasi Clipboard API saya rangkum perilaku saat salin gagal dan verifikasi dengan Playwright.

Kalau berbagi file, panggil canShare lebih dulu

Bukan cuma URL atau teks, ada kalanya kamu mau berbagi gambar atau PDF. Diagram yang dihasilkan, PDF struk, tangkapan layar. Semua itu dimasukkan sebagai objek File ke dalam array files lalu dioper.

Namun, dukungan berbagi file lebih sempit daripada berbagi teks. Jadi kalau kamu langsung memanggil navigator.share({ files }), di lingkungan tak didukung ia akan memuntahkan eksepsi dan mati. Lebih aman bertanya dulu “bahan ini, bisa dibagikan?” lewat navigator.canShare() sebelum mengoper.

async function shareFile(file) {
  const data = { files: [file], title: "Dokumen", text: "Membagikan PDF" };

  // Cek dulu lewat canShare apakah file ini bisa dibagikan
  if (navigator.canShare && navigator.canShare(data)) {
    try {
      await navigator.share(data);
      return "shared";
    } catch (error) {
      if (error.name === "AbortError") return "cancelled";
      console.warn("Berbagi file gagal. Beralih ke berbagi URL.", error);
    }
  }

  // Tak didukung atau gagal -> alihkan ke berbagi URL unduhan atau salin
  return "fallback";
}

canShare adalah fungsi ringan yang hanya mengembalikan true / false, dan ia sendiri tidak membuka sheet. Khusus untuk deteksi. Kalau tak didukung, ketimbang memaksa mengoper file, membagikan URL unduhan dari file yang sudah diunggah jauh menurunkan tingkat kegagalan.

Di PWA ada “sisi yang berbagi” dan “sisi yang dibagikan”

Inilah bagian paling menarik dari Web Share API.

navigator.share() tadi soal sisi yang berbagi keluar dari situsmu. Di sisi lain, PWA juga punya mekanisme menjadi sisi yang menerima berbagi (share target) dari aplikasi lain. Saat di ponsel kamu mau membagikan foto lalu PWA buatanmu ikut berjajar di daftar tujuan berbagi, itu maksudnya.

Mekanismenya cukup menuliskan share_target di manifest.json PWA. OS akan mengenali “PWA ini bisa menerima berbagi” dan memasukkannya ke pilihan share sheet.

{
  "share_target": {
    "action": "/share-receiver",
    "method": "GET",
    "params": {
      "title": "title",
      "text": "text",
      "url": "url"
    }
  }
}

Dengan menulis begini, data yang dibagikan dari aplikasi lain akan datang berbarengan query seperti /share-receiver?title=...&text=...&url=.... Selanjutnya halaman penerima tinggal membacanya lalu menyimpan atau menampilkannya. Pemasangan PWA dan desain di sisi service worker saya rangkum langkahnya di artikel jadi PWA, jadi buat yang ingin membangun sampai share target, baca sekalian.

Ada satu alasan lagi kenapa tombol berbagi jadi berperan di PWA. Saat diluncurkan dari home screen, address bar dan menu berbagi browser menghilang, sehingga tombol berbagi yang kamu taruh di dalam halaman menjadi satu-satunya jalur keluar ke luar. Dibanding saat dilihat lewat tab, tingkat kepentingan tombol itu naik.

Tiga kegagalan yang saya lakukan

Saya tulis jujur. Tombol berbagi pertama saya bolong di mana-mana.

Pertama, insiden diam di desktop di awal tadi. Saya malas mengecek keberadaan navigator.share dan langsung memanggilnya. Karena saya tes di ponsel, saya tidak sadar, lalu menerbitkan “tombol yang dipencet tak terjadi apa-apa” ke produksi di PC tak didukung. Setelah saya pasang pengecekan keberadaan dan fallback salin, sekarang di perangkat mana pun selalu ada reaksi.

Kedua, menampilkan AbortError sebagai toast merah. Pengguna cuma menutup share sheet pelan-pelan, tapi setiap kali muncul error “gagal berbagi”. Padahal menutup itu bukan kegagalan. Setelah saya ubah jadi khusus AbortError ditelan tanpa menampilkan apa pun, peringatan aneh itu hilang.

Ketiga, mencoba membuka berbagi bersamaan tampilnya halaman. Karena rakus ingin “begitu selesai baca, tolong dibagikan”, saya memanggil navigator.share() di onload, lalu ditolak NotAllowedError karena tidak ada aksi pengguna. Web Share API hanya jalan tepat setelah klik atau tap. Sudah jelas, tapi godaan untuk membuka otomatis itu diam-diam kuat. Sekarang saya selalu memanggilnya dari click tombol.

Pertanyaan umum

T. navigator.share tidak jalan di desktop. Apakah ini bug? J. Bukan bug, ini sesuai spesifikasi. Saat tulisan ini dibuat, Chrome desktop dan sejenisnya belum mendukung, sehingga navigator.share sendiri tidak ada. Bercabanglah dengan typeof navigator.share === "function", dan kalau tak didukung alihkan ke salin.

T. Di lokal jalan tapi di produksi tidak. J. Sering kali penyebabnya syarat secure context (HTTPS atau localhost). Di staging http:// atau akses lewat IP langsung tidak jalan. Bisa kamu pastikan dengan window.isSecureContext.

T. Bisakah saya mengukur siapa berbagi ke aplikasi mana? J. Tidak bisa. Web Share API tidak mengembalikan aplikasi tujuan ke situs. Sebagai gantinya, mencatat empat jenis terpisah, “tombol ditekan”, “share sheet terbuka”, “batal”, “fallback salin”, berguna untuk perbaikan. Desain event lebih enak dibaca nanti jika kamu satukan ke implementasi analitik.

T. Apa beda AbortError dan NotAllowedError? J. AbortError hanya berarti pengguna menutup sheet (jangan dianggap kegagalan). NotAllowedError adalah penolakan karena, misalnya, dipanggil tanpa aksi pengguna. Untuk yang kedua, tinjau ulang apakah implementasimu sudah memanggilnya tepat setelah klik.

T. Saya ingin berbagi gambar atau PDF. J. Masukkan File ke array files lalu oper, tapi pastikan dulu dukungannya lewat navigator.canShare({ files }) sebelum memanggil. Kalau tak didukung, lebih aman beralih ke berbagi URL unduhan.

Hasil setelah saya coba langsung

Setelah saya bagikan ke beberapa perangkat, yang saya pahami adalah fakta bahwa nilai Web Share API terletak bukan pada “sheet-nya terbuka”, melainkan pada “tidak menghentikan pembaca di perangkat yang tidak membukanya”. Sesuai syarat penggunaan di MDN, kondisi didukung, tak didukung, dan batal terpisah dengan rapi, jadi cukup susun urutannya: cek keberadaan navigator.share -> sukses -> abaikan AbortError -> selain itu salin, dan tombol diam pun lenyap.

Saat meminta ke Claude Code pun, ketimbang “bikinkan tombol berbagi”, kalau kamu tulis sampai syaratnya, “bikin tombol berbagi yang di browser tak didukung dialihkan ke salin, dan AbortError tidak dianggap kegagalan”, bentuk yang siap pakai di produksi langsung dikembalikan sekali jalan. Buat yang ingin sekaligus memantapkan desain seputar berbagi bersama tim, lewat pelatihan / konsultasi kamu bisa merancang PWA, pengukuran, dan fallback secara menyeluruh. Mengoper bahan itu tugas OS; tugas kita adalah “menyiapkan langkah berikutnya di perangkat mana pun”. Begitu kamu menerima ini, tombol berbagi jadi jauh lebih mudah dibuat.

#Web Share API #navigator.share #tombol berbagi #fallback #PWA
Gratis

PDF gratis: cheatsheet Claude Code

Masukkan email dan unduh satu halaman berisi command, kebiasaan review, dan workflow aman.

Kami menjaga datamu dan tidak mengirim spam.

Masa

Tentang penulis

Masa

Engineer yang berfokus pada workflow Claude Code praktis dan adopsi tim.