Created Layout & Responsive Header Component
This commit is contained in:
19
components/modal/modal-portal.tsx
Normal file
19
components/modal/modal-portal.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import { useRef, useEffect, useState } from 'react'
|
||||
import { createPortal } from 'react-dom'
|
||||
|
||||
interface modalPortal {
|
||||
children: React.ReactNode
|
||||
selector?: string
|
||||
}
|
||||
|
||||
export const ModalPortal = ({ children, selector = 'modal' }: modalPortal) => {
|
||||
const ref = useRef<HTMLDivElement | null>(null)
|
||||
const [mounted, setMounted] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
ref.current = document.querySelector(selector)
|
||||
setMounted(true)
|
||||
}, [selector])
|
||||
|
||||
return mounted && ref.current ? createPortal(children, ref.current) : null
|
||||
}
|
||||
41
components/modal/modal.tsx
Normal file
41
components/modal/modal.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import { useEffect, useRef } from 'react'
|
||||
import clsx from 'clsx'
|
||||
|
||||
import { ModalPortal } from '@/components/modal/modal-portal'
|
||||
|
||||
import { useClickOutside } from '@/hooks/useClickOutside'
|
||||
|
||||
interface modalProps {
|
||||
isOpen: boolean
|
||||
close: () => void
|
||||
children: React.ReactNode
|
||||
closeOnClickAway?: boolean
|
||||
className?: string
|
||||
}
|
||||
|
||||
export const Modal = ({
|
||||
isOpen,
|
||||
close,
|
||||
children,
|
||||
closeOnClickAway = false,
|
||||
className,
|
||||
}: modalProps) => {
|
||||
const contentRef = useRef(null)
|
||||
|
||||
useClickOutside({
|
||||
onClick: () => closeOnClickAway && close(),
|
||||
ref: contentRef,
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (!isOpen) return
|
||||
}, [isOpen])
|
||||
|
||||
return isOpen ? (
|
||||
<ModalPortal selector="#modal">
|
||||
<div ref={contentRef} className={clsx('w-full h-full', className)}>
|
||||
{children}
|
||||
</div>
|
||||
</ModalPortal>
|
||||
) : null
|
||||
}
|
||||
Reference in New Issue
Block a user