From a24406cce30f351c2eeb3fa1c9183ac2eab508c0 Mon Sep 17 00:00:00 2001 From: Benji <64439681+benjitrosch@users.noreply.github.com> Date: Thu, 14 Apr 2022 13:34:56 -0400 Subject: [PATCH] chore(Modal): refactored modal for better customization (#85) BREAKING CHANGE: removed all props in favor of passing in subcomponents --- src/Modal/Modal.stories.tsx | 29 ++++++++--- src/Modal/Modal.tsx | 97 ++++++++++++++----------------------- src/Modal/ModalActions.tsx | 28 +++++++++++ src/Modal/ModalBody.tsx | 23 +++++++++ src/Modal/ModalHeader.tsx | 25 ++++++++++ 5 files changed, 136 insertions(+), 66 deletions(-) create mode 100644 src/Modal/ModalActions.tsx create mode 100644 src/Modal/ModalBody.tsx create mode 100644 src/Modal/ModalHeader.tsx diff --git a/src/Modal/Modal.stories.tsx b/src/Modal/Modal.stories.tsx index 44e799a3..d0356eda 100644 --- a/src/Modal/Modal.stories.tsx +++ b/src/Modal/Modal.stories.tsx @@ -10,15 +10,32 @@ export default { } as Meta export const Default: Story = (args) => { - const [visible, toggleVisible] = useState(false) + const [visible, setVisible] = useState(false) + + const toggleVisible = () => { + setVisible(!visible) + } return ( <> - - toggleVisible(false)}> - Enim dolorem dolorum omnis atque necessitatibus. Consequatur aut - adipisci qui iusto illo eaque. Consequatur repudiandae et. Nulla ea - quasi eligendi. Saepe velit autem minima. + + + Lorem Ipsum + + + Enim dolorem dolorum omnis atque necessitatibus. Consequatur aut + adipisci qui iusto illo eaque. Consequatur repudiandae et. Nulla ea + quasi eligendi. Saepe velit autem minima. + + + + + + ) diff --git a/src/Modal/Modal.tsx b/src/Modal/Modal.tsx index 8a551c34..1e856bbd 100644 --- a/src/Modal/Modal.tsx +++ b/src/Modal/Modal.tsx @@ -1,97 +1,70 @@ -import React, { forwardRef, ReactNode, useImperativeHandle } from 'react' +import React, { forwardRef } from 'react' import clsx from 'clsx' import { twMerge } from 'tailwind-merge' import { IComponentBaseProps } from '../types' -import Button from '../Button' - -export type ModalRef = { - accept: () => void - cancel: () => void -} +import ModalActions from './ModalActions' +import ModalBody from './ModalBody' +import ModalHeader from './ModalHeader' export type ModalProps = React.HTMLAttributes & IComponentBaseProps & { open?: boolean - title?: string - footer?: boolean - acceptText?: string - cancelText?: string - closeOnBlur?: boolean - onAccept?: () => void - onCancel?: () => void + responsive?: boolean + onClickBackdrop?: () => void } -const Modal = forwardRef( +const Modal = forwardRef( ( { children, open, - title, - footer = true, - acceptText = 'Accept', - cancelText = 'Close', - onAccept, - onCancel, + responsive, + onClickBackdrop, dataTheme, className, - closeOnBlur = true, ...props }, ref ): JSX.Element => { - const classes = twMerge( + const containerClasses = twMerge( 'modal', - className, clsx({ 'modal-open': open, + 'modal-bottom sm:modal-middle': responsive, }) ) - useImperativeHandle(ref, (): ModalRef => { - return { - accept: () => { - onAccept && onAccept() - }, - cancel: () => { - onCancel && onCancel() - }, - } - }) - - const handleBackdropClick: React.MouseEventHandler = (e) => { - if (e.target === e.currentTarget) { - e.stopPropagation() - if (closeOnBlur && onCancel) { - onCancel() - } - } - } + const bodyClasses = twMerge( + 'modal-box', + className + ) return (
{ + e.stopPropagation() + if (e.target === e.currentTarget) { + e.stopPropagation() + if (onClickBackdrop) { + onClickBackdrop() + } + } + }} > -
- {title ?
{title}
: null} - -
{children}
- - {footer ? ( -
- - -
- ) : null} +
+ {children}
) @@ -100,4 +73,8 @@ const Modal = forwardRef( Modal.displayName = 'Modal' -export default Modal +export default Object.assign(Modal, { + Header: ModalHeader, + Body: ModalBody, + Actions: ModalActions, +}) diff --git a/src/Modal/ModalActions.tsx b/src/Modal/ModalActions.tsx new file mode 100644 index 00000000..58b21216 --- /dev/null +++ b/src/Modal/ModalActions.tsx @@ -0,0 +1,28 @@ +import React from 'react' +import { twMerge } from 'tailwind-merge' + +import { IComponentBaseProps } from '../types' + +type ModalActionsProps = React.HTMLAttributes & + IComponentBaseProps + +const ModalActions = React.forwardRef(({ + children, + className, + ...props +}, ref) => { + const classes = twMerge('modal-action', className) + return ( +
+ {children} +
+ ) +}) + +ModalActions.displayName = "ModalActions" + +export default ModalActions diff --git a/src/Modal/ModalBody.tsx b/src/Modal/ModalBody.tsx new file mode 100644 index 00000000..029200c0 --- /dev/null +++ b/src/Modal/ModalBody.tsx @@ -0,0 +1,23 @@ +import React from 'react' + +type ModalBodyProps = React.HTMLAttributes + +const ModalBody = React.forwardRef(({ + children, + className, + ...props +}, ref) => { + return ( +
+ {children} +
+ ) +}) + +ModalBody.displayName = "ModalBody" + +export default ModalBody diff --git a/src/Modal/ModalHeader.tsx b/src/Modal/ModalHeader.tsx new file mode 100644 index 00000000..c541365e --- /dev/null +++ b/src/Modal/ModalHeader.tsx @@ -0,0 +1,25 @@ +import React from 'react' +import { twMerge } from 'tailwind-merge' + +type ModalHeaderProps = React.HTMLAttributes + +const ModalHeader = React.forwardRef(({ + children, + className, + ...props +}, ref) => { + const classes = twMerge('w-full mb-8 text-xl', className) + return ( +
+ {children} +
+ ) +}) + +ModalHeader.displayName = "ModalHeader" + +export default ModalHeader