Dialog
StabilnyOkno nałożone na stronę, które skupia uwagę na jednym zadaniu i blokuje wszystko inne, dopóki zadanie nie zostanie zakończone albo okno zamknięte.
Instalacja
$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/dialog.jsonUżycie
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"<Dialog>
<DialogTrigger render={<Button variant="outline" />}>Edit profile</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Edit profile</DialogTitle>
<DialogDescription>Changes are visible to everyone in your workspace.</DialogDescription>
</DialogHeader>
{/* … */}
<DialogFooter>
<DialogClose render={<Button variant="outline" />}>Cancel</DialogClose>
<Button>Save changes</Button>
</DialogFooter>
</DialogContent>
</Dialog>DialogContent sam renderuje portal, przyciemnione tło i okno. Wyzwalacze i przyciski zamykania przyjmują prop render, więc element, który otwiera okno, jest prawdziwym Button z prfct, a nie opakowaniem wokół niego.
Przykłady
Formularz
Najczęstsze okno dialogowe: krótki formularz, który edytuje jedną rzecz. Po otwarciu okna fokus trafia do pierwszego pola, a po zamknięciu wraca do wyzwalacza. Ogranicz się do kilku pól — wszystko dłuższe zasługuje na osobną stronę albo Sheet. Umieść pola i stopkę w jednym elemencie <form>, żeby Enter wysyłał formularz.
Przewijana treść
Gdy treść jest wyższa niż obszar widoku, przewijaj tylko środkową część okna, żeby tytuł i akcje pozostały widoczne. Samo okno nigdy nie jest większe niż obszar widoku pomniejszony o margines 1 rem z każdej strony.
Tryb kontrolowany
Okna otwierane z pozycji menu, skrótem klawiszowym albo po zakończeniu operacji asynchronicznej nie mają własnego wyzwalacza. Wyrenderuj okno poza menu i steruj nim za pomocą open i onOpenChange.
const [open, setOpen] = React.useState(false)
<DropdownMenuItem onClick={() => setOpen(true)}>Rename…</DropdownMenuItem>
<Dialog open={open} onOpenChange={setOpen}>
<DialogContent>{/* … */}</DialogContent>
</Dialog>Stopka
DialogFooter to pas z delikatnie zabarwionym tłem, przylegający do dolnej krawędzi. Akcje umieszczaj po prawej, dodatkowy kontekst po lewej, a gdy okno potrzebuje tylko drogi wyjścia, użyj showCloseButton.
Szerokość
Domyślna maksymalna szerokość to max-w-lg (32 rem) — w sam raz dla formularza. Dla treści pomocniczych, np. listy skrótów, poszerz okno klasą max-w-*, ale zachowaj boczny margines: okno ma zawsze najwyżej calc(100% - 2rem) szerokości.
Wytyczne
Kiedy używać
- Aby zebrać niewielką ilość danych bez opuszczania strony: zmiana nazwy, zaproszenie, edycja kilku pól.
- Aby pokazać informację, którą trzeba potwierdzić, zanim przejdzie się dalej.
- Aby potwierdzić zadanie rozpoczęte na bieżącej stronie, z kontekstem wystarczającym do podjęcia decyzji.
Kiedy nie używać
- Do potwierdzania akcji nieodwracalnych lub niszczących dane — użyj Alert Dialog, którego nie da się zamknąć kliknięciem obok.
- Do długich formularzy, procesów wieloetapowych i wszystkiego, co trzeba porównywać z zawartością strony — użyj Sheet albo osobnej strony.
- Do komunikatu o powodzeniu akcji — użyj Toast. Przerywanie pracy tylko po to, żeby powiedzieć, że wszystko poszło dobrze, to podatek od każdego zadania.
- Do kontrolek kontekstowych powiązanych z jednym elementem — użyj Popover.
Wybór nakładki
Każda nakładka to kompromis między skupieniem uwagi a zachowaniem kontekstu. Wybierz najlżejszą, która wystarczy do zadania.
Jak pisać
Tytuł okna powinien mówić, co ono robi, a nie zadawać pytanie, które potem powtarzasz: Edytuj profil, Zaproś do zespołu. Główny przycisk nazwij od rezultatu i powtórz kluczowy rzeczownik, jeśli to pomaga: Zapisz zmiany, Wyślij 3 zaproszenia. Opis jest opcjonalny, ale zwykle warto poświęcić mu jedno zdanie kontekstu.
Jedno okno naraz
Nigdy nie otwieraj okna dialogowego na innym oknie dialogowym. Jeśli zadanie wymaga drugiego kroku, podmień zawartość pierwszego okna albo przenieś cały proces na osobną stronę.
Dostępność
Okno realizuje wzorzec WAI-ARIA dialog. Base UI renderuje je z role="dialog" i aria-modal, nadaje mu nazwę z DialogTitle i opis z DialogDescription.
| Klawisz | Działanie |
|---|---|
EnterSpacja | Na wyzwalaczu: otwiera okno i przenosi do niego fokus. |
Tab | Przenosi fokus do następnego elementu, który może go przyjąć. Fokus nie wychodzi poza okno. |
ShiftTab | Przenosi fokus do poprzedniego elementu, który może go przyjąć; na początku przeskakuje na koniec. |
Esc | Zamyka okno i przywraca fokus do elementu, który je otworzył. |
- Zawsze dodawaj tytuł.
DialogTitlenadaje oknu dostępną nazwę. Jeśli projekt nie przewiduje widocznego tytułu, zostaw go i dodajclassName="sr-only". - Fokus. Po otwarciu fokus trafia do pierwszego elementu, który może go przyjąć — a przy otwarciu dotykiem do samego okna, żeby nie wysuwała się klawiatura ekranowa. Zmienisz to propsami
initialFocusifinalFocusnaDialogContent. - Reszta strony jest nieaktywna. Gdy okno modalne jest otwarte, przewijanie strony jest zablokowane, a treść poza oknem jest nieosiągalna dla myszy, klawiatury i czytnika ekranu.
- Droga wyjścia. Zostaw przycisk zamykania (
showCloseButton, domyślnie włączony) albo przyciskDialogClosew stopce. Osoby korzystające z czytnika ekranu na urządzeniu dotykowym nie mogą nacisnąć Esc. - Ruch. Okno pojawia się z przenikaniem i skalowaniem w ciągu 320 ms, z krzywą przejścia
enter, a znika szybciej, niż się pojawiło. Przy ograniczonym ruchu pojawia się natychmiast.
Dokumentacja API
Dialog
Komponent główny. Nie renderuje żadnego elementu. Przyjmuje wszystkie propsy Dialog.Root z Base UI.
DialogTrigger
Otwiera okno. Renderuje <button>; użyj render, żeby wyrenderować Button z prfct.
DialogContent
Renderuje portal, przyciemnione tło i samo okno.
DialogHeader, DialogTitle, DialogDescription
DialogHeader układa tytuł i opis jeden pod drugim i rezerwuje miejsce na przycisk zamykania. DialogTitle renderuje <h2> i nadaje oknu nazwę; DialogDescription renderuje <p> i je opisuje.
DialogFooter
Pas z delikatnie zabarwionym tłem, przylegający do dolnej krawędzi okna. Na małych ekranach układa akcje jedna pod drugą, od sm wzwyż wyrównuje je do prawej.
DialogClose
Zamyka okno. Renderuje <button>; użyj render, żeby wyrenderować Button z prfct.