Web Share API Implementation on Website
Web Share API invokes native OS sharing dialog — the same that opens when sharing from mobile app. User sees their apps list: Telegram, WhatsApp, Notes, Mail, AirDrop. No custom buttons for each social media, no popups with icons.
Support: iOS Safari 12.1+, Android Chrome 61+, Edge 79+. Desktop support partial — works in Chrome/Edge on Windows, not in Firefox and Safari macOS (without extensions).
Basic Sharing
interface ShareData {
title?: string
text?: string
url?: string
files?: File[]
}
async function share(data: ShareData): Promise<void> {
if (!navigator.share) {
throw new Error('Web Share API not supported')
}
// Check browser supports this data type
if (!navigator.canShare(data)) {
throw new Error('This content type not supported for sharing')
}
await navigator.share(data)
}
File Sharing
async function shareFile(file: File, title?: string): Promise<void> {
const data: ShareData = { files: [file], title }
if (!navigator.canShare?.(data)) {
// Fallback: offer download
const url = URL.createObjectURL(file)
const a = document.createElement('a')
a.href = url
a.download = file.name
a.click()
URL.revokeObjectURL(url)
return
}
await navigator.share(data)
}
// Share Canvas as image
async function shareCanvas(
canvas: HTMLCanvasElement,
filename: string,
title?: string
): Promise<void> {
const blob = await new Promise<Blob>((resolve, reject) =>
canvas.toBlob((b) => (b ? resolve(b) : reject(new Error('Error'))), 'image/png')
)
const file = new File([blob], filename, { type: 'image/png' })
await shareFile(file, title)
}
React Component with Fallback
interface ShareButtonProps {
url: string
title?: string
text?: string
fallbackCopy?: boolean
}
function ShareButton({ url, title, text, fallbackCopy = true }: ShareButtonProps) {
const [copied, setCopied] = useState(false)
const supportsShare = typeof navigator !== 'undefined' && 'share' in navigator
const handleShare = async () => {
if (supportsShare) {
try {
await navigator.share({ url, title, text })
} catch (e) {
// User canceled — not an error
if (e instanceof Error && e.name !== 'AbortError') {
console.error('Share error:', e)
}
}
return
}
if (fallbackCopy) {
await navigator.clipboard?.writeText(url)
setCopied(true)
setTimeout(() => setCopied(false), 2000)
}
}
return (
<button onClick={handleShare}>
{supportsShare ? 'Share' : copied ? 'Link copied' : 'Copy link'}
</button>
)
}
What's Involved
Utility share with support check and canShare, React component with fallback (copy to buffer), file and image support if needed, AbortError handling (user closed dialog).
Timeline: 2–3 hours.







