Created
May 9, 2022 19:01
-
-
Save clqu/32883b5bc2146bdc545a261b49c3c5eb to your computer and use it in GitHub Desktop.
This is a modal component made with TailwindCSS and Next.js.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Modal from '../Modal' | |
export default function Home() { | |
return ( | |
<> | |
<Modal | |
title={"Modal Title"} | |
content={"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."} | |
onConfirm={() => console.log('Button confirm')} | |
onDiscard={() => console.log('Button discard')} | |
buttons={[ | |
{ role: "custom", onClick: () => console.log("custom test"), toClose: true, classes: "bg-zinc-500/20 px-4 py-2 rounded-lg hover:bg-zinc-500/30 transition-all duration-200", label: "Custom" }, | |
{ role: "discard", toClose: true, classes: "bg-zinc-500/20 px-4 py-2 rounded-lg hover:bg-zinc-500/30 transition-all duration-200", label: "Discard" }, | |
{ role: "confirm", toClose: false, classes: "bg-green-500 px-4 py-2 rounded-lg hover:bg-green-600 transition-all duration-200", label: "Confirm" } | |
]} | |
> | |
<div>açmak için tıkla</div> | |
</Modal> | |
</> | |
) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { Fragment, useState, useEffect } = require("react"); | |
const { Transition } = require("@headlessui/react"); | |
module.exports = ({ | |
title = "", | |
content = "", | |
buttons = [], | |
classes = "", | |
onDiscard = "", | |
onConfirm = "", | |
children | |
}) => { | |
let [ isOpen, setIsOpen ] = useState(false); | |
useEffect(() => { | |
setIsOpen(isOpen); | |
if(!isOpen) { | |
document.documentElement.style.overflow = "auto"; | |
} else { | |
document.documentElement.style.overflow = "hidden"; | |
} | |
}, [isOpen]); | |
const HandleChange = () => { | |
setIsOpen(!isOpen); | |
} | |
return <> | |
<div onClick={() => HandleChange()}> | |
{children} | |
</div> | |
<Transition show={isOpen}> | |
<Transition.Child | |
as={Fragment} | |
enter="transition-all duration-200" | |
enterFrom="opacity-0" | |
enterTo="opacity-100" | |
leave="transition-all duration-200" | |
leaveTo="opacity-0" | |
leaveFrom="opacity-100" | |
> | |
<div style={{ zIndex: '1' }} onClick={() => HandleChange()} className="w-full h-full left-0 top-0 bg-black/50 fixed" /> | |
</Transition.Child> | |
<Transition.Child | |
as={Fragment} | |
enter="transition-all duration-200" | |
enterFrom="opacity-0 scale-75" | |
enterTo="opacity-100 scale-100" | |
leave="transition-all duration-200" | |
leaveTo="opacity-0 scale-75" | |
leaveFrom="opacity-100 scale-100" | |
> | |
<div style={{ zIndex: '2' }} className="flex justify-center items-center h-full w-full fixed"> | |
<div className={`max-w-[28rem] w-full ${classes ? classes : 'p-4 bg-white rounded-lg'}`}> | |
<div className="w-full flex justify-between items-center mb-6"> | |
<p className="font-medium text-lg">{title}</p> | |
<div onClick={() => HandleChange()} className="w-8 h-8 flex justify-center items-center rounded-lg transition-all duration-200 cursor-pointer hover:bg-zinc-500/20"> | |
<svg width="24px" height="24px" viewBox="0 0 36 36" version="1.1" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink"> | |
<path className="clr-i-outline clr-i-outline-path-1" d="M19.41,18l8.29-8.29a1,1,0,0,0-1.41-1.41L18,16.59,9.71,8.29A1,1,0,0,0,8.29,9.71L16.59,18,8.29,26.29a1,1,0,1,0,1.41,1.41L18,19.41l8.29,8.29a1,1,0,0,0,1.41-1.41Z" /> | |
<rect x={0} y={0} width={36} height={36} fillOpacity={0} /> | |
</svg> | |
</div> | |
</div> | |
<p className="text-md">{content}</p> | |
<div className="mt-6 flex justify-end items-center gap-2"> | |
{buttons.map((button, index) => ( | |
<button | |
onClick={() => { | |
if(button.role === "discard") { | |
onDiscard(); | |
} | |
if(button.role === "confirm") { | |
onConfirm(); | |
} | |
if(button.role === "custom") { | |
button.onClick(); | |
} | |
if(button.toClose) { | |
setIsOpen(false); | |
} | |
}} | |
key={index} | |
className={button.classes} | |
> | |
{button.label} | |
</button> | |
))} | |
</div> | |
</div> | |
</div> | |
</Transition.Child> | |
</Transition> | |
</> | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It's working fine though, but we could have a prop to change the open state dynamically.