Share Dialog

Boite de dialogue modale pour partager une page sur les plateformes sociales avec une action de copie du lien et des libelles remplacables. Installez Share Dialog depuis le registre VLLNT UI avec la CLI shadcn.

Signaler un bug

Boite de dialogue modale pour partager une page sur les plateformes sociales avec une action de copie du lien et des libelles remplacables. Fait partie de la famille overlay dans VLLNT UI, il est publie comme entree de registre lisible par machine — copiez la source directement dans votre application avec la CLI shadcn et possedez-la, sans dependance d'execution a une bibliotheque de composants.

Apercu

Basculez entre clair et sombre pour inspecter l'apercu Storybook integre.

Installation

Ajoutez Share Dialog a votre projet avec la CLI shadcn. La source arrive dans votre code, prete a etre adaptee :

pnpm dlx shadcn@latest add https://ui.vllnt.ai/r/share-dialog.json

Source

"use client"; import * as React from "react"; import { cn } from "../../lib/utils"; import { useCopyToClipboard } from "../copy-button/copy-button"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "../dialog/dialog"; export type SharePlatform = { buildUrl: (pageUrl: string, pageTitle: string) => string; key: string; label: string; }; export type ShareDialogLabels = { copied: string; copyLink: string; }; export type ShareDialogProps = { /** Function to build the URL for copying (should add UTM params) */ buildCopyUrl?: (url: string) => string; description?: string; labels?: ShareDialogLabels; onCopy?: () => void; onOpenChange?: (open: boolean) => void; onShare?: (platformKey: string) => void; open?: boolean; platforms: SharePlatform[]; title?: string; }; function PlatformButton({ onClick, platform, }: { onClick: (key: string) => void; platform: SharePlatform; }) { const handleSelectPlatform = () => { onClick(platform.key); }; return ( <button className={cn( "w-full rounded-md border border-border bg-background px-4 py-3", "text-sm font-medium text-foreground", "transition-colors duration-150", "hover:bg-accent hover:text-accent-foreground", "focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", )} onClick={handleSelectPlatform} type="button" > {platform.label} </button> ); } function CopyButton({ buildCopyUrl, labels, onCopy, }: { buildCopyUrl?: (url: string) => string; labels: ShareDialogLabels; onCopy?: () => void; }) { const { copied, copy } = useCopyToClipboard(); const handleCopy = React.useCallback(async () => { const url = buildCopyUrl ? buildCopyUrl(window.location.href) : window.location.href; const text = `${document.title} - ${url}`; if (await copy(text)) { onCopy?.(); } }, [buildCopyUrl, copy, onCopy]); return ( <button className={cn( "col-span-2 w-full rounded-md border px-4 py-3", "text-sm font-medium", "transition-colors duration-150", "focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", copied ? "border-green-500 bg-green-500/10 text-green-600 dark:text-green-400" : "border-border bg-background text-foreground hover:bg-accent hover:text-accent-foreground", )} onClick={handleCopy} type="button" > {copied ? labels.copied : labels.copyLink} </button> ); } const defaultLabels: ShareDialogLabels = { copied: "Copied!", copyLink: "Copy link", }; export function ShareDialog({ buildCopyUrl, description, labels = defaultLabels, onCopy, onOpenChange, onShare, open, platforms, title = "Share", }: ShareDialogProps) { const handlePlatformClick = React.useCallback( (key: string) => { const platform = platforms.find((p) => p.key === key); if (platform) { const url = platform.buildUrl(window.location.href, document.title); window.open(url, "_blank", "noopener,noreferrer"); onShare?.(key); onOpenChange?.(false); } }, [platforms, onShare, onOpenChange], ); return ( <Dialog onOpenChange={onOpenChange} open={open}> <DialogContent className="sm:max-w-sm"> <DialogHeader> <DialogTitle>{title}</DialogTitle> {description ? ( <DialogDescription>{description}</DialogDescription> ) : null} </DialogHeader> <div className="grid grid-cols-2 gap-2"> {platforms.map((platform) => ( <PlatformButton key={platform.key} onClick={handlePlatformClick} platform={platform} /> ))} <CopyButton buildCopyUrl={buildCopyUrl} labels={labels} onCopy={onCopy} /> </div> </DialogContent> </Dialog> ); }

Stories

Explorez chaque variante et etat dans le Storybook interactif :

Apercu

Basculez entre clair et sombre pour inspecter l'apercu Storybook integre.

Dependances

  • @vllnt/ui@^0.3.0