ShareModal

A ShareModal is build with a design system components and guidelines that enables users to share a link or content effortlessly. It provides options to share via social media, copy the link, or send via email, ensuring a seamless and accessible sharing experience.

Quick Start

Installation
npm install @adaptavant/share-modal
Import
import { ShareModal } from '@adaptavant/share-modal';

Default

The Share Modal takes a link, title, description (primary and secondary), and optionLabels for built‑in actions like Copy Link, Email, Facebook, Messenger, and WhatsApp. It also connects onClose and closeButtonProps with an explicit label to improve screen‑reader clarity.
The ShareModal is responsive: from tablet breakpoint it converts to a bottom sheet, displaying the link as a QR code with Copy and native Share button.

Note:
headingImageProps has been deprecate as of 1.1.0, please use avatarProps

const [openModal, setOpenModal] = React.useState(false);

const closeModal = () => {
  setOpenModal(false);
};

return (
  <React.Fragment>
    <Button
      iconStart={ShareIcon}
      label="Share"
      onClick={() => {
        setOpenModal(true);
      }}
      size="standard"
      variant="neutralSecondary"
    >
      Share
    </Button>
    <ShareModal
      className="share-modal"
      closeButtonProps={{
        label: "Close share modal",
        onClick: closeModal,
      }}
      link="https://earth.anywhere.co/widgets"
      onClose={closeModal}
      open={openModal}
      translations={{
        description: {
          primary: "Earth Design System",
          secondary:
            "That’s here. An evolving digital ecosystem that we strive to care.",
        },
        optionLabels: {
          copyLabel: "Copy Link",
          emailLabel: "Email",
          facebookLabel: "Facebook",
          messengerLabel: "Messenger",
          whatsappLabel: "Whatsapp",
        },
        title: "Share this page",
      }}
    />
  </React.Fragment>
);

Translations

Use the translations prop to localize the modal’s title and descriptions, and optionLabels to translate built‑in action buttons (Copy Link, Email, Facebook, Messenger, WhatsApp).

Note:
translations.content has been deprecate as of 1.1.0, please use translations.description.primary

const [openModal, setOpenModal] = React.useState(false);

const closeModal = () => {
  setOpenModal(false);
};

return (
  <React.Fragment>
    <Button
      iconStart={ShareIcon}
      label="Compartir"
      onClick={() => {
        setOpenModal(true);
      }}
      size="standard"
      variant="neutralSecondary"
    >
      Compartir
    </Button>
    <ShareModal
      className="share-modal"
      closeButtonProps={{
        label: "Cerrar modal de compartir",
        onClick: closeModal,
      }}
      link="https://earth.anywhere.co/widgets"
      onClose={closeModal}
      open={openModal}
      translations={{
        description: {
          primary: "Sistema de Diseño Earth",
          secondary:
            "Aquí está. Un ecosistema digital en evolución que nos esforzamos por cuidar.",
        },
        optionLabels: {
          copyLabel: "Copiar enlace",
          emailLabel: "Correo",
          facebookLabel: "Facebook",
          messengerLabel: "Messenger",
          whatsappLabel: "WhatsApp",
        },
        title: "Compartir esta página",
      }}
    />
  </React.Fragment>
);

With Custom Options

Use the shareOptions prop to include your own sharing buttons. Each option takes an icon, label, and onClick action—for example, opening a Twitter or LinkedIn share.

const [openModal, setOpenModal] = React.useState(false);

const closeModal = () => {
  setOpenModal(false);
};

