Skip to content
WingoUI
ComponentsTemplatesDocsPricingAI agentsBlogChangelog
Components
Buttons & Actions
ButtonButton GroupCopy ButtonDelete ButtonTheme ToggleToggleToggle Group
Inputs
Avatar UploadCalendarCheckboxColor PickerComboboxCron PickerCurrency InputDate PickerDate Range PickerDate Time PickerDuration PickerEmail InputFile UploadFilter BuilderInputInput GroupListboxMasked InputMention InputMonth PickerMulti SelectNumber InputOTP InputPassword InputPhone InputRadio GroupRatingSearch InputSegmented ControlSelectSignature PadSliderSwitchTag InputTextareaTime PickerTimezone Select
Forms
Address InputCSV ImportFieldForm WizardInline EditInvoice line itemsRich Text EditorSchema Builder
Navigation
Back To TopBounce SidebarBreadcrumbCommand MenuGlobal SearchGooey NavHook SidebarNav MenuNav TabsPaginationProximity SidebarScroll ProgressSidebarStepsTable Of ContentsTabsTopbarUser MenuWorkspace Switcher
Overlays
Alert DialogContext MenuDialogDrawerDropdown MenuFamily DrawerHover CardPopoverShare DialogSheetShortcuts DialogTooltipTour
Feedback
AlertBannerCookie ConsentEmoji ReactionEmpty StateNotification BellNotification CenterProgressRoute ProgressSetup ChecklistSkeletonSpinnerToast
Data Display
Approval FlowAvatarBadgeCalendar ViewCode BlockComment ThreadContact cardCountdownDescription ListDiff ViewerFile ListFile managerFolderGanttJSON ViewerKbdLog ViewerMarkdownPresenceSchedulerTagTimelineTree View
Tables & Lists
Audit LogData TableDeal PipelineEditable GridKanbanListMembers tablePermissions MatrixTableTask ListVirtual List
Charts & Stats
Animated CounterArea chartBar chartDonut chartFunnel chartGaugeGitHub ActivityHeatmap calendarLeaderboardLine chartRadar chartRadial barSparklineStat CardTrackerTrend badge
Layout
AccordionApp ShellCardCollapsibleDetail LayoutEntity HeaderPage HeaderScroll AreaSeparatorSettings LayoutSplit ViewToolbar
Media
Audio PlayerCarouselCSV ViewerDOCX EditorDOCX ViewerExcel ViewerFile SystemImage compareImage CropperImage LightboxLocation MapPDF ViewerPowerPoint ViewerQR CodeStep PlayerVideo Player
AI Kit
Agent Status CardChat MessageChat ThreadConversation ListFluid OrbGrid RevealMatrix OrbModel PickerPrompt InputReasoning IndicatorRule BuilderSuggestion ChipsTool Call TimelineUsage MeterVoice InputWorkflow Canvas
Text & Effects
Background PatternGravity LettersMarqueeText AnimateText Rotate
Mobile
Action SheetBottom Tab BarFABHaptic ButtonHero HeaderInstall PromptLarge Title HeaderNotification BannerOnboarding CarouselPicker WheelPull To RefreshSlide To ConfirmSticky CTA BarSwipe DeckSwipeable Tabs
Commerce
Cart drawerCategory pickerCheckout stepsCoupon inputFavorite buttonFilter panelListing cardListing gridOrder trackerPricePrice rangePricing tableProduct galleryQuantity stepperReviewsSeller card
Marketing Sections
App Download SectionBlog Cards SectionCTA SectionFAQ SectionFeature GridFeature ShowcaseHero SectionIntegrations SectionLogo CloudMarketing FooterMarketing HeaderMarketing SectionNewsletter SectionPricing SectionStats SectionSteps SectionTeam SectionTestimonials SectionTimeline SectionVideo Section
Blocks
Admin Dashboard PageAdmin ShellAI Chat PageAPI Keys PageAutomation Builder PageCheckout PageCRM Contact PageCRM Pipeline PageError PagesInbox PageInvoice PageKPI DashboardListing Detail PageLogin PageMarketplace Home PageMarketplace Search PageMarketplace ShellMobile App HomeOnboarding FlowPost Listing WizardPricing PageRegister PageSettings PageUsers Admin Page
Templates
About PageAcademy PageAccessibility PageAffiliate PageAI Product PageBlog PageBlog Post PageBug Bounty PageCareers PageChangelog PageCommunity PageCompare PageContact PageCustomer Story PageCustomers PageDemo Booking PageDevelopers PageDocs Home PageDownload PageEnterprise PageEvents PageExperts PageFAQ PageFeature PageGlossary PageHelp Article PageHelp Center PageImpact PageIntegration Detail PageIntegrations PageJob Detail PageLanding PageLaunch PageLegal PageManifesto PagePress PageProduct Tour PagePromo PageReferral PageResearch Report PageRoadmap PageROI Calculator PageSecurity PageSolutions PageStartups PageStatus PageSwitch PageTemplate Gallery PageWaitlist PageYear in Review Page
Hooks & Utilities
AI ChatChart kitCommerceDate utilsFile exportFile typesFiltersForm validationHapticsInvoicingMotion presetsNavigationNumber formatRelative timeRomanian locationsSpreadsheetText matchTonesUIProvideruseClipboarduseConsentuseControllableStateuseCooldownuseDebounceuseKeyboardInsetuseLocaleuseLongPressuseMediaControlsuseMediaQueryuseOverflowItemsusePersistedStateuseScrollEdgesuseScrollStateuseSelectionuseShortcutuseStickToBottom
GalleryTheme

