Docs/Componenti
// componente
Modal
Modal controllato con Headless UI: backdrop scuro, pannello centrato, animazioni di entrata/uscita, chiusura con click fuori, tasto Esc o la X in alto a destra. Client component. La visibilità la gestisci tu dall'esterno con una coppia useState.
File
components/Modal.tsx
Uso base
app/dashboard/page.tsx
tsx
"use client";
import { useState } from "react";
import Modal from "@/components/Modal";
export default function Page() {
const [isModalOpen, setIsModalOpen] = useState(false);
return (
<>
<button className="btn-brutal" onClick={() => setIsModalOpen(true)}>
Apri il modal
</button>
<Modal isModalOpen={isModalOpen} setIsModalOpen={setIsModalOpen} />
</>
);
}Props
isModalOpen: boolean— obbligatoria. Passa aTransition show:truemonta e anima il modal.setIsModalOpen: React.Dispatch<React.SetStateAction<boolean>>— obbligatoria. È il setter dellouseStatedel genitore. Viene chiamato confalsesia dalla X sia daonClosedelDialog(click fuori o Esc).
Proprio perché riceve una funzione come prop, il genitore deve essere un client component: non puoi passare un setter da un server component.
Personalizzare
Titolo (“I'm a modal”) e contenuto (“And here is my content”) sono hard-coded. Il primo cambio sensato è renderli props:
components/Modal.tsx
tsx
interface ModalProps {
isModalOpen: boolean;
setIsModalOpen: React.Dispatch<React.SetStateAction<boolean>>;
title?: string;
children?: React.ReactNode;
}
const Modal = ({ isModalOpen, setIsModalOpen, title, children }: ModalProps) => {
// ...
<Dialog.Title as="h2" className="font-semibold">
{title}
</Dialog.Title>
// ...
<section>{children}</section>
};- Larghezza:
max-w-3xlsulDialog.Panel— scendi amax-w-mdper una conferma, sali per un form lungo. - Stile: il pannello usa ancora
rounded-xl bg-base-100 shadow-xldi DaisyUI. Per il look del resto del sito sostituiscilo concard-brutalebackground: var(--cream). - Chiusura forzata: se il modal contiene un form che non deve essere chiuso per sbaglio, passa
onClose={() => {}}alDialoge lascia solo la X. - Backdrop: il
Transition.Childconbg-neutral-focus bg-opacity-50. Cambia colore e opacità lì.
Nel repo attuale nessuna pagina lo importa: è pronto da agganciare quando ti serve.