Im remaking one of my older projects using react+TS+Tailwind and I decided to use element for modal instead of creating classic modal element - I choose it due to accessibility.
However I ran into some issues. Currently when I can set this component to open when it uses open attribute, but then it opens as dialog and not as modal. I do not know where to call .showModal() method and on what exactly to open it as a modal (heh this seems to be easier for me to do in vanilla js :P)
Thats my Modal component
interface Props {
showModal: HandleModal
edit: (id: number, value: string) => void
closeModal: React.Dispatch<React.SetStateAction<HandleModal>>
}
const Modal = ({ showModal, edit, closeModal }: Props) => {
let modalContent = (
<div className=''>
<p>Please input a correct task in the input field</p>
<Button click={() => closeModal({ show: false })}>Close</Button>
</div>
)
let modalTitle = 'Error'
return (
<dialog aria-modal='true' open={showModal.show} className='dialog'>
<div className=''>
<h1>{modalTitle}</h1>
</div>
{modalContent}
</dialog>
)
}
export default Modal
And thats my App file
function App() {
const [toDos, setToDos] = useState(DummyToDos)
const [showModal, setShowModal] = useState<HandleModal>({
show: false,
})
const addToDo = (todo: Todo) => {
setToDos(prevState => {
return [todo, ...prevState]
})
}
const editToDo = (id: number, value: string) => {
const editedToDos = [...toDos].map(todo => {
if (todo.id === id) {
todo.text = value
}
return todo
})
setToDos(editedToDos)
setShowModal({
show: false,
})
}
const deleteToDo = (id: number) => {
const newToDos = toDos.filter(todo => todo.id !== id)
setToDos(newToDos)
}
const completeToDo = (id: number) => {
const completedToDos = [...toDos].map(todo => {
if (todo.id === id) {
todo.complete = !todo.complete
}
return todo
})
setToDos(completedToDos)
}
return (
<div className='mx-auto flex h-96 w-10/12 flex-col items-center text-center'>
<Header add={addToDo} showModal={setShowModal} />
<ToDoList items={toDos} edit={setShowModal} complete={completeToDo} del={deleteToDo} />
<Modal edit={editToDo} showModal={showModal} closeModal={setShowModal}/>
</div>
)
}
export default App
I can open this component chaning open attribute to true but it opens as dialog and not modal. I've tried setting aria-modal to true to force it to open as modal - sadly it doesnt work. I do not know where and on what exactly should I call .showModal() method
You need to have a ref to that dialog element and close or open dialog depending on your showModal.show state
const dialogRef = useRef<HTMLDialogElement>(null)
useLayoutEffect(() => {
if (dialogRef.current?.open && !showModal.show) {
dialogRef.current.close()
} else if (!dialogRef.current?.open && showModal.show) {
dialogRef.current.showModal()
}
}, [showModal.show])
// ...
return (
<dialog ref={dialogRef}>
...
</dialog>
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With