import React, { type MouseEventHandler, type ReactElement, type ReactNode, } from 'react'; import type { IconName } from '../Icon/Icon'; import { useId } from '../../hooks/useId'; import { ModalOverlay } from './ModalOverlay'; import { ModalContent } from './ModalContent'; import { ModalHeaderWithIcon, type ModalHeaderWithIconVariant, } from './ModalHeaderWithIcon'; import { ModalHeaderWithIllustration } from './ModalHeaderWithIllustration'; import { ModalFooter } from './ModalFooter'; import { ModalBody } from './ModalBody'; export type ModalProps = { /** * Actions to display in the Modal */ actions?: ReactNode; /** * Whether the modal should be open */ isOpen: boolean; /** * Whether the modal should have opening and closing animation * @default false */ noAnimation?: boolean; /** * The element where to mount the Modal. It needs to be outside * the GrapesProvider tree for the focus trap to work properly. * @default document.body */ portalContainer?: Element; /** * The title of the Modal */ title: string; /** * The subtitle of the Modal */ subtitle?: string; /** * The content of the Modal */ children?: ReactNode; /** * className for the element */ className?: string; /** * Handler that is called when the Modal is closed */ onClose?: MouseEventHandler; } & ( | // Modal with icon { /** * The icon to display in the button */ iconName: IconName; /** * Specifies the icon variant * @default info */ iconVariant?: ModalHeaderWithIconVariant; illustration?: never; illustrationHeight?: never; } // Modal with illustration | { iconName?: never; iconVariant?: never; /** * The illustration to display on top of the Modal */ illustration: ReactNode; /** * Specifies the illustration height * @default 424px */ illustrationHeight?: string; } ); /** * A Modal is window containing contextual information, tasks, or workflows that appear over the user interface. * The content behind a modal dialog is inert, meaning that users cannot interact with it. * @see https://grapes.spendesk.design/docs/components/modal */ export const Modal = ({ actions, children, iconName, iconVariant = 'info', illustration, illustrationHeight = '424px', isOpen, portalContainer, title, subtitle, className, onClose, noAnimation = false, ...rest }: ModalProps): ReactElement | null => { const labelledById = useId(); const hasIcon = iconName != null; return ( {hasIcon ? ( ) : ( )} {children ? {children} : null} {actions ? {actions} : null} ); };