Overlays

Share Dialog

Overlays

Share Dialog React block for Tailwind CSS v4

PopoverSheet
Live props
Content
resourceName
description
link
domain
Behavior
defaultInviteRole
defaultAccess
defaultLinkRole
showMessage
State
readOnly
defaultOpen
Layout
size
responsive
Code
import { ShareDialog } from "@/components/blocks/share-dialog"

<ShareDialog />
  1. Home
  2. Components
  3. Overlays
  4. Share Dialog
Pro

Share Dialog React block for Tailwind CSS v4

v1.0.0·Added in 1.10.0

The Share dialog of a collaborative app: invite people by email with a role, manage who has access, set link access and copy the link.

Share opens the dialog with the cursor in the email field (a bottom sheet below 768px). Type or paste addresses: Enter, a comma or a space turns each into a chip, Backspace brings the last one back as text, and people from suggestions show their name and photo. A bad address or someone who already has access stays as a red chip with the reason under the field. Pick the role, add an optional message (mod+Enter sends) and press Invite: the button loads, then the new people slide into the list as Pending with a Resend link and a toast confirms. A failed invite keeps the chips and shows the error inline. In the list change anyone's role from their picker, or open the ... menu to resend, make them the owner or remove access after a confirmation; the owner's row is fixed. Under General access switch between Restricted, Anyone at the domain and Anyone with the link, and pick the link role. Copy link swaps its label to Link copied and shows a toast; Done or Escape closes. Read-only viewers see the list and copy the link but change nothing.

Share Dialog is a Pro React block in the React overlay components category, written in TypeScript for React 19 and Tailwind CSS v4. It installs as source with npx wingo-ui@latest add share-dialog, together with Alert Dialog, Avatar, Badge, Button, Copy Button and 9 more and the npm packages motion and lucide-react.

Add to a project

Requirements: React 19 and Tailwind CSS v4, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup

npx wingo-ui@latest add share-dialog

Pro item: the CLI needs a Pro account. See plans

Usage

Import ShareDialog from @/components/blocks/share-dialog.

"use client"

import { ShareDialog } from "@/components/blocks/share-dialog"
import type { ShareDialogPerson } from "@/components/blocks/share-dialog-data"

