import React, { useRef } from 'react'; import { Overlay, useModalOverlay, useDialog } from 'react-aria'; import { OverlayTriggerState } from 'react-stately'; import { DOMAttributes, FocusableElement } from '@react-types/shared'; /* This has to be a separate element otherwise the focus trap fails. Assuming this is because it needs to fit inside the 'Overlay' as a form of context. */ function ModalContent({ children, ...props }: { children: (titleProps: DOMAttributes) => React.ReactElement; }) { const ref = useRef(null); const { dialogProps, titleProps } = useDialog(props, ref); return (
{children(titleProps)}
); } export type ModalProps = { isDismissable?: boolean; state: OverlayTriggerState; overlayProps: DOMAttributes; children: (titleProps: DOMAttributes) => React.ReactElement; // Returns the title props from the 'ModalContent' scope: 'squiz-gb-scope' | 'squiz-cb-scope' | 'squiz-rb-scope'; }; export function Modal({ isDismissable, state, overlayProps, children, scope, ...props }: ModalProps) { const ref = useRef(null); const { modalProps, underlayProps } = useModalOverlay({ isDismissable, ...props }, state, ref); return (
{(titleProps) => children(titleProps)}
); }