diff --git a/packages/frontend/component/src/ui/modal/modal.tsx b/packages/frontend/component/src/ui/modal/modal.tsx index f47a519a1..ee0b6b198 100644 --- a/packages/frontend/component/src/ui/modal/modal.tsx +++ b/packages/frontend/component/src/ui/modal/modal.tsx @@ -10,7 +10,7 @@ import * as VisuallyHidden from '@radix-ui/react-visually-hidden'; import { assignInlineVars } from '@vanilla-extract/dynamic'; import clsx from 'clsx'; import type { CSSProperties } from 'react'; -import { forwardRef, useCallback } from 'react'; +import { forwardRef, useCallback, useEffect, useState } from 'react'; import type { IconButtonProps } from '../button'; import { IconButton } from '../button'; @@ -90,129 +90,163 @@ class ModalTransitionContainer extends HTMLElement { } } -let container: ModalTransitionContainer | null = null; -function prepareContainer() { - if (!container) { +let defined = false; +function createContainer() { + if (!defined) { customElements.define( 'modal-transition-container', ModalTransitionContainer ); - container = new ModalTransitionContainer(); - document.body.append(container); + defined = true; } + const container = new ModalTransitionContainer(); + document.body.append(container); return container; } -export const Modal = forwardRef((props, ref) => { - const { - modal, - portalOptions, - open, - onOpenChange, - width, - height, - minHeight = 194, - title, - description, - withoutCloseButton = false, - persistent, - contentOptions: { - style: contentStyle, - className: contentClassName, - onPointerDownOutside, - onEscapeKeyDown, - ...otherContentOptions - } = {}, - overlayOptions: { - className: overlayClassName, - style: overlayStyle, - ...otherOverlayOptions - } = {}, - closeButtonOptions = {}, - children, - ...otherProps - } = props; +export const ModalInner = forwardRef( + (props, ref) => { + const { + modal, + portalOptions, + open, + onOpenChange, + width, + height, + minHeight = 194, + title, + description, + withoutCloseButton = false, + persistent, + contentOptions: { + style: contentStyle, + className: contentClassName, + onPointerDownOutside, + onEscapeKeyDown, + ...otherContentOptions + } = {}, + overlayOptions: { + className: overlayClassName, + style: overlayStyle, + ...otherOverlayOptions + } = {}, + closeButtonOptions = {}, + children, + ...otherProps + } = props; - return ( - - - -
- { - onPointerDownOutside?.(e); - persistent && e.preventDefault(); - }, - [onPointerDownOutside, persistent] - )} - onEscapeKeyDown={useCallback( - (e: KeyboardEvent) => { - onEscapeKeyDown?.(e); - persistent && e.preventDefault(); - }, - [onEscapeKeyDown, persistent] - )} - className={clsx(styles.modalContent, contentClassName)} + const [container, setContainer] = useState( + null + ); + + useEffect(() => { + const container = createContainer(); + setContainer(container); + return () => { + setTimeout(() => { + container.remove(); + }, 1000) as unknown as number; + }; + }, []); + + const handlePointerDownOutSide = useCallback( + (e: PointerDownOutsideEvent) => { + onPointerDownOutside?.(e); + persistent && e.preventDefault(); + }, + [onPointerDownOutside, persistent] + ); + + const handleEscapeKeyDown = useCallback( + (e: KeyboardEvent) => { + onEscapeKeyDown?.(e); + persistent && e.preventDefault(); + }, + [onEscapeKeyDown, persistent] + ); + + if (!container) { + return; + } + + return ( + + + - {withoutCloseButton ? null : ( - - - - - - )} - {title ? ( - - {title} - - ) : ( - // Refer: https://www.radix-ui.com/primitives/docs/components/dialog#title - // If you want to hide the title, wrap it inside our Visually Hidden utility like this . - - - - )} - {description ? ( - - {description} - - ) : null} + {...otherOverlayOptions} + /> +
+ + {withoutCloseButton ? null : ( + + + + + + )} + {title ? ( + + {title} + + ) : ( + // Refer: https://www.radix-ui.com/primitives/docs/components/dialog#title + // If you want to hide the title, wrap it inside our Visually Hidden utility like this . + + + + )} + {description ? ( + + {description} + + ) : null} - {children} - -
-
-
- ); + {children} +
+
+
+
+ ); + } +); + +ModalInner.displayName = 'ModalInner'; + +export const Modal = forwardRef((props, ref) => { + if (!props.open) { + return; + } + return ; }); Modal.displayName = 'Modal';