export function ShareDoc({ docId, people }: { docId: string; people: ShareDialogPerson[] }) {
  return (
    <ShareDialog
      resourceName="Q4 Launch Plan"
      link={`https://docs.acme.com/d/${docId}`}
      defaultPeople={people}
      onInvite={async (emails, role, message) => {
        const res = await fetch(`/api/docs/${docId}/invites`, { method: "POST", body: JSON.stringify({ emails, role, message }) })
        if (!res.ok) throw new Error("The invites were not sent. Try again.")
      }}
      onRoleChange={(personId, role) =>
        fetch(`/api/docs/${docId}/members/${personId}`, { method: "PATCH", body: JSON.stringify({ role }) })
      }
      onRemove={(personId) => fetch(`/api/docs/${docId}/members/${personId}`, { method: "DELETE" })}
      onAccessChange={(access) => fetch(`/api/docs/${docId}`, { method: "PATCH", body: JSON.stringify({ access }) })}
    />
  )
}

Props

  • resourceNamedefault "Q4 Launch Plan"
    string

    The file, doc or project being shared; it fills the title (Share "Q4 Launch Plan") and the remove confirmation.

  • title
    ReactNode | ((name: string) => ReactNode)

    The dialog title, or a function of resourceName. Default Share "name" from labels.title.

  • descriptiondefault ""
    ReactNode

    A line under the title, e.g. who can see the file today.

  • people
    ShareDialogPerson[]

    Controlled list of people with access: { id, name, email, avatar?, role, owner?, pending? }. Pair it with onPeopleChange, which fires after invites, role changes, removals and a new owner.

  • defaultPeopledefault "SHARE_DIALOG_PEOPLE"
    ShareDialogPerson[]

    Starting list while uncontrolled; the sample is an owner, an editor, a commenter and a pending invite.

  • onPeopleChange
    (people: ShareDialogPerson[]) => void

    The list after every change the dialog makes.

  • rolesdefault "DEFAULT_SHARE_DIALOG_ROLES"
    ShareDialogRole[]

    The role options { value, label, description? } for invites, rows and the link. Default Viewer, Commenter and Editor.

  • suggestionsdefault "[]"
    ShareDialogPerson[]

    People the email field suggests while typing (name, address and photo); invited ones keep their name and photo in the list.

  • linkdefault "https://docs.acme.com/d/q4-launch-plan"
    string

    The address Copy link puts on the clipboard.

  • domaindefault "acme.com"
    string

    The organization domain for the "Anyone at acme.com" access option. Empty hides that option.

  • labels
    Partial<ShareDialogLabels>

    Merged over DEFAULT_SHARE_DIALOG_LABELS. Every string: the trigger, title, placeholder, roles, toasts, confirmations, access options and buttons. Functions take the name or count.

  • trigger
    ReactNode

    The element that opens the dialog, rendered with asChild. Default a soft Share button; null renders none, for a dialog driven by open.

  • defaultInviteRoledefault "viewer"
    string

    The role preselected for new invites.

  • defaultAccessdefault "restricted"
    "restricted" | "domain" | "anyone"

    Starting general access while uncontrolled: only people with access, anyone at the domain, or anyone with the link.

  • access
    "restricted" | "domain" | "anyone"

    Controlled general access; pair it with onAccessChange.

  • onAccessChange
    (access: ShareDialogAccess) => void

    A new general access was picked.

  • defaultLinkRoledefault "viewer"
    string

    Starting role for people who open the link, shown while access is not restricted.

  • linkRole
    string

    Controlled link role; pair it with onLinkRoleChange.

  • onLinkRoleChange
    (role: string) => void

    A new link role was picked.

  • onInvite
    (emails: string[], role: string, message?: string) => void | Promise<unknown>

    Invite was pressed with valid, new addresses. Return a promise to show the loading state; a rejection keeps the chips and shows its message under the field.

  • onRoleChange
    (personId: string, role: string) => void | Promise<unknown>

    A row's role changed. It updates at once; a rejection puts the old role back with an error toast.

  • onRemove
    (personId: string) => void | Promise<unknown>

    Remove access was confirmed. A rejection shows in the confirmation and keeps the row.

  • onTransferOwnership
    (personId: string) => void | Promise<unknown>

    Adds Make owner to each row's menu; after the confirmation that person becomes the owner and the old owner an editor.

  • onResend
    (personId: string) => void | Promise<unknown>

    Resend on a pending invite.

  • showMessagedefault true
    boolean

    A message field slides in under the invite row once there are addresses.

  • readOnlydefault false
    boolean

    For viewers: no invite row, roles and access as plain text, no row menus. Copy link still works.

  • defaultOpendefault false
    boolean

    Opens on mount while uncontrolled.

  • open
    boolean

    Controlled open state; pair it with onOpenChange. The dialog stays open while an invite is sending.

  • onOpenChange
    (open: boolean) => void

    Done, the close button, Escape, an outside click or the sheet drag.

  • sizedefault "md"
    "md" | "lg"

    Dialog width: md 520px, lg 720px. Below 768px it is a bottom sheet either way.

  • responsivedefault true
    boolean

    A bottom sheet below 768px, with the role pickers and row menus as sheets too.

  • className
    string

    Classes for the dialog content. Other props go to the dialog content too (onOpenAutoFocus, aria-*).

  • classNames
    Partial<Record<ShareDialogSlot, string>>

    Classes for overlay, content, header, body, footer, invite, people, person, access, copy and done.

