- Introduced ModalDestinationButton for destination selection with customizable icons and labels. - Added ModalInput for text input with optional character counter. - Implemented ModalLink for reusable links styled as underlined text. - Created ModalPlatformCard for platform selection with badges. - Developed ModalRadioGroup for radio button groups with custom styling. - Added ModalSection for grouping modal content with optional labels. - Implemented ModalSelect for dropdown selections with custom styling. - Created ModalShareButtons for sharing options via Gmail, Email, and Messenger. - Developed ModalTextarea for multi-line text input with character counter. - Introduced ModalToggle for toggle switches with optional help text and links. - Updated README.md with component descriptions, usage examples, and design guidelines. - Added index.ts for centralized exports of modal components.
77 lines
1.6 KiB
TypeScript
77 lines
1.6 KiB
TypeScript
import React, { useEffect, useRef } from 'react'
|
||
import styles from './Modal.module.css'
|
||
|
||
export interface ModalProps {
|
||
open: boolean
|
||
onClose: () => void
|
||
title?: string
|
||
children: React.ReactNode
|
||
footer?: React.ReactNode
|
||
width?: 'sm' | 'md' | 'lg' | 'xl'
|
||
closeOnOverlayClick?: boolean
|
||
}
|
||
|
||
export const Modal: React.FC<ModalProps> = ({
|
||
open,
|
||
onClose,
|
||
title,
|
||
children,
|
||
footer,
|
||
width = 'md',
|
||
closeOnOverlayClick = true
|
||
}) => {
|
||
const dialogRef = useRef<HTMLDialogElement>(null)
|
||
|
||
useEffect(() => {
|
||
const dialog = dialogRef.current
|
||
if (!dialog) return
|
||
|
||
if (open) {
|
||
dialog.showModal()
|
||
} else {
|
||
dialog.close()
|
||
}
|
||
}, [open])
|
||
|
||
const handleOverlayClick = (e: React.MouseEvent<HTMLDialogElement>) => {
|
||
if (closeOnOverlayClick && e.target === dialogRef.current) {
|
||
onClose()
|
||
}
|
||
}
|
||
|
||
if (!open) return null
|
||
|
||
return (
|
||
<dialog
|
||
ref={dialogRef}
|
||
className={`${styles.modal} ${styles[`modal-${width}`]}`}
|
||
onClick={handleOverlayClick}
|
||
>
|
||
<div className={styles.modalContent}>
|
||
{/* Header */}
|
||
{title && (
|
||
<div className={styles.modalHeader}>
|
||
<h3 className={styles.modalTitle}>{title}</h3>
|
||
<button
|
||
type="button"
|
||
className={styles.closeButton}
|
||
onClick={onClose}
|
||
aria-label="Cerrar"
|
||
>
|
||
×
|
||
</button>
|
||
</div>
|
||
)}
|
||
|
||
{/* Body */}
|
||
<div className={styles.modalBody}>{children}</div>
|
||
|
||
{/* Footer */}
|
||
{footer && <div className={styles.modalFooter}>{footer}</div>}
|
||
</div>
|
||
</dialog>
|
||
)
|
||
}
|
||
|
||
export default Modal
|