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 ponent 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 ponent
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 pleteToDo = (id: number) => {
const pletedToDos = [...toDos].map(todo => {
if (todo.id === id) {
todoplete = !todoplete
}
return todo
})
setToDos(pletedToDos)
}
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} plete={pleteToDo} del={deleteToDo} />
<Modal edit={editToDo} showModal={showModal} closeModal={setShowModal}/>
</div>
)
}
export default App
I can open this ponent 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
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 ponent 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 ponent
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 pleteToDo = (id: number) => {
const pletedToDos = [...toDos].map(todo => {
if (todo.id === id) {
todo.plete = !todo.plete
}
return todo
})
setToDos(pletedToDos)
}
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} plete={pleteToDo} del={deleteToDo} />
<Modal edit={editToDo} showModal={showModal} closeModal={setShowModal}/>
</div>
)
}
export default App
I can open this ponent 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
Share Improve this question asked Jun 27, 2023 at 17:07 Jakub KamińskiJakub Kamiński 531 silver badge3 bronze badges1 Answer
Reset to default 6You 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)
useEffect(() => {
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>
)