Parts

  • DEFAULT_SHARE_DIALOG_LABELS

    constant

    The English strings; spread it and override what you need for another language.

  • DEFAULT_SHARE_DIALOG_ROLES

    constant

    Viewer, Commenter and Editor with a short description each.

  • SHARE_DIALOG_PEOPLE

    constant

    Sample people with access (share-dialog-data.ts): an owner, an editor, a commenter and a pending invite.

  • SHARE_DIALOG_SUGGESTIONS

    constant

    Sample teammates for the suggestions prop.

  • ShareDialogPerson

    type

    { id, name, email, avatar?, role, owner?, pending? }: one row of People with access.

  • ShareDialogRole

    type

    { value, label, description? }: one role option.

  • ShareDialogAccess

    type

    "restricted" | "domain" | "anyone".

  • ShareDialogLabels

    type

    The shape of labels.

Examples

Open

Shared with four people

An owner, an editor, a commenter and a pending invite; suggestions, Make owner and Remove access with a confirmation.

Open

Anyone with the link

defaultAccess="anyone" with commenters by link, opened from a custom trigger.

Open

Invite error

The first invite fails: the chips stay and the message shows under the field. Try again and it goes through.

Open

Read-only viewer

readOnly: the list and the access as text, Copy link still works.

Open

Large, no message

size="lg" with a description, editors by default and showMessage={false}.

Dependencies

motionlucide-reactalert-dialogavatarbadgebuttoncopy-buttondialogdropdown-menuemail-inputselecttextareatoastuse-controllable-statemotionui-config

Files

  • components/blocks/share-dialog.tsx
  • components/blocks/share-dialog-data.ts

FAQ

Is the React Share Dialog block free?

The preview, props and docs are free; copying the source needs a Pro plan. See plans.

How do I install Share Dialog?

Run npx wingo-ui@latest add share-dialog. It also adds the Wingo UI items it builds on (Alert Dialog, Avatar, Badge, Button, Copy Button and 9 more) and the npm packages motion and lucide-react. With shadcn, add the @wingo-ui registry with your API key, then run npx shadcn@latest add @wingo-ui/share-dialog.

How does Share Dialog behave on phones?

A bottom sheet below 768px, with the role pickers and row menus as sheets too. The responsive prop controls this and is on by default.

See also

Members tablePermissions MatrixUsers Admin PageDialogTag InputCopy Button

More React overlay components

SheetShortcuts DialogTourTooltipDropdown MenuAlert Dialog
All 13 React overlay components
PreviousPopoverNext Sheet