return (
  <React.Fragment>
    <Button
      iconStart={ShareIcon}
      label="Share"
      onClick={() => {
        setOpenModal(true);
      }}
      size="standard"
      variant="neutralSecondary"
    >
      Share
    </Button>
    <ShareModal
      className="share-modal"
      closeButtonProps={{
        label: "Modal Close Button",
        onClick: closeModal,
      }}
      link="https://go.setmore.com"
      onClose={closeModal}
      open={openModal}
      shareOptions={[
        {
          icon: TwitterIcon,
          id: "share-via-twitter",
          label: "Twitter",
          onClick: () => {
            window.open(
              "https://twitter.com/intent/tweet?url=somelink",
              "_blank"
            );
          },
        },
        {
          icon: LinkedinIcon,
          id: "share-via-linkedin",
          label: "Linkedin",
          onClick: () => {
            window.open(
              "https://www.linkedin.com/sharing/share-offsite/?url=somelink",
              "_blank"
            );
          },
        },
      ]}
      translations={{
        description: { primary: "Share this page with" },
        optionLabels: {
          copyLabel: "Copy Link",
          emailLabel: "Email",
        },
        title: "Share this page",
      }}
    />
  </React.Fragment>
);

API Reference

ShareModal

PropsTypeDescriptionDefault
translationsobjectTranslations object for the ShareModal. title key is required. description and optionLabels are optional. If optionLabels are undefined then shareOption should be provided._
translations.titlestringtitle key is required prop_
translations.descriptionobjectdescription key is optional prop_
translations.contentstring

⚠️ Deprecated, use translations.description instead.

_
translations
.description
.primary
stringPrimary text inside the share modal._
translations
.description
.secondary
stringSecondary text inside the share modal._
translations.optionLabelscopyLabel | emailLabel | facebookLabel | messengerLabel | whatsappLabelAll keys in optionLabels are optional, a default option will be rendered only if a corresponding key is provided._
onClosefunctionCallback triggered on closing the share modal and will activate upon pressing "Esc" or clicking on the overlay._
onEscPress?(event: KeyboardEvent) => voidCallback fired when "Esc" key is pressed along with onClose._
onOverlayClick?functionCallback fired when the overlay is clicked along with onClose_
closeOnEsc?booleanIf set to false, the share modal will not close when the Esc key is pressed, and the Esc keydown event along with the onClose callback won't be attached. Similarly, onEscPress will have no effect.true
openbooleanWhen set to true, the dialog will be mounted to DOM._
size?numberThe size of the Modal 'Dialog' box in pixels.640
togglePoint?numberThe screen width at which the modal should switch to a mobile-friendly layout. Deprecated with backwards compatibility ⚠️ (The logic will be handled internally in future)768
mobileFriendly?booleanIndicates if the share modal should be render Sheet in responsive view.true
closeOnOverlayClick?booleanIf set to false, the share modal will not close when the overlay is clicked, and the onClose callback won’t be attached. Similarly, onOverlayClick will have no effect.true
avatarProps?objectTo render image before the heading, contains label and src_
avatarProps.labelstringAria label content for the image added before the heading._
avatarProps.srcstringUrl content for the image added before the heading._

headingImageProps?

object

⚠️ Deprecated, use avatarProps instead.

To render image before the heading, contains label and src

_

headingImageProps.label

string

⚠️ Deprecated, use avatarProps.label instead.

Aria label content for the image added before the heading.

_

headingImageProps.src

string

⚠️ Deprecated, use avatarProps.src instead.

Url content for the image added before the heading.

_

linkstringLink to be shared_
shareOptions?Array of ObjectsTo have custom share options, If no share options are passed, the default share options will be displayed_
closeButtonProps?objectTo render and customise share modal close button contains label and onClick_
closeButtonProps.labelstringAria label content for the close Icon button._
closeButtonProps.onClickfunctionCallback function to be invoked when the close button is clicked._

Style API

Our design system components include style props that allow you to easily customize different parts of each component to match your design needs.

Please refer to the Style API documentation for more insights.

ShareModal parts

const [openModal, setOpenModal] = React.useState(false);

const closeModal = () => {
  setOpenModal(false);
};

