import { forwardRef, useRef, MutableRefObject } from 'react'; import VisuallyHidden from '@reach/visually-hidden'; import { isString } from 'lodash'; import { Box, BoxProps } from '../Box'; import { Button, ButtonProps } from '../Button'; import { Text } from '../Text'; import { Modal, ModalProps } from './Modal'; export const ANNOUNCEMENT_MODAL_CTA = 'ANNOUNCEMENT_MODAL_CTA'; /** A callback that requires the usage of onDismiss and ref to keep things accessible! */ export type AnnouncementModalCTARenderProp = ({ onDismiss, ref, }: Pick & { ref: MutableRefObject; }) => JSX.Element; interface LinkCTA extends BoxProps<'a'> {} interface ButtonCTA extends ButtonProps {} export interface AnnouncementModalProps extends Omit< ModalProps, 'isAlertModal' | 'children' | 'modalDescription' | 'modalLabel' | 'leastDestructiveRef' > { /** * Can either be a string or an object filled with props relevant to either a button component or a box component * rendered as an anchor element. */ cta: string | LinkCTA | ButtonCTA; imageSource?: string; modalDescription: string; modalLabel: string; ['data-testid']?: string; } const CTAButton = forwardRef( ( { children, onDismiss }: Pick & { children: string }, ref: ButtonProps['ref'], ) => ( ), ); CTAButton.displayName = 'CTAButton'; export const AnnouncementModal = ({ className, cta, imageSource, modalDescription, modalLabel, onDismiss, variant = 'modal-medium', withCloseButton = true, ...rest }: AnnouncementModalProps) => { const ctaRef = useRef(null); // probably a button, but could also be an anchor return ( {modalDescription}} modalLabel={{modalLabel}} onDismiss={onDismiss} variant={variant} withCloseButton={withCloseButton} {...rest} > {/** * The base Modal component renders the label and descripton beforre children (this content). For this abstraction, * we pass visually-hidden elements for the base Modal's label and description keeping the modal announced properly, * but we visibly render the correct content while masking it for users with assistive technology via aria-hidden. * * In other words, assistive technology users hear the correct thing while seeing-eye users see the correct thing. */} {isString(cta) ? ( {cta} ) : ( // @ts-ignore