From 48f46f090e4de334fd253d77bcb8cdcc752c18e3 Mon Sep 17 00:00:00 2001 From: SWARVY Date: Thu, 8 Aug 2024 15:18:28 +0900 Subject: [PATCH] feat(time): create Modal / ModalFilter / ModalContent using compound component pattern (#97) --- apps/time/src/shared/ui/Modal.tsx | 102 ++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 apps/time/src/shared/ui/Modal.tsx diff --git a/apps/time/src/shared/ui/Modal.tsx b/apps/time/src/shared/ui/Modal.tsx new file mode 100644 index 00000000..d4850e2d --- /dev/null +++ b/apps/time/src/shared/ui/Modal.tsx @@ -0,0 +1,102 @@ +'use client'; + +import { PropsWithChildren, useEffect } from 'react'; + +import { CloseOutline } from '@clab/icon'; +import { cn } from '@clab/utils'; + +interface ModalProps extends PropsWithChildren { + title: string; + visible: boolean; + close: () => void; +} + +interface ModalFilterProps extends PropsWithChildren { + title: string; +} + +interface ModalFilterItemProps extends PropsWithChildren { + onClick: () => void; + selected: boolean; +} + +function ModalFilter({ title, children }: ModalFilterProps) { + return ( +
+

{title}

+ +
+ ); +} + +function ModalFilterItem({ + selected, + onClick, + children, +}: ModalFilterItemProps) { + return ( + + ); +} + +function ModalContent({ children }: PropsWithChildren) { + return
{children}
; +} + +export default function Modal({ title, close, children }: ModalProps) { + useEffect(() => { + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === 'Escape') { + close(); + } + }; + + document.body.classList.add('overflow-hidden'); + document.addEventListener('keydown', handleKeyDown); + + return () => { + document.body.classList.remove('overflow-hidden'); + document.removeEventListener('keydown', handleKeyDown); + }; + }, []); + + return ( +
+
+
+

{title ?? ''}

+ +
+ {children} +
+
+ ); +} + +Modal.Content = ModalContent; +Modal.Filter = ModalFilter; +Modal.FilterItem = ModalFilterItem; + +Modal.displayName = 'Modal'; +ModalContent.displayName = 'ModalContent'; +ModalFilter.displayName = 'ModalFilter'; +ModalFilterItem.displayName = 'ModalFilterItem';