return (
  <React.Fragment>
    <Button
      iconStart={ShareIcon}
      label="Share"
      onClick={() => {
        setOpenModal(true);
      }}
      size="standard"
      variant="neutralSecondary"
    >
      Share
    </Button>
    <ShareModal
      className="border-4"
      classNames={{
        title: "text-positive-secondary",
        modalHeader: "mx-2 rounded-md p-2 bg-positive-secondary",
        modalContent: "p-3 bg-caution-secondary",
        modalHeaderContent: "text-critical-secondary border-4 bg-critical-secondary-hover",
        modalWrapper: "z-10 bg-opacity-90",
      }}
      closeButtonProps={{
        label: "Close share modal",
        onClick: closeModal,
      }}
      link="https://go.setmore.com"
      onClose={closeModal}
      open={openModal}
      translations={{
        description: { primary: 'Share this page with' },
        optionLabels: {
          copyLabel: "Copy Link",
          emailLabel: "Email",
          facebookLabel: "Facebook",
          messengerLabel: "Messenger",
          whatsappLabel: "Whatsapp",
        },
        title: "Share this page",
      }}
    />
  </React.Fragment>
);

Stylable PartsDescription
rootThe container that wraps the share modal.
titleThe title displayed in the header of the share modal.
modalHeaderThe container that holds and organizes the heading components.
modalHeaderContentThe container that holds the heading text and icon.
modalWrapperThe container that wraps the whole modal element, acts as the overlay as well.
modalContentThe container that holds the main content within the modal body.

NOTE: The content style part has been removed. Use primaryDescription and secondaryDescription style parts instead for styling description text.

ShareModalChildren parts

const [openModal, setOpenModal] = React.useState(false);

const closeModal = () => {
  setOpenModal(false);
};

return (
  <React.Fragment>
    <Button
      iconStart={ShareIcon}
      label="Share"
      onClick={() => {
        setOpenModal(true);
      }}
      size="standard"
      variant="neutralSecondary"
    >
      Share
    </Button>
    <ShareModal
      className="border-4"
      classNames={{
        optionStack: 'bg-critical',
        optionButton: 'bg-positive',
        track: 'bg-caution',
        primaryDescription: 'text-link',
        secondaryDescription: 'text-body-16'
      }}
      closeButtonProps={{
        label: "Close share modal",
        onClick: closeModal,
      }}
      link="https://anywhereworks.com"
      onClose={closeModal}
      open={openModal}
      translations={{
        description: { primary: 'Anywhereworks', secondary: 'Help the world work Anywhere' },
        optionLabels: {
          copyLabel: "Copy Link",
          emailLabel: "Email",
          facebookLabel: "Facebook",
          messengerLabel: "Messenger",
          whatsappLabel: "Whatsapp",
        },
        title: "Share this page",
      }}
    />
  </React.Fragment>
);

Stylable PartsDescription
optionStackThe container that wraps the option buttons.
optionButtonThe style for option button.
trackThe container that holds and avatar the description.
primaryDescriptionThe style for primary text.
secondaryDrescriptionThe style for secondary text.

ShareSheetChildren parts

Note: The bottom sheet renders only on mobile. The qrCode and sheetWrapper style parts apply only while the sheet is visible.

const [openModal, setOpenModal] = React.useState(false);

const closeModal = () => {
  setOpenModal(false);
};

return (
  <React.Fragment>
    <Button
      iconStart={ShareIcon}
      label="Share"
      onClick={() => {
        setOpenModal(true);
      }}
      size="standard"
      variant="neutralSecondary"
    >
      Share
    </Button>
    <ShareModal
      className="border-4"
      classNames={{
        optionStack: 'bg-critical',
        optionButton: 'bg-positive',
        sheetWrapper: 'bg-caution',
        qrCode: 'fill-positive',
      }}
      closeButtonProps={{
        label: "Close share modal",
        onClick: closeModal,
      }}
      link="https://anywhereworks.com"
      onClose={closeModal}
      open={openModal}
      translations={{
        description: { primary: 'Anywhereworks', secondary: 'Help the world work Anywhere' },
        optionLabels: {
          copyLabel: "Copy Link",
          emailLabel: "Email",
          facebookLabel: "Facebook",
          messengerLabel: "Messenger",
          whatsappLabel: "Whatsapp",
        },
        title: "Share this page",
      }}
    />
  </React.Fragment>
);

Stylable PartsDescription
optionStackThe container that wraps the option buttons.
optionButtonThe style for option button.
sheetWrapperThe container that qrcode and buttons.
qrCodeThe style for qrcode.