-
Notifications
You must be signed in to change notification settings - Fork 120
Expand file tree
/
Copy pathModal.tsx
More file actions
106 lines (95 loc) · 2.58 KB
/
Modal.tsx
File metadata and controls
106 lines (95 loc) · 2.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import React, { forwardRef, useCallback, useRef } from 'react'
import clsx from 'clsx'
import { twMerge } from 'tailwind-merge'
import { IComponentBaseProps, ComponentPosition } from '../types'
import ModalActions from './ModalActions'
import ModalBody from './ModalBody'
import ModalHeader from './ModalHeader'
import ModalLegacy from './ModalLegacy'
export type ModalProps = React.DialogHTMLAttributes<HTMLDialogElement> &
IComponentBaseProps & {
open?: boolean
position?: Exclude<ComponentPosition, 'left' | 'right'>
responsive?: boolean
backdrop?: boolean
ariaHidden?: boolean
}
const Modal = forwardRef<HTMLDialogElement, ModalProps>(
(
{
children,
open,
position,
responsive,
backdrop,
ariaHidden,
dataTheme,
className,
...props
},
ref
): JSX.Element => {
const containerClasses = twMerge(
'modal',
clsx({
'modal-open': open,
'modal-end': position === 'end',
'modal-start': position === 'start',
'modal-top': position === 'top',
'modal-middle': position === 'middle',
'modal-bottom': position === 'bottom',
'modal-bottom sm:modal-middle': responsive,
})
)
ariaHidden = ariaHidden ?? !open
const bodyClasses = twMerge('modal-box', className)
return (
<dialog
{...props}
aria-label="Modal"
aria-hidden={ariaHidden}
open={open}
aria-modal={open}
data-theme={dataTheme}
className={containerClasses}
ref={ref}
>
<div data-theme={dataTheme} className={bodyClasses}>
{children}
</div>
{backdrop && (
<form method="dialog" className="modal-backdrop">
<button>close</button>
</form>
)}
</dialog>
)
}
)
Modal.displayName = 'Modal'
export type DialogProps = Omit<ModalProps, 'ref'>
const useDialog = () => {
const dialogRef = useRef<HTMLDialogElement>(null)
const handleShow = useCallback(() => {
dialogRef.current?.showModal()
}, [dialogRef])
const handleHide = useCallback(() => {
dialogRef.current?.close()
}, [dialogRef])
const Dialog = useCallback<React.FunctionComponent>(({ children, ...props }: DialogProps) => {
return (
<Modal {...props} ref={dialogRef}>
{children}
</Modal>
)
}, [dialogRef])
Dialog.displayName = 'Dialog'
return { dialogRef, Dialog, handleShow, handleHide }
}
export default Object.assign(Modal, {
Header: ModalHeader,
Body: ModalBody,
Actions: ModalActions,
Legacy: ModalLegacy,
useDialog,
})