diff --git a/.github/copilot/integrate-analytics.prompt.md b/.github/copilot/integrate-analytics.prompt.md
index 60cd595..cc8f4c6 100644
--- a/.github/copilot/integrate-analytics.prompt.md
+++ b/.github/copilot/integrate-analytics.prompt.md
@@ -41,14 +41,14 @@ forwards to whatever tool they choose.
## 2 — Core events catalogue
-| `eventName` | `interactionType` | Fires when |
-| ---------------------------- | ----------------- | ----------------------------------------------- |
-| `social_share_popup_open` | `popup_open` | Share modal/popup opens |
-| `social_share_popup_close` | `popup_close` | Modal closes (button, overlay, or Esc key) |
-| `social_share_click` | `share` | User clicks a platform button (share intent) |
-| `social_share_success` | `share` | Platform share window opened successfully |
-| `social_share_copy` | `copy` | User copies the link to clipboard |
-| `social_share_error` | `error` | Share or copy action failed |
+| `eventName` | `interactionType` | Fires when |
+| -------------------------- | ----------------- | -------------------------------------------- |
+| `social_share_popup_open` | `popup_open` | Share modal/popup opens |
+| `social_share_popup_close` | `popup_close` | Modal closes (button, overlay, or Esc key) |
+| `social_share_click` | `share` | User clicks a platform button (share intent) |
+| `social_share_success` | `share` | Platform share window opened successfully |
+| `social_share_copy` | `copy` | User copies the link to clipboard |
+| `social_share_error` | `error` | Share or copy action failed |
---
@@ -59,7 +59,7 @@ forwards to whatever tool they choose.
```js
// Fires on the container element and bubbles through the DOM (composed:true
// means it also crosses shadow-DOM boundaries).
-document.addEventListener("social-share", (e) => {
+document.addEventListener('social-share', (e) => {
const payload = e.detail;
// Forward to your analytics tool here
});
@@ -72,7 +72,7 @@ and Mixpanel both need the same event.
```js
new SocialShareButton({
- container: "#share-button",
+ container: '#share-button',
onAnalytics: (payload) => {
// Forward to your analytics tool here
},
@@ -96,11 +96,8 @@ Load the adapters file **in addition to** the main library script:
const { GoogleAnalyticsAdapter, MixpanelAdapter } = window.SocialShareAnalytics;
new SocialShareButton({
- container: "#share-button",
- analyticsPlugins: [
- new GoogleAnalyticsAdapter(),
- new MixpanelAdapter(),
- ],
+ container: '#share-button',
+ analyticsPlugins: [new GoogleAnalyticsAdapter(), new MixpanelAdapter()],
});
```
@@ -125,7 +122,7 @@ Prerequisite: GA4 `gtag.js` snippet loaded by the host.
const { GoogleAnalyticsAdapter } = window.SocialShareAnalytics;
new SocialShareButton({
- container: "#share-button",
+ container: '#share-button',
analyticsPlugins: [new GoogleAnalyticsAdapter()],
});
@@ -135,7 +132,7 @@ new SocialShareButton({
Custom event category (optional):
```js
-new GoogleAnalyticsAdapter({ eventCategory: "engagement" })
+new GoogleAnalyticsAdapter({ eventCategory: 'engagement' });
```
### Mixpanel
@@ -145,7 +142,7 @@ Prerequisite: `mixpanel-browser` snippet or SDK loaded.
```js
const { MixpanelAdapter } = window.SocialShareAnalytics;
new SocialShareButton({
- container: "#share-button",
+ container: '#share-button',
analyticsPlugins: [new MixpanelAdapter()],
});
// Calls: mixpanel.track(eventName, { platform, url, ... })
@@ -156,7 +153,7 @@ new SocialShareButton({
```js
const { SegmentAdapter } = window.SocialShareAnalytics;
new SocialShareButton({
- container: "#share-button",
+ container: '#share-button',
analyticsPlugins: [new SegmentAdapter()],
});
// Calls: analytics.track(eventName, { platform, url, ... })
@@ -169,7 +166,7 @@ Prerequisite: Plausible `script.js` loaded with custom events enabled.
```js
const { PlausibleAdapter } = window.SocialShareAnalytics;
new SocialShareButton({
- container: "#share-button",
+ container: '#share-button',
analyticsPlugins: [new PlausibleAdapter()],
});
// Calls: plausible(eventName, { props: { platform, url, ... } })
@@ -180,7 +177,7 @@ new SocialShareButton({
```js
const { PostHogAdapter } = window.SocialShareAnalytics;
new SocialShareButton({
- container: "#share-button",
+ container: '#share-button',
analyticsPlugins: [new PostHogAdapter()],
});
// Calls: posthog.capture(eventName, { platform, url, ... })
@@ -195,8 +192,8 @@ const { CustomAdapter } = window.SocialShareAnalytics;
new SocialShareButton({
analyticsPlugins: [
new CustomAdapter((payload) => {
- fetch("/api/analytics", {
- method: "POST",
+ fetch('/api/analytics', {
+ method: 'POST',
body: JSON.stringify(payload),
});
}),
@@ -231,17 +228,17 @@ GA4, Mixpanel, and a custom endpoint at the same time:
```js
const { GoogleAnalyticsAdapter, MixpanelAdapter, CustomAdapter } = window.SocialShareAnalytics;
-document.addEventListener("social-share", (e) => {
- console.log("Raw event:", e.detail); // Debugging / logging
+document.addEventListener('social-share', (e) => {
+ console.log('Raw event:', e.detail); // Debugging / logging
});
new SocialShareButton({
- container: "#share-button",
- componentId: "homepage-hero",
+ container: '#share-button',
+ componentId: 'homepage-hero',
analyticsPlugins: [
new GoogleAnalyticsAdapter(),
new MixpanelAdapter(),
- new CustomAdapter((p) => fetch("/log", { method: "POST", body: JSON.stringify(p) })),
+ new CustomAdapter((p) => fetch('/log', { method: 'POST', body: JSON.stringify(p) })),
],
});
```
@@ -255,7 +252,7 @@ development. Remove or set to `false` in production.
```js
new SocialShareButton({
- container: "#share-button",
+ container: '#share-button',
debug: true,
// → [SocialShareButton Analytics] { version: '1.0', source: 'social-share-button', ... }
});
@@ -271,7 +268,7 @@ instrumentation must be explicitly consented to before activation.
```js
new SocialShareButton({
- container: "#share-button",
+ container: '#share-button',
analytics: false,
});
```
diff --git a/.github/copilot/integrate-social-share-button.prompt.md b/.github/copilot/integrate-social-share-button.prompt.md
index 3b7a24b..ffd571d 100644
--- a/.github/copilot/integrate-social-share-button.prompt.md
+++ b/.github/copilot/integrate-social-share-button.prompt.md
@@ -25,11 +25,11 @@ You are helping a developer integrate the **SocialShareButton** library
The README defines **3 installation methods**. Ask (or infer) which the developer wants:
-| Method | When to use |
-|--------|-------------|
-| **Method 1 — CDN (Recommended)** | Most projects. No build step needed. Load via `
```
@@ -99,8 +102,8 @@ No framework. Just add the CDN tags directly:
**Step 2:** Open an **existing** component that renders on every page — typically `src/components/Header.jsx`, `src/layouts/MainLayout.jsx`, or your root `App.jsx`. Add the snippet below to that component so the share button is consistently available across your app.
```jsx
-import { useEffect, useRef } from "react";
-import { useLocation } from "react-router-dom"; // omit if not using React Router
+import { useEffect, useRef } from 'react';
+import { useLocation } from 'react-router-dom'; // omit if not using React Router
// ⬇️ Replace 'Header' with the name of the component where you want the
// share button to appear — e.g. Navbar, MainLayout, App, etc.
@@ -113,7 +116,7 @@ function Header() {
if (initRef.current || !window.SocialShareButton) return;
shareButtonRef.current = new window.SocialShareButton({
- container: "#share-button",
+ container: '#share-button',
});
initRef.current = true;
@@ -150,13 +153,9 @@ function Header() {
**Step 1:** Add CDN to `app/layout.tsx`:
```tsx
-import Script from "next/script";
+import Script from 'next/script';
-export default function RootLayout({
- children,
-}: {
- children: React.ReactNode;
-}) {
+export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
@@ -180,10 +179,10 @@ export default function RootLayout({
**Step 2:** Because `SocialShareButton` manipulates the DOM, it must run inside a **Client Component** (note the `"use client"` directive at the top). Add the snippet below to an existing component such as `app/components/Header.tsx` or `app/components/Navbar.tsx` — any component already included in your layout.
```tsx
-"use client";
+'use client';
-import { useEffect, useRef } from "react";
-import { usePathname } from "next/navigation";
+import { useEffect, useRef } from 'react';
+import { usePathname } from 'next/navigation';
// ⬇️ Replace 'Header' with the name of the component where you want the
// share button to appear — e.g. Navbar, MainLayout, App, etc.
@@ -195,11 +194,10 @@ export default function Header() {
useEffect(() => {
const initButton = () => {
- if (initRef.current || !window.SocialShareButton || !containerRef.current)
- return;
+ if (initRef.current || !window.SocialShareButton || !containerRef.current) return;
shareButtonRef.current = new window.SocialShareButton({
- container: "#share-button",
+ container: '#share-button',
});
initRef.current = true;
};
@@ -262,7 +260,7 @@ declare global {
**Step 1:** Add CDN to `pages/_document.tsx`:
```tsx
-import { Html, Head, Main, NextScript } from "next/document";
+import { Html, Head, Main, NextScript } from 'next/document';
export default function Document() {
return (
@@ -286,8 +284,8 @@ export default function Document() {
**Step 2:** Open an existing component that is rendered on every page — typically `components/Header.tsx`, `components/Navbar.tsx`, or `components/Layout.tsx`. Since `_document.tsx` loads the script globally, the button is ready to initialize in any of these components.
```tsx
-import { useEffect, useRef } from "react";
-import { useRouter } from "next/router";
+import { useEffect, useRef } from 'react';
+import { useRouter } from 'next/router';
// ⬇️ Replace 'Header' with the name of the component where you want the
// share button to appear — e.g. Navbar, MainLayout, App, etc.
@@ -299,11 +297,10 @@ export default function Header() {
useEffect(() => {
const initButton = () => {
- if (initRef.current || !window.SocialShareButton || !containerRef.current)
- return;
+ if (initRef.current || !window.SocialShareButton || !containerRef.current) return;
shareButtonRef.current = new window.SocialShareButton({
- container: "#share-button",
+ container: '#share-button',
});
initRef.current = true;
};
@@ -384,7 +381,7 @@ declare global {
// Add
to your component's template/HTML first,
// then initialize once the DOM is ready (e.g., in mounted(), ngAfterViewInit(), or useEffect()):
new window.SocialShareButton({
- container: "#share-button",
+ container: '#share-button',
});
```
@@ -395,10 +392,10 @@ new window.SocialShareButton({
Use when the project has a bundler (Webpack, Vite, etc.) and the developer prefers `import` syntax. Works in any framework.
```javascript
-import SocialShareButton from "social-share-button-aossie";
-import "social-share-button-aossie/src/social-share-button.css";
+import SocialShareButton from 'social-share-button-aossie';
+import 'social-share-button-aossie/src/social-share-button.css';
-new SocialShareButton({ container: "#share-button" });
+new SocialShareButton({ container: '#share-button' });
```
> No CDN tags needed — the npm package includes both JS and CSS.
@@ -412,10 +409,10 @@ Only use this when the developer **explicitly** wants a reusable JSX component.
Tell them to copy `src/social-share-button-react.jsx` from the library into their project — **do not create a new file from scratch**.
```jsx
-import { SocialShareButton } from "./components/SocialShareButton";
+import { SocialShareButton } from './components/SocialShareButton';
function App() {
- return ;
+ return ;
}
```
@@ -423,30 +420,30 @@ function App() {
## All constructor options
-| Option | Type | Default | Description |
-| ------------------ | -------------- | ---------------------- | -------------------------------------------------- |
-| `container` | string/Element | — | **Required.** CSS selector or DOM element |
-| `url` | string | `window.location.href` | URL to share |
-| `title` | string | `document.title` | Share title/headline |
-| `description` | string | `''` | Additional description text |
-| `hashtags` | array | `[]` | e.g. `['js', 'webdev']` |
-| `via` | string | `''` | Twitter handle (without @) |
+| Option | Type | Default | Description |
+| ------------------ | -------------- | ---------------------- | ---------------------------------------------------------- |
+| `container` | string/Element | — | **Required.** CSS selector or DOM element |
+| `url` | string | `window.location.href` | URL to share |
+| `title` | string | `document.title` | Share title/headline |
+| `description` | string | `''` | Additional description text |
+| `hashtags` | array | `[]` | e.g. `['js', 'webdev']` |
+| `via` | string | `''` | Twitter handle (without @) |
| `platforms` | array | All platforms | `whatsapp facebook twitter linkedin telegram reddit email` |
-| `buttonText` | string | `'Share'` | Button label text |
-| `buttonStyle` | string | `'default'` | `default` `primary` `compact` `icon-only` |
-| `buttonColor` | string | `''` | Custom button background color |
-| `buttonHoverColor` | string | `''` | Custom button hover color |
-| `customClass` | string | `''` | Additional CSS class for button |
-| `theme` | string | `'dark'` | `dark` or `light` |
-| `modalPosition` | string | `'center'` | Modal position on screen |
-| `showButton` | boolean | `true` | Show/hide the share button |
-| `onShare` | function | `null` | `(platform, url) => void` |
-| `onCopy` | function | `null` | `(url) => void` |
-| `analytics` | boolean | `true` | Set `false` to disable all event emission |
-| `onAnalytics` | function | `null` | `(payload) => void` — direct analytics hook |
-| `analyticsPlugins` | array | `[]` | Adapter instances from `social-share-analytics.js` |
-| `componentId` | string | `null` | Label this instance for analytics tracking |
-| `debug` | boolean | `false` | Log analytics events to console |
+| `buttonText` | string | `'Share'` | Button label text |
+| `buttonStyle` | string | `'default'` | `default` `primary` `compact` `icon-only` |
+| `buttonColor` | string | `''` | Custom button background color |
+| `buttonHoverColor` | string | `''` | Custom button hover color |
+| `customClass` | string | `''` | Additional CSS class for button |
+| `theme` | string | `'dark'` | `dark` or `light` |
+| `modalPosition` | string | `'center'` | Modal position on screen |
+| `showButton` | boolean | `true` | Show/hide the share button |
+| `onShare` | function | `null` | `(platform, url) => void` |
+| `onCopy` | function | `null` | `(url) => void` |
+| `analytics` | boolean | `true` | Set `false` to disable all event emission |
+| `onAnalytics` | function | `null` | `(payload) => void` — direct analytics hook |
+| `analyticsPlugins` | array | `[]` | Adapter instances from `social-share-analytics.js` |
+| `componentId` | string | `null` | Label this instance for analytics tracking |
+| `debug` | boolean | `false` | Log analytics events to console |
---
@@ -469,7 +466,7 @@ const shareButton = useRef(null);
useEffect(() => {
shareButton.current = new window.SocialShareButton({
- container: "#share-button",
+ container: '#share-button',
});
}, []);
@@ -487,25 +484,25 @@ useEffect(() => {
## Troubleshooting
-| Symptom | Cause | Fix |
-|---------|-------|-----|
-| Multiple buttons appearing | Component re-renders creating duplicate instances | Use `useRef` + `initRef` guard (shown in all examples above) |
-| Button not appearing | Script loads after component renders | Add `if (window.SocialShareButton)` null check |
-| Modal not opening | CSS not loaded or ID mismatch | Verify CSS CDN in `
`; match `container: '#share-button'` with `
` |
-| `TypeError: SocialShareButton is not a constructor` | CDN script not loaded yet | Use interval polling (see Next.js examples above) |
-| URL not updating on navigation | Component initialized once, doesn't track routes | Use `updateOptions()` on route change |
+| Symptom | Cause | Fix |
+| --------------------------------------------------- | ------------------------------------------------- | --------------------------------------------------------------------------------------------- |
+| Multiple buttons appearing | Component re-renders creating duplicate instances | Use `useRef` + `initRef` guard (shown in all examples above) |
+| Button not appearing | Script loads after component renders | Add `if (window.SocialShareButton)` null check |
+| Modal not opening | CSS not loaded or ID mismatch | Verify CSS CDN in ``; match `container: '#share-button'` with `
` |
+| `TypeError: SocialShareButton is not a constructor` | CDN script not loaded yet | Use interval polling (see Next.js examples above) |
+| URL not updating on navigation | Component initialized once, doesn't track routes | Use `updateOptions()` on route change |
---
## Common mistakes to prevent
-| ❌ Wrong | ✅ Correct |
-|---------|-----------|
-| Creating `ShareButton.jsx` / `ShareButton.tsx` | Add directly to existing `Header.jsx`, `Navbar.tsx`, etc. |
-| Calling `new SocialShareButton()` inside JSX `return` | Call only inside `useEffect` / lifecycle hook |
-| Not calling `destroy()` on unmount | Always clean up — prevents duplicate modals on re-mount |
-| Mismatched container ID | `container: '#share-button'` must exactly match `
` |
-| Script loads after component renders in Next.js | Use `strategy="beforeInteractive"` **or** poll with `setInterval` |
+| ❌ Wrong | ✅ Correct |
+| ----------------------------------------------------- | ------------------------------------------------------------------------- |
+| Creating `ShareButton.jsx` / `ShareButton.tsx` | Add directly to existing `Header.jsx`, `Navbar.tsx`, etc. |
+| Calling `new SocialShareButton()` inside JSX `return` | Call only inside `useEffect` / lifecycle hook |
+| Not calling `destroy()` on unmount | Always clean up — prevents duplicate modals on re-mount |
+| Mismatched container ID | `container: '#share-button'` must exactly match `
` |
+| Script loads after component renders in Next.js | Use `strategy="beforeInteractive"` **or** poll with `setInterval` |
---
@@ -516,4 +513,3 @@ useEffect(() => {
- Always modify **existing** files — never suggest creating new component files.
- When modifying an existing file, mark additions with `// ADD THIS`.
- Do not add abstractions, wrappers, or extra files beyond what the README shows.
-
diff --git a/README.md b/README.md
index bf8c605..6baa77d 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,6 @@
-
> ⚠️ **IMPORTANT**
>
> All project discussions happens on **[Discord](https://discord.com/channels/1022871757289422898/1479012884209078365)**.
@@ -73,7 +72,7 @@ Lightweight social sharing component for web applications. Zero dependencies, fr
- 🌐 Multiple platforms: WhatsApp, Facebook, X, LinkedIn, Telegram, Reddit, Email
- 🎯 Zero dependencies - pure vanilla JavaScript
-- ⚛️ Framework support: React, Next.js, Vue, Angular, or plain HTML
+- ⚛️ Framework support: React, Next.js, Vue, Angular, Remix, or plain HTML
- 🔄 Auto-detects current URL and page title
- 📱 Fully responsive and mobile-ready
- 🎨 Customizable themes (dark/light)
@@ -86,7 +85,10 @@ Lightweight social sharing component for web applications. Zero dependencies, fr
### Via CDN (Recommended)
```html
-
+
```
@@ -101,11 +103,11 @@ Lightweight social sharing component for web applications. Zero dependencies, fr
No matter which framework you use, integration always follows the same 3 steps:
-| Step | What to do | Where |
-|------|-----------|-------|
-| **1️⃣ Load Library** | Add CSS + JS (CDN links) | Global layout file — `index.html` / `layout.tsx` / `_document.tsx` |
-| **2️⃣ Add Container** | Place `` | The UI component where you want the button to appear |
-| **3️⃣ Initialize** | Call `new SocialShareButton({ container: "#share-button" })` | Inside that component, after the DOM is ready (e.g. `useEffect`, `mounted`, `ngAfterViewInit`) |
+| Step | What to do | Where |
+| -------------------- | ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------- |
+| **1️⃣ Load Library** | Add CSS + JS (CDN links) | Global layout file — `index.html` / `layout.tsx` / `_document.tsx` |
+| **2️⃣ Add Container** | Place `` | The UI component where you want the button to appear |
+| **3️⃣ Initialize** | Call `new SocialShareButton({ container: "#share-button" })` | Inside that component, after the DOM is ready (e.g. `useEffect`, `mounted`, `ngAfterViewInit`) |
> 💡 Pick your framework below for the full copy-paste snippet:
@@ -132,8 +134,8 @@ No matter which framework you use, integration always follows the same 3 steps:
Open an **existing** component that renders on every page — typically `src/components/Header.jsx`, `src/layouts/MainLayout.jsx`, or your root `App.jsx`. Add the snippet below to that component so the share button is consistently available across your app.
```jsx
-import { useEffect, useRef } from "react";
-import { useLocation } from "react-router-dom"; // omit if not using React Router
+import { useEffect, useRef } from 'react';
+import { useLocation } from 'react-router-dom'; // omit if not using React Router
// ⬇️ Replace 'Header' with the name of the component where you want the
// share button to appear — e.g. Navbar, MainLayout, App, etc.
@@ -146,7 +148,7 @@ function Header() {
if (initRef.current || !window.SocialShareButton) return;
shareButtonRef.current = new window.SocialShareButton({
- container: "#share-button",
+ container: '#share-button',
});
initRef.current = true;
@@ -184,13 +186,9 @@ function Header() {
### Step 1: Add CDN to `app/layout.tsx`
```tsx
-import Script from "next/script";
+import Script from 'next/script';
-export default function RootLayout({
- children,
-}: {
- children: React.ReactNode;
-}) {
+export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
@@ -216,10 +214,10 @@ export default function RootLayout({
Because `SocialShareButton` manipulates the DOM, it must run inside a **Client Component** (note the `"use client"` directive at the top). Add the snippet below to an existing component such as `app/components/Header.tsx` or `app/components/Navbar.tsx` — any component already included in your layout.
```tsx
-"use client";
+'use client';
-import { useEffect, useRef } from "react";
-import { usePathname } from "next/navigation";
+import { useEffect, useRef } from 'react';
+import { usePathname } from 'next/navigation';
// ⬇️ Replace 'Header' with the name of the component where you want the
// share button to appear — e.g. Navbar, MainLayout, App, etc.
@@ -231,11 +229,10 @@ export default function Header() {
useEffect(() => {
const initButton = () => {
- if (initRef.current || !window.SocialShareButton || !containerRef.current)
- return;
+ if (initRef.current || !window.SocialShareButton || !containerRef.current) return;
shareButtonRef.current = new window.SocialShareButton({
- container: "#share-button",
+ container: '#share-button',
});
initRef.current = true;
};
@@ -299,7 +296,7 @@ declare global {
### Step 1: Add CDN to `pages/_document.tsx`
```tsx
-import { Html, Head, Main, NextScript } from "next/document";
+import { Html, Head, Main, NextScript } from 'next/document';
export default function Document() {
return (
@@ -325,8 +322,8 @@ export default function Document() {
Open an existing component that is rendered on every page — typically `components/Header.tsx`, `components/Navbar.tsx`, or `components/Layout.tsx`. Since `_document.tsx` loads the script globally, the button is ready to initialize in any of these components.
```tsx
-import { useEffect, useRef } from "react";
-import { useRouter } from "next/router";
+import { useEffect, useRef } from 'react';
+import { useRouter } from 'next/router';
// ⬇️ Replace 'Header' with the name of the component where you want the
// share button to appear — e.g. Navbar, MainLayout, App, etc.
@@ -338,11 +335,10 @@ export default function Header() {
useEffect(() => {
const initButton = () => {
- if (initRef.current || !window.SocialShareButton || !containerRef.current)
- return;
+ if (initRef.current || !window.SocialShareButton || !containerRef.current) return;
shareButtonRef.current = new window.SocialShareButton({
- container: "#share-button",
+ container: '#share-button',
});
initRef.current = true;
};
@@ -426,12 +422,59 @@ Open your root or layout component (e.g., `App.vue`, `app.component.html`, or `A
// Add to your component's template/HTML first,
// then initialize once the DOM is ready (e.g., in mounted(), ngAfterViewInit(), or useEffect()):
new window.SocialShareButton({
- container: "#share-button",
+ container: '#share-button',
});
```
+
+🎸 Remix
+
+### Step 1: Load CSS via `links` export and JS via CDN script in `app/root.tsx`
+
+```tsx
+import type { LinksFunction } from '@remix-run/node';
+
+export const links: LinksFunction = () => [
+ {
+ rel: 'stylesheet',
+ href: 'https://cdn.jsdelivr.net/gh/AOSSIE-Org/SocialShareButton@v1.0.3/src/social-share-button.css',
+ },
+];
+```
+
+Add the CDN `
+```
+
+### Step 2: Copy `src/social-share-button-remix.jsx` into your project and use it in a route
+
+```tsx
+// app/routes/_index.tsx
+import SocialShareButton from '~/components/social-share-button-remix';
+
+export default function Index() {
+ return (
+
+ );
+}
+```
+
+> **Note:** Remix is SSR-first. The component wraps all browser-API calls inside
+> `useEffect` with an `typeof window !== 'undefined'` guard so it renders safely
+> on the server and only initialises `SocialShareButton` in the browser.
+
+
+
---
## Configuration
@@ -440,13 +483,13 @@ new window.SocialShareButton({
```jsx
new SocialShareButton({
- container: "#share-button", // Required: CSS selector or DOM element
- url: "https://example.com", // Optional: defaults to window.location.href
- title: "Custom Title", // Optional: defaults to document.title
- buttonText: "Share", // Optional: button label text
- buttonStyle: "primary", // default | primary | compact | icon-only
- theme: "dark", // dark | light
- platforms: ["twitter", "linkedin"], // Optional: defaults to all platforms
+ container: '#share-button', // Required: CSS selector or DOM element
+ url: 'https://example.com', // Optional: defaults to window.location.href
+ title: 'Custom Title', // Optional: defaults to document.title
+ buttonText: 'Share', // Optional: button label text
+ buttonStyle: 'primary', // default | primary | compact | icon-only
+ theme: 'dark', // dark | light
+ platforms: ['twitter', 'linkedin'], // Optional: defaults to all platforms
});
```
@@ -481,12 +524,12 @@ Control the text that appears when users share to social platforms:
```jsx
new SocialShareButton({
- container: "#share-button",
- url: "https://myproject.com",
- title: "Check out my awesome project!", // Main title/headline
- description: "An amazing tool for developers", // Additional description
- hashtags: ["javascript", "webdev", "opensource"], // Hashtags included in posts
- via: "MyProjectHandle", // Your Twitter handle
+ container: '#share-button',
+ url: 'https://myproject.com',
+ title: 'Check out my awesome project!', // Main title/headline
+ description: 'An amazing tool for developers', // Additional description
+ hashtags: ['javascript', 'webdev', 'opensource'], // Hashtags included in posts
+ via: 'MyProjectHandle', // Your Twitter handle
});
```
@@ -506,8 +549,8 @@ new SocialShareButton({
```jsx
new SocialShareButton({
- container: "#share-button",
- buttonStyle: "primary", // or 'default', 'compact', 'icon-only'
+ container: '#share-button',
+ buttonStyle: 'primary', // or 'default', 'compact', 'icon-only'
});
```
@@ -517,9 +560,9 @@ Pass `buttonColor` and `buttonHoverColor` to match your project's color scheme:
```jsx
new SocialShareButton({
- container: "#share-button",
- buttonColor: "#ff6b6b", // Button background color
- buttonHoverColor: "#ff5252", // Hover state color
+ container: '#share-button',
+ buttonColor: '#ff6b6b', // Button background color
+ buttonHoverColor: '#ff5252', // Hover state color
});
```
@@ -529,9 +572,9 @@ For more complex styling, use a custom CSS class:
```jsx
new SocialShareButton({
- container: "#share-button",
- buttonStyle: "primary",
- customClass: "my-custom-button",
+ container: '#share-button',
+ buttonStyle: 'primary',
+ customClass: 'my-custom-button',
});
```
@@ -555,23 +598,23 @@ Then in your CSS file:
```jsx
// Material Design Red
new SocialShareButton({
- container: "#share-button",
- buttonColor: "#f44336",
- buttonHoverColor: "#da190b",
+ container: '#share-button',
+ buttonColor: '#f44336',
+ buttonHoverColor: '#da190b',
});
// Tailwind Blue
new SocialShareButton({
- container: "#share-button",
- buttonColor: "#3b82f6",
- buttonHoverColor: "#2563eb",
+ container: '#share-button',
+ buttonColor: '#3b82f6',
+ buttonHoverColor: '#2563eb',
});
// Custom Brand Color
new SocialShareButton({
- container: "#share-button",
- buttonColor: "#your-brand-color",
- buttonHoverColor: "#your-brand-color-dark",
+ container: '#share-button',
+ buttonColor: '#your-brand-color',
+ buttonHoverColor: '#your-brand-color-dark',
});
```
@@ -588,12 +631,12 @@ new SocialShareButton({
```jsx
new SocialShareButton({
- container: "#share-button",
+ container: '#share-button',
onShare: (platform, url) => {
console.log(`Shared on ${platform}: ${url}`);
},
onCopy: (url) => {
- console.log("Link copied:", url);
+ console.log('Link copied:', url);
},
});
```
@@ -605,11 +648,11 @@ new SocialShareButton({
### Using npm Package
```javascript
-import SocialShareButton from "social-share-button-aossie";
-import "social-share-button-aossie/src/social-share-button.css";
+import SocialShareButton from 'social-share-button-aossie';
+import 'social-share-button-aossie/src/social-share-button.css';
new SocialShareButton({
- container: "#share-button",
+ container: '#share-button',
});
```
@@ -618,10 +661,10 @@ new SocialShareButton({
If you want a reusable React component, copy `src/social-share-button-react.jsx` to your project:
```jsx
-import { SocialShareButton } from "./components/SocialShareButton";
+import { SocialShareButton } from './components/SocialShareButton';
function App() {
- return ;
+ return ;
}
```
@@ -640,7 +683,7 @@ const shareButton = useRef(null);
useEffect(() => {
shareButton.current = new window.SocialShareButton({
- container: "#share-button",
+ container: '#share-button',
});
}, []);
@@ -676,7 +719,7 @@ useEffect(() => {
```jsx
if (window.SocialShareButton) {
- new window.SocialShareButton({ container: "#share-button" });
+ new window.SocialShareButton({ container: '#share-button' });
}
```
@@ -729,14 +772,14 @@ if (window.SocialShareButton) {
```jsx
// Professional networks only
new SocialShareButton({
- container: "#share-button",
- platforms: ["linkedin", "twitter", "email"],
+ container: '#share-button',
+ platforms: ['linkedin', 'twitter', 'email'],
});
// Messaging apps only
new SocialShareButton({
- container: "#share-button",
- platforms: ["whatsapp", "telegram"],
+ container: '#share-button',
+ platforms: ['whatsapp', 'telegram'],
});
```
@@ -744,9 +787,9 @@ new SocialShareButton({
```jsx
new SocialShareButton({
- container: "#share-button",
- buttonStyle: "icon-only",
- theme: "light",
+ container: '#share-button',
+ buttonStyle: 'icon-only',
+ theme: 'light',
});
```
diff --git a/docs/client-guide.md b/docs/client-guide.md
index 6b49350..da7d57d 100644
--- a/docs/client-guide.md
+++ b/docs/client-guide.md
@@ -8,12 +8,12 @@
Your audience is already sharing. Give them a button worth clicking.
-| What you get | What you skip |
-|---|---|
-| One-line install | Backend servers |
+| What you get | What you skip |
+| ---------------------- | --------------------------- |
+| One-line install | Backend servers |
| Works on any framework | Tracking or data collection |
-| Fully customizable | Lock-in or licensing fees |
-| Lightweight & fast | Build step (CDN option) |
+| Fully customizable | Lock-in or licensing fees |
+| Lightweight & fast | Build step (CDN option) |
---
diff --git a/eslint.config.js b/eslint.config.js
index 701e191..9b85c82 100644
--- a/eslint.config.js
+++ b/eslint.config.js
@@ -1,13 +1,13 @@
-import js from "@eslint/js";
-import globals from "globals";
+import js from '@eslint/js';
+import globals from 'globals';
export default [
js.configs.recommended,
{
- files: ["src/**/*.{js,jsx}"],
+ files: ['src/**/*.{js,jsx}'],
languageOptions: {
- ecmaVersion: "latest",
- sourceType: "module",
+ ecmaVersion: 'latest',
+ sourceType: 'module',
parserOptions: {
ecmaFeatures: {
jsx: true,
@@ -20,15 +20,15 @@ export default [
},
},
rules: {
- "no-console": "error",
- "no-unused-vars": ["warn", { "caughtErrorsIgnorePattern": "^_" }],
- "semi": ["error", "always"],
+ 'no-console': 'error',
+ 'no-unused-vars': ['warn', { caughtErrorsIgnorePattern: '^_' }],
+ semi: ['error', 'always'],
},
},
{
- files: ["eslint.config.js", "**/*.config.js"],
+ files: ['eslint.config.js', '**/*.config.js'],
languageOptions: {
- sourceType: "module",
+ sourceType: 'module',
globals: {
...globals.node,
},
diff --git a/index.html b/index.html
index 90db0da..ae4d812 100644
--- a/index.html
+++ b/index.html
@@ -397,7 +397,7 @@
-
+
-import SocialShareButton from 'social-share-button';
+import SocialShareButton from 'social-share-button';
function App() {
return (
@@ -438,6 +438,59 @@
⚛️ React Integration
+
+
+
🎸 Remix Integration
+
+ Remix is an SSR-first React framework — all browser APIs must live inside
+ useEffect.
+ Copy src/social-share-button-remix.jsx
+ into your project and follow the steps below.
+
+
+
Step 1 — Load the CSS & JS in app/root.tsx
+
+
+
+
+// app/root.tsx
+import type { LinksFunction } from "@remix-run/node";
+
+export const links: LinksFunction = () => [
+ {
+ rel: "stylesheet",
+ href: "https://cdn.jsdelivr.net/npm/social-share-button/dist/social-share-button.css",
+ },
+];
+
+// In the <head> of your root component, add:
+// <Scripts /> loads the Remix client bundle.
+// Place the CDN <script> just before </body>:
+// <script src="https://cdn.jsdelivr.net/npm/social-share-button/dist/social-share-button.js"></script>
+