npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-sharesheet

v1.8.0

Published

A mobile-first share sheet for React with native share support, Open Graph previews, 15+ social platforms, and headless APIs. Tailwind-styled by default, fully customizable.

Readme

react-sharesheet

npm version npm downloads License: MIT Demo

A mobile-first share sheet for React with native share support, built-in Open Graph previews, and 15+ social platforms.

Designed for modern React apps, react-sharesheet ships with a beautiful Tailwind-based drawer UI out of the box, while also exposing fully headless APIs for complete customization.

→ Live Demo

Why react-sharesheet?

  • 📱 Mobile-first drawer UI - feels native on iOS & Android
  • 🔗 Native Web Share API - fallback handled automatically
  • 🖼 Built-in Open Graph previews - no extra setup
  • 🧠 Headless APIs - build your own UI if needed
  • 🎨 Themeable - CSS variables + Tailwind class overrides
  • 🌍 15+ social platforms - WhatsApp, X, Telegram, Instagram, and more

Installation

npm install react-sharesheet
# or
pnpm add react-sharesheet
# or
yarn add react-sharesheet

Peer Dependencies

npm install react react-dom

Tailwind CSS Setup

Tailwind v4

Add the package source to your CSS file:

@import "tailwindcss";
@source "../../node_modules/react-sharesheet/dist";

Tailwind v3

Add the package to your tailwind.config.js content array:

// tailwind.config.js
module.exports = {
  content: [
    "./src/**/*.{js,ts,jsx,tsx}",
    "./node_modules/react-sharesheet/dist/**/*.{js,mjs}", // <-- Add this
  ],
  // ...
}

Quick Start

Full Drawer (recommended)

import { ShareSheetDrawer } from "react-sharesheet";

function App() {
  return (
    <ShareSheetDrawer
      title="Share this!"
      shareUrl="https://example.com"
      shareText="Check out this awesome page!"
    >
      <button>Share</button>
    </ShareSheetDrawer>
  );
}

Content Only (for custom modals)

import { ShareSheetContent } from "react-sharesheet/content";

function CustomModal() {
  return (
    <Dialog>
      <ShareSheetContent
        shareUrl="https://example.com"
        shareText="Check this out!"
      />
    </Dialog>
  );
}

Headless (full control)

import { useShareSheet } from "react-sharesheet/headless";

function CustomShareUI() {
  const {
    canNativeShare,
    copied,
    copyLink,
    nativeShare,
    shareWhatsApp,
    shareX,
  } = useShareSheet({
    shareUrl: "https://example.com",
    shareText: "Check this out!",
  });

  return (
    <div className="flex gap-2">
      {canNativeShare && <button onClick={nativeShare}>Share</button>}
      <button onClick={copyLink}>{copied ? "Copied!" : "Copy"}</button>
      <button onClick={shareWhatsApp}>WhatsApp</button>
      <button onClick={shareX}>X</button>
    </div>
  );
}

Automatic Link Preview

The share sheet automatically fetches Open Graph (OG) metadata from the shareUrl and displays a rich preview - just like Twitter, Telegram, and other platforms do when you paste a link.

<ShareSheetDrawer
  shareUrl="https://gwendall.com"  // OG data fetched automatically!
  shareText="Check out this site!"
>
  <button>Share</button>
</ShareSheetDrawer>

The component will:

  1. Fetch OG metadata (title, description, image) from the URL
  2. Display a loading shimmer while fetching
  3. Show the OG image if available, or a placeholder with the page title

Using the OG Hook Directly

You can also use the useOGData hook for custom implementations:

import { useOGData } from "react-sharesheet/headless";

function CustomPreview({ url }: { url: string }) {
  const { ogData, loading, error } = useOGData(url);

  if (loading) return <div>Loading...</div>;
  if (!ogData) return <div>No preview available</div>;

  return (
    <div>
      {ogData.image && <img src={ogData.image} alt={ogData.title} />}
      <h3>{ogData.title}</h3>
      <p>{ogData.description}</p>
    </div>
  );
}

OGData Type

interface OGData {
  title?: string;       // Page title
  description?: string; // Page description
  image?: string;       // OG image URL
  url?: string;         // Canonical URL
  siteName?: string;    // Site name
}

Theming

CSS Variables

Override these variables to match your theme. Note: Colors are applied via inline styles, so CSS variables are the only way to customize them (Tailwind classes won't override inline styles).

:root {
  /* Drawer */
  --sharesheet-overlay-bg: rgba(0, 0, 0, 0.7);
  --sharesheet-drawer-bg: #09090b;
  --sharesheet-drawer-border: #27272a;
  --sharesheet-handle-bg: #27272a;
  
  /* Typography */
  --sharesheet-title-color: #ffffff;
  --sharesheet-subtitle-color: #a1a1aa;
  --sharesheet-button-label-color: #ffffff;
  
  /* Image Preview */
  --sharesheet-preview-bg: rgba(255, 255, 255, 0.05);
  --sharesheet-preview-shimmer: rgba(255, 255, 255, 0.1);
  
  /* Platform colors (optional - defaults to brand colors) */
  --sharesheet-whatsapp-bg: #25D366;
  --sharesheet-telegram-bg: #229ED9;
  /* ... see full list below */
}

/* Dark/Light mode support */
.dark {
  --sharesheet-drawer-bg: #0a0a0a;
}

.light {
  --sharesheet-drawer-bg: #ffffff;
  --sharesheet-title-color: #09090b;
}
/* Drawer */
--sharesheet-overlay-bg: rgba(0, 0, 0, 0.7);
--sharesheet-drawer-bg: #09090b;
--sharesheet-drawer-border: #27272a;
--sharesheet-handle-bg: #27272a;

/* Typography */
--sharesheet-title-color: #ffffff;
--sharesheet-subtitle-color: #a1a1aa;
--sharesheet-button-label-color: #ffffff;

/* Image Preview */
--sharesheet-preview-bg: rgba(255, 255, 255, 0.05);
--sharesheet-preview-shimmer: rgba(255, 255, 255, 0.1);

/* Platform backgrounds */
--sharesheet-native-bg: #7c3aed;
--sharesheet-copy-bg: #3b82f6;
--sharesheet-download-bg: #ef4444;
--sharesheet-whatsapp-bg: #25D366;
--sharesheet-telegram-bg: #229ED9;
--sharesheet-instagram-bg: #E1306C;
--sharesheet-facebook-bg: #1877F2;
--sharesheet-snapchat-bg: #FFFC00;
--sharesheet-sms-bg: #22c55e;
--sharesheet-email-bg: #f97316;
--sharesheet-linkedin-bg: #0A66C2;
--sharesheet-reddit-bg: #FF4500;
--sharesheet-x-bg: #000000;
--sharesheet-tiktok-bg: #000000;
--sharesheet-threads-bg: #000000;

Tailwind Class Overrides

Override any part of the component with classNames:

<ShareSheetDrawer
  shareUrl="..."
  shareText="..."
  classNames={{
    // Drawer
    overlay: "bg-black/80 backdrop-blur-sm",
    drawer: "bg-background rounded-t-3xl",
    drawerInner: "p-6",
    handle: "bg-muted",
    trigger: "cursor-pointer",
    
    // Content
    root: "max-w-lg",
    header: "mb-6",
    title: "text-3xl font-bold text-foreground",
    subtitle: "text-muted-foreground",
    
    // Preview
    preview: "mb-4",
    previewSkeleton: "rounded-xl",
    previewImage: "border border-white/10",
    
    // Buttons
    grid: "gap-6",
    button: "w-20",
    buttonIcon: "rounded-xl shadow-lg",
    buttonLabel: "font-medium",
  }}
>

API Reference

Props

ShareSheetContent / ShareSheetDrawer

| Prop | Type | Default | Description | |------|------|---------|-------------| | title | string | "Share" | Title displayed at the top | | shareUrl | string | required | URL to share (OG preview fetched automatically) | | shareText | string | required | Text to share | | downloadUrl | string | - | URL for download button | | downloadFilename | string | - | Filename for download | | className | string | - | Class for root container | | classNames | object | - | Override sub-component classes | | buttonSize | number | 45 | Button size in pixels | | iconSize | number | 22 | Icon size in pixels | | show | ShareOption[] | - | Show only these platforms, in this exact order | | hide | ShareOption[] | - | Hide these platforms | | labels | object | - | Custom button labels | | icons | object | - | Custom button icons | | onNativeShare | () => void | - | Native share callback | | onCopy | () => void | - | Copy callback | | onDownload | () => void | - | Download callback |

ShareSheetDrawer (additional)

| Prop | Type | Default | Description | |------|------|---------|-------------| | children | ReactNode | required | Trigger element | | disabled | boolean | false | Disable the trigger | | open | boolean | - | Controlled open state | | onOpenChange | (open: boolean) => void | - | Open state callback |

ShareOption

Available platform identifiers:

type ShareOption =
  | "native"    // Native share API
  | "copy"      // Copy to clipboard
  | "download"  // Download file
  | "whatsapp"
  | "telegram"
  | "instagram"
  | "facebook"
  | "snapchat"
  | "sms"
  | "email"
  | "linkedin"
  | "reddit"
  | "x"
  | "tiktok"
  | "threads";

useShareSheet Hook

const {
  canNativeShare,  // boolean - browser supports native share
  copied,          // boolean - link was recently copied
  downloading,     // boolean - download in progress
  safeUrl,         // string - resolved share URL
  
  // Actions
  copyLink,        // () => Promise<void>
  nativeShare,     // () => Promise<void>
  downloadFile,    // () => Promise<void>
  
  // Platform share functions
  shareWhatsApp,   // () => void
  shareTelegram,   // () => void
  shareX,          // () => void
  shareFacebook,   // () => void
  shareInstagram,  // () => void
  shareTikTok,     // () => void
  shareThreads,    // () => void
  shareSnapchat,   // () => void
  shareSMS,        // () => void
  shareEmail,      // () => void
  shareLinkedIn,   // () => void
  shareReddit,     // () => void
} = useShareSheet({
  shareUrl: string,
  shareText: string,
  downloadUrl?: string,
  downloadFilename?: string,
  emailSubject?: string,
  onNativeShare?: () => void,
  onCopy?: () => void,
  onDownload?: () => void,
});

Exports

// Everything
import { 
  ShareSheetDrawer, 
  ShareSheetContent,
  useShareSheet,
  CSS_VARS,
  CSS_VAR_DEFAULTS,
  // Platform utilities
  PLATFORMS,
  PLATFORM_COLORS,
  PLATFORM_ICONS,
  PLATFORM_LABELS,
  getPlatform,
  getPlatformColor,
  // Share functions
  shareToWhatsApp,
  shareToX,
  // ...
} from "react-sharesheet";

// Content only (smaller bundle)
import { ShareSheetContent } from "react-sharesheet/content";

// Drawer only
import { ShareSheetDrawer } from "react-sharesheet/drawer";

// Headless (smallest bundle - no UI components)
import { 
  useShareSheet, 
  PLATFORM_COLORS,
  PLATFORM_ICONS,
  getPlatform,
  shareToWhatsApp, 
  shareToX,
  // ...
} from "react-sharesheet/headless";

Platform Utilities

Access platform colors, icons, and labels for custom UIs:

import { 
  PLATFORM_COLORS, 
  PLATFORM_ICONS, 
  PLATFORM_LABELS,
  getPlatform,
  getAllPlatforms,
} from "react-sharesheet";

// Get all platforms
const platforms = getAllPlatforms();
// [{ id: "whatsapp", label: "WhatsApp", colors: {...}, Icon: ... }, ...]

// Get single platform
const whatsapp = getPlatform("whatsapp");
// { id: "whatsapp", label: "WhatsApp", colors: { bg: "#25D366", text: "#fff" }, Icon: ... }

// Use colors directly
const bgColor = PLATFORM_COLORS.whatsapp.bg; // "#25D366"
const textColor = PLATFORM_COLORS.whatsapp.text; // "#ffffff"

// Use icons
const WhatsAppIcon = PLATFORM_ICONS.whatsapp;
<WhatsAppIcon size={24} className="text-white" />

// Use labels
const label = PLATFORM_LABELS.whatsapp; // "WhatsApp"

Build a custom share button

import { getPlatform, shareToWhatsApp } from "react-sharesheet";

function WhatsAppButton({ url, text }: { url: string; text: string }) {
  const { colors, Icon, label } = getPlatform("whatsapp");
  
  return (
    <button
      onClick={() => shareToWhatsApp(url, text)}
      style={{ backgroundColor: colors.bg, color: colors.text }}
    >
      <Icon size={20} />
      {label}
    </button>
  );
}

Examples

Filter platforms

// Show only specific platforms
<ShareSheetContent
  shareUrl="..."
  shareText="..."
  show={["copy", "whatsapp", "telegram", "x"]}
/>

// Hide specific platforms
<ShareSheetContent
  shareUrl="..."
  shareText="..."
  hide={["tiktok", "snapchat", "threads"]}
/>

Custom labels

<ShareSheetContent
  shareUrl="..."
  shareText="..."
  labels={{
    copy: "Copy Link",
    native: "More options...",
    whatsapp: "Send via WhatsApp",
  }}
/>

With download

<ShareSheetDrawer
  shareUrl="https://example.com/post/123"
  shareText="Check out my video!"
  downloadUrl="https://example.com/video.mp4"
  downloadFilename="my-video.mp4"
>
  <button>Share</button>
</ShareSheetDrawer>

Controlled state

function ControlledExample() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <button onClick={() => setOpen(true)}>Open Share Sheet</button>
      <ShareSheetDrawer
        open={open}
        onOpenChange={setOpen}
        shareUrl="..."
        shareText="..."
      >
        <span /> {/* Hidden trigger */}
      </ShareSheetDrawer>
    </>
  );
}

Styling & Tailwind

react-sharesheet ships with a Tailwind-based UI by default.

Tailwind is only required if you use the prebuilt components.
If you don't use Tailwind, you can:

  • Use the headless hook to build your own UI
  • Override all styles via classNames
  • Use the exposed CSS variables

This makes react-sharesheet easy to integrate into any React stack.

Requirements

  • React 18+
  • Tailwind CSS (only for prebuilt components)

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT © Gwendall