Dialog
Odaklı bir iş için modal pencere. Açıkken focus içeride tutulur, kapanınca tetikleyiciye geri döner.
Import
import { Dialog } from "@merid/react";<Dialog.Root>
<Dialog.Trigger asChild>
<Button variant="secondary">Profili düzenle</Button>
</Dialog.Trigger>
<Dialog.Content closeLabel="Kapat">
<Dialog.Title>Profili düzenle</Dialog.Title>
<Dialog.Description>Değişiklikleri çalışma alanındaki herkes görür.</Dialog.Description>
<Field label="Görünen ad">
<Input defaultValue="Ada Lovelace" />
</Field>
<Field label="Rol">
<Select.Root defaultValue="editor">
<Select.Trigger />
<Select.Content>
<Select.Item value="viewer">İzleyici</Select.Item>
<Select.Item value="editor">Editör</Select.Item>
<Select.Item value="admin">Yönetici</Select.Item>
</Select.Content>
</Select.Root>
</Field>
<Dialog.Footer>
<Dialog.Close>Vazgeç</Dialog.Close>
<Dialog.Close asChild>
<Button variant="primary">Kaydet</Button>
</Dialog.Close>
</Dialog.Footer>
</Dialog.Content>
</Dialog.Root>Anatomi
<Dialog.Root>
<Dialog.Trigger />
<Dialog.Content>
<Dialog.Title />
<Dialog.Description />
<Dialog.Footer>
<Dialog.Close>Vazgeç</Dialog.Close>
</Dialog.Footer>
</Dialog.Content>
</Dialog.Root>- Root açık/kapalı state'ini tutar. Kendisi bir eleman render'lamaz.
- Trigger, dialog'u açıp kapatan bir
<button>'dır. Onun yerine kendi elemanını (örneğin birButton) render'lamak içinasChildver. - Content modal yüzeydir; arka planla (backdrop) birlikte
document.body'ye portal'lanır. Maksimum genişliğinisizebelirler. - Title dialog'u etiketler (
aria-labelledby). Her zaman bir tane ekle. - Description varsa
aria-describedbyile bağlanır. - Footer aksiyonları sağa hizalı dizer.
- Close metin içerikle kullanıldığında secondary bir Button render'lar; farklı bir eleman (örneğin primary bir
Button) vermek içinasChildkullan. Content sağ üstteki ikonlu kapatma butonunu kendiliğinden ekler (showClose, varsayılan olarak açık). İçeriksiz birCloserender'larsan o ikon butonu sen yerleştirmiş olursun, otomatik olan kenara çekilir. - Content içinde açılan popover, menü, select ve tooltip'ler dialog'un üstünde katmanlanır; dialog içindeki bir formda
Selectek ayar gerektirmeden çalışır.
Örnekler
Boyutlar
size maksimum genişliği belirler: sm 440px, md 560px (varsayılan), lg 720px, full ise kenarlarda 16px boşluk bırakarak viewport'un tamamı. 640px ve altında her boyut alttan açılan bir sheet'e dönüşür.
<Dialog.Content size="sm">…</Dialog.Content>
<Dialog.Content size="md">…</Dialog.Content>
<Dialog.Content size="lg">…</Dialog.Content>
<Dialog.Content size="full">…</Dialog.Content>Controlled
State'i kendi component'inde tutmak için open ve onOpenChange ver. Örneğin dialog'u bir Trigger dışında bir yerden açman gerektiğinde.
const [open, setOpen] = useState(false);
<Button variant="secondary" onClick={() => setOpen(true)}>State'ten aç</Button>
<Dialog.Root open={open} onOpenChange={setOpen}>
<Dialog.Content>
<Dialog.Title>Controlled dialog</Dialog.Title>
<Dialog.Description>Açık/kapalı state'i üst component'te tutuluyor.</Dialog.Description>
<Dialog.Footer>
<Button variant="primary" onClick={() => setOpen(false)}>Tamam</Button>
</Dialog.Footer>
</Dialog.Content>
</Dialog.Root>İlk focus
Focus önce initialFocus ile verilen elemana, yoksa data-autofocus taşıyan elemana, o da yoksa ilk tab'lanabilir elemana gider.
<Dialog.Content>
<Dialog.Title>Yeniden adlandır</Dialog.Title>
<Input data-autofocus defaultValue="Northwind" />
</Dialog.Content>Kapatmayı engellemek
Kaydedilmemiş işin kaybolması pahalıya patlayacaksa closeOnOutsidePress={false} ya da closeOnEscape={false} ver. Onaylar için AlertDialog'u tercih et.
API referansı
Dialog.Root
| Prop | Tip | Varsayılan | Açıklama |
|---|---|---|---|
open | boolean | – | Controlled açık/kapalı state'i. |
defaultOpen | boolean | false | Uncontrolled kullanımda başlangıç state'i. |
onOpenChange | (open: boolean) => void | – | Açık/kapalı state'i değişmesi gerektiğinde çağrılır. |
children | ReactNode | – | Trigger, Content ve bu dialog'un state'ini paylaşan diğer her şey. |
Dialog.Trigger
Tüm <button> attribute'larını kabul eder. type varsayılan olarak "button"'dır (asChild kullanıldığında atanmaz).
| Prop | Tip | Varsayılan | Açıklama |
|---|---|---|---|
asChild | boolean | false | `<button>` yerine tek child elemanı (örneğin kendi `Button`'ını) render'lar; props, ref ve handler'ları birleştirir. |
ref | Ref<HTMLButtonElement> | – | Butona iletilen ref. |
Dialog.Content
role dışındaki tüm <div> attribute'larını kabul eder.
| Prop | Tip | Varsayılan | Açıklama |
|---|---|---|---|
size | DialogSize | "md" | Maksimum genişlik: `sm` 440px, `md` 560px, `lg` 720px, `full` kenarlarda 16px boşlukla viewport'un tamamı. `DialogSize` tipi `"sm" | "md" | "lg" | "full"`. |
closeOnOutsidePress | boolean | true | Arka plana basıldığında kapanır. |
closeOnEscape | boolean | true | Escape ile kapanır. |
initialFocus | RefObject<HTMLElement | null> | – | Açılınca focus alacak eleman. Verilmezse önce [data-autofocus], sonra ilk tab'lanabilir eleman. |
container | Element | null | document.body | Portal hedefi. `undefined` verilirse `document.body` kullanılır; `null` verilirse hedef oluşana kadar hiçbir şey render'lanmaz. |
showClose | boolean | true | Sağ üstteki standart ikonlu kapatma butonunu otomatik render'lar. Kendi ikonlu `Close`'unu render'ladığında atlanır. |
closeLabel | string | "Close" | Otomatik kapatma butonunun erişilebilir adı. Türkçe arayüzde `"Kapat"` ver. |
ref | Ref<HTMLDivElement> | – | Dialog elemanına iletilen ref. |
Dialog.Title
Bir <h2> render'lar. Tüm başlık attribute'larını kabul eder.
| Prop | Tip | Varsayılan | Açıklama |
|---|---|---|---|
ref | Ref<HTMLHeadingElement> | – | Başlığa iletilen ref. |
Dialog.Description
Bir <p> render'lar. Tüm paragraf attribute'larını kabul eder.
| Prop | Tip | Varsayılan | Açıklama |
|---|---|---|---|
ref | Ref<HTMLParagraphElement> | – | Paragrafa iletilen ref. |
Dialog.Close
Tüm <button> attribute'larını kabul eder.
| Prop | Tip | Varsayılan | Açıklama |
|---|---|---|---|
icon | boolean | içerik yoksa true | Sağ üstteki standart ikon butonunu render'lar. false olduğunda (içerik verildiyse varsayılan budur) içeriği secondary bir Button olarak render'lar. |
asChild | boolean | false | `<button>` yerine tek child elemanı (örneğin kendi `Button`'ını) render'lar; props, ref ve handler'ları birleştirir. |
ref | Ref<HTMLButtonElement> | – | Butona iletilen ref. |
Dialog.Footer
Bir <div> render'lar ve tüm <div> attribute'larını kabul eder; ek prop'u yoktur.
Stil verme
| Sınıf | Eleman |
|---|---|
.mrd-dialog__backdrop | Sabit arka plan, var(--mrd-backdrop) |
.mrd-dialog | Yüzey: maksimum genişlik data-size'dan gelir (440 / 560 / 720px / full), --mrd-radius-card, --mrd-shadow-2xl |
.mrd-dialog__title | Başlık |
.mrd-dialog__description | Açıklama metni |
.mrd-dialog__footer | Aksiyon satırı |
.mrd-dialog__close | İkonlu kapatma butonu |
Content data-size taşır; content ve backdrop DOM'dayken data-state="open" taşır; tetikleyici data-state="open" | "closed" taşır. 640px ve altında dialog alttan açılan bir sheet'e dönüşür, footer'daki aksiyonlar alt alta dizilir. Kullanılan token'lar: --mrd-backdrop, --mrd-surface, --mrd-z-overlay, --mrd-duration-enter. Dialog içinde açılan popover, menü, select ve tooltip'ler onun üstünde katmanlanır (--mrd-z-popover, --mrd-z-tooltip). Metin içerikli bir Close, data-variant="secondary" ile .mrd-button olarak render'lanır. Trigger'a ya da farklı varyantta bir Close'a stil vermek için asChild ile bir Button ver.
Erişilebilirlik
WAI-ARIA Dialog (Modal) desenini izler. Content role="dialog" ve aria-modal="true" taşır; Trigger aria-haspopup="dialog" ve aria-expanded taşır. Açıkken sayfanın scroll'u kilitlenir.
| Tuş | Ne yapar |
|---|---|
| SpaceEnter | Tetikleyicideyken dialog'u açar. |
| Tab | Focus'u dialog içindeki bir sonraki elemana taşır; sona gelince başa döner. |
| ShiftTab | Focus'u bir önceki elemana taşır; başa gelince sona döner. |
| Esc | Dialog'u kapatır ve focus'u tetikleyiciye döndürür. |
Kullanım ilkeleri
Yap
Kaçın
Yap
Kaçın
İlgili sayfalar
- AlertDialog: yanıt bekleyen onaylar için.
- Drawer: sayfanın yanında duran uzun içerik için.
- Popover: modal olmayan, bir tetikleyiciye bağlı içerik için.