import { cx } from '@emotion/css'; import { useDialog } from '@react-aria/dialog'; import { FocusScope } from '@react-aria/focus'; import { OverlayContainer, useOverlay } from '@react-aria/overlays'; import React, { PropsWithChildren, useRef } from 'react'; import { useTheme2 } from '../../themes'; import { IconName } from '../../types'; import { IconButton } from '../IconButton/IconButton'; import { HorizontalGroup } from '../Layout/Layout'; import { ModalHeader } from './ModalHeader'; import { getModalStyles } from './getModalStyles'; export interface Props { /** @deprecated no longer used */ icon?: IconName; /** @deprecated no longer used */ iconTooltip?: string; /** Title for the modal or custom header element */ title: string | JSX.Element; className?: string; contentClassName?: string; closeOnEscape?: boolean; closeOnBackdropClick?: boolean; trapFocus?: boolean; isOpen?: boolean; onDismiss?: () => void; /** If not set will call onDismiss if that is set. */ onClickBackdrop?: () => void; } export function Modal(props: PropsWithChildren) { const { title, children, isOpen = false, closeOnEscape = true, closeOnBackdropClick = true, className, contentClassName, onDismiss, onClickBackdrop, trapFocus = true, } = props; const theme = useTheme2(); const styles = getModalStyles(theme); const ref = useRef(null); // Handle interacting outside the dialog and pressing // the Escape key to close the modal. const { overlayProps, underlayProps } = useOverlay( { isKeyboardDismissDisabled: !closeOnEscape, isOpen, onClose: onDismiss }, ref ); // Get props for the dialog and its title const { dialogProps, titleProps } = useDialog({}, ref); if (!isOpen) { return null; } const headerClass = cx(styles.modalHeader, typeof title !== 'string' && styles.modalHeaderWithTabs); return (
{typeof title === 'string' && } { // FIXME: custom title components won't get an accessible title. // Do we really want to support them or shall we just limit this ModalTabsHeader? typeof title !== 'string' && title }
{children}
); } function ModalButtonRow({ leftItems, children }: { leftItems?: React.ReactNode; children: React.ReactNode }) { const theme = useTheme2(); const styles = getModalStyles(theme); if (leftItems) { return (
{leftItems} {children}
); } return (
{children}
); } Modal.ButtonRow = ModalButtonRow; interface DefaultModalHeaderProps { id?: string; title: string; icon?: IconName; iconTooltip?: string; } function DefaultModalHeader({ icon, iconTooltip, title, id }: DefaultModalHeaderProps): JSX.Element { return ; }