diff options
| author | Armand Philippot <git@armandphilippot.com> | 2023-10-31 16:00:45 +0100 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2023-11-11 18:15:27 +0100 |
| commit | 3ff4c37a7a2c40340c17f9e6c1754444bce0f839 (patch) | |
| tree | 551ca3df148d46af2bd27995fa98c01378030644 /src/components/molecules/modals/modal/modal.tsx | |
| parent | 0e52a59917406ad03c174e030c6c1c92ab23449d (diff) | |
refactor(components): rewrite Modal component
* add an optional close button
* add an icon prop
Diffstat (limited to 'src/components/molecules/modals/modal/modal.tsx')
| -rw-r--r-- | src/components/molecules/modals/modal/modal.tsx | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/src/components/molecules/modals/modal/modal.tsx b/src/components/molecules/modals/modal/modal.tsx new file mode 100644 index 0000000..ed55488 --- /dev/null +++ b/src/components/molecules/modals/modal/modal.tsx @@ -0,0 +1,103 @@ +import { + type ForwardRefRenderFunction, + type HTMLAttributes, + type ReactNode, + forwardRef, +} from 'react'; +import { Button, Icon } from '../../../atoms'; +import styles from './modal.module.scss'; + +export type ModalProps = HTMLAttributes<HTMLDivElement> & { + /** + * The modal body. + */ + children: ReactNode; + /** + * The close button label. + */ + closeBtnLabel?: string; + /** + * The modal title. + */ + heading?: ReactNode; + /** + * Define an icon to illustrate the modal. + */ + icon?: ReactNode; + /** + * The modal kind. + * + * @default 'primary' + */ + kind?: 'primary' | 'secondary'; + /** + * A callback function to handle close button action. + */ + onClose?: () => void; +}; + +const ModalWithRef: ForwardRefRenderFunction<HTMLDivElement, ModalProps> = ( + { + children, + className = '', + closeBtnLabel, + heading, + icon, + kind = 'primary', + onClose, + ...props + }, + ref +) => { + const hasHeader = !!heading || !!icon || !!closeBtnLabel; + const modalClass = [ + styles.modal, + styles[hasHeader ? 'modal--has-header' : ''], + styles[closeBtnLabel ? 'modal--has-btn' : ''], + styles[`modal--${kind}`], + className, + ].join(' '); + + return ( + <div {...props} className={modalClass} ref={ref}> + {hasHeader ? ( + <div className={styles.header}> + {icon ? ( + <div aria-hidden className={styles.icon}> + {icon} + </div> + ) : null} + {heading ? <div className={styles.title}>{heading}</div> : null} + {closeBtnLabel ? ( + <Button + aria-label={closeBtnLabel} + className={styles.btn} + onClick={onClose} + // eslint-disable-next-line react/jsx-no-literals + kind="neutral" + // eslint-disable-next-line react/jsx-no-literals + shape="initial" + > + <Icon + aria-hidden + className={styles.icon} + // eslint-disable-next-line react/jsx-no-literals + shape="cross" + // eslint-disable-next-line react/jsx-no-literals + size="xs" + /> + </Button> + ) : null} + </div> + ) : null} + {children} + </div> + ); +}; + +/** + * Modal component + * + * Render a modal component. + */ +export const Modal = forwardRef(ModalWithRef); |
