@akhatmirzo/ui

Dialog

Modal oyna: forma va tasdiqlash uchun, telefonda pastdan chiqadi; imperativ confirm() bilan.

Import

import { Dialog, ConfirmDialog, ConfirmProvider, confirm } from '@akhatmirzo/ui';

Qachon ishlatish

  • Diqqatni bitta vazifaga qaratish kerak bo'lsa — qisqa forma, tafsilotlarni tahrirlash, muhim ogohlantirish. Foydalanuvchi oynani yopmaguncha sahifa bilan ishlay olmaydi.
  • Xavfli amalni tasdiqlash — confirm() yoki ConfirmDialog. Bitta qator kod bilan true / false javob olasiz.
  • Uzun forma yoki filtrlar uchun yon panel — Drawer qulayroq: sahifa konteksti ko'rinib turadi.
  • Kichik, bog'lanmagan kontent (filtr, rang tanlash) uchun modal kerak emas — Popover oling.
  • Natija haqida xabar ("Saqlandi") uchun oyna ochmang — toast() yetarli.

Tuzilishi

Dialog — holatni boshqaradi (open, defaultOpen, onOpenChange). Qolgan qismlar:

QismVazifasi
Dialog.TriggerOchuvchi element. asChild bilan o'zingizning tugmangizni bering
Dialog.ContentOynaning o'zi: fon, sarlavha, izoh, ✕ tugmasi, fokus tuzog'i
Dialog.FooterPastki tugmalar qatori — o'ngga tekislangan, 8px oraliq
Dialog.CloseBosilganda oynani yopadigan element (asChild bilan)
<Dialog open={open} onOpenChange={setOpen}>
  <Dialog.Trigger asChild>
    <Button>Ochish</Button>
  </Dialog.Trigger>
  <Dialog.Content title="Profilni tahrirlash" description="O'zgarishlar darhol saqlanadi.">
    {/* forma */}
    <Dialog.Footer>
      <Dialog.Close asChild>
        <Button>Bekor qilish</Button>
      </Dialog.Close>
      <Button variant="primary">Saqlash</Button>
    </Dialog.Footer>
  </Dialog.Content>
</Dialog>

title — majburiy: ekran o'quvchi oynani shu nom bilan e'lon qiladi. Ko'rinmasligi kerak bo'lsa, hideTitle qo'ying, lekin olib tashlamang.

O'lchamlar

size oyna kengligini belgilaydi: sm — 400px, md — 520px (standart), lg — 640px, xl — 800px, full — butun ekran. Balandlik ekrandan 32px kam bo'lishi mumkin, kontent uzun bo'lsa oyna ichida scroll paydo bo'ladi.

Sozlamalar

  • dismissible={false} — tashqariga bosish oynani yopmaydi (Esc ishlayveradi).
  • closeButton={false} — o'ng yuqoridagi ✕ tugmasini olib tashlaydi.
  • hideTitle — sarlavhani ko'rinmas qiladi, ekran o'quvchi uni baribir o'qiydi.
  • mobileSheet={false} — telefonda (640px dan tor ekranda) ham oyna markazda qoladi. Standart holatda u pastdan chiqadigan sheet'ga aylanadi.

Yuborish paytida

Forma yuborilayotganda oynani tasodifan yopib qo'ymaslik uchun dismissible ni o'chiring va onOpenChange da yopilishni to'xtating — shunda tashqariga bosish ham, Esc ham ishlamaydi.

Tasdiqlash: confirm()

confirm() — imperativ API: oynani ochadi va Promise<boolean> qaytaradi. "Tasdiqlash" — true, "Bekor qilish", Esc yoki tashqariga bosish — false.

const ok = await confirm({
  title: "Buyurtma o'chirilsinmi?",
  description: "Bu amalni qaytarib bo'lmaydi.",
  confirmText: "O'chirish",
  variant: 'danger',
});
if (ok) await deleteOrder(id);
  • variant: 'danger' — tasdiqlash tugmasi qizil, dastlabki fokus "Bekor qilish" da: foydalanuvchi Enter ni tasodifan bosib, ma'lumotni o'chirib yubormaydi.
  • onConfirm Promise qaytarsa — tugma loading holatiga o'tadi, oyna javob kelguncha yopilmaydi (Esc va tashqariga bosish ham ishlamaydi). Promise xato bilan tugasa, oyna ochiq qoladi — foydalanuvchi qayta urinadi yoki bekor qiladi.

ConfirmProvider shart

confirm() ishlashi uchun ilovada bir marta <ConfirmProvider /> turishi kerak. U bo'lmasa, confirm() "ilovada <ConfirmProvider /> topilmadi" xatosi bilan rad etiladi.

app/providers.tsx
'use client';

import { ConfirmProvider } from '@akhatmirzo/ui';
import type { ReactNode } from 'react';

export function Providers({ children }: { children: ReactNode }) {
  return <ConfirmProvider>{children}</ConfirmProvider>;
}

ConfirmProvider ilovani o'rab olishi ham, yonida yolg'iz turishi ham mumkin. Uning labels prop'i barcha confirm() oynalari uchun standart tugma matnlarini o'rnatadi: labels={{ confirm: 'Confirm', cancel: 'Cancel' }}.

ConfirmDialog — deklarativ variant

Tasdiqlash oynasi JSX'da turishi kerak bo'lsa (masalan, aniq trigger bilan), ConfirmDialog dan foydalaning. Opsiyalari confirm() bilan bir xil, ustiga trigger va onCancel.

Dialog ichida Select va Combobox

Dialog.Content ichidagi Select, Combobox, DropdownMenu va Popover modal qatlamini o'zi aniqlaydi: paneli oyna ustida ochiladi va fokus tuzog'i ularga xalaqit bermaydi. Hech qanday z-index yoki container sozlash shart emas. Drawer ichida ham xuddi shunday.

Props

Dialog

Radix Dialog Root prop'larini qabul qiladi.

PropTipStandartTavsif
openboolean—Ochiqmi (boshqariladigan rejim)
defaultOpenboolean—Boshlang'ich holatda ochiq
onOpenChange(open: boolean) => void—Ochilib-yopilganda
modalbooleantrueSahifaning qolgan qismini bloklaydi

Dialog.Content

Qolgan <div> atributlari, ref va Radix hodisalari (onEscapeKeyDown, onOpenAutoFocus, onInteractOutside ...) panelga uzatiladi.

PropTipStandartTavsif
titlemajburiyReactNode—Sarlavha — ekran o'quvchi uchun ham
descriptionReactNode—Sarlavha ostidagi izoh
size'sm' | 'md' | 'lg' | 'xl' | 'full''md'400 / 520 / 640 / 800px / butun ekran
hideTitlebooleanfalseSarlavhani ko'rinmas qiladi (ekran o'quvchi o'qiydi)
closeButtonbooleantrueO'ng yuqorida ✕ tugmasi
dismissiblebooleantruefalse — tashqariga bosish yopmaydi (Esc ishlaydi)
mobileSheetbooleantrue640px dan tor ekranda pastdan chiqadigan sheet
overlayClassNamestring—Fon (overlay) uchun klass
containerHTMLElement | null—Portal konteyneri (standart — document.body)
labels{ close?: string }{ close: 'Yopish' }✕ tugmasining nomi

Dialog.Trigger, Dialog.Close

Ikkalasi ham asChild qabul qiladi — o'z elementingizni (odatda Button) bering. Dialog.Footer — oddiy <div>, barcha div atributlarini oladi.

confirm() va ConfirmDialog

confirm(options): Promise<boolean>. ConfirmDialog xuddi shu opsiyalarni prop sifatida oladi.

PropTipStandartTavsif
titlemajburiyReactNode—Savol
descriptionReactNode—Qisqa izoh
confirmTextReactNode'Tasdiqlash'Tasdiqlash tugmasi matni
cancelTextReactNode'Bekor qilish'Bekor qilish tugmasi matni
variant'default' | 'danger''default'danger — qizil tugma, fokus 'Bekor qilish' da
onConfirm() => unknown—Promise qaytarsa — loading, tugaguncha yopilmaydi; xatoda ochiq qoladi

Faqat ConfirmDialog uchun:

PropTipStandartTavsif
triggerReactNode—Ochuvchi element
openboolean—Boshqariladigan rejim
defaultOpenbooleanfalseBoshida ochiq
onOpenChange(open: boolean) => void—Ochilib-yopilganda
onCancel() => void—Bekor qilinganda (tugma, Esc yoki tashqariga bosish)
labels{ confirm?: string; cancel?: string }—Standart tugma matnlari

ConfirmProvider

PropTipStandartTavsif
labels{ confirm?: string; cancel?: string }—Barcha confirm() oynalari uchun standart matnlar
childrenReactNode—Ixtiyoriy: ilovani o'rab olishi mumkin

Data atributlari

AtributQayerdaQiymat
data-statepanelopen · closed
data-sizepanelsm · md · lg · xl · full
data-sheetpaneltelefonda sheet ko'rinishida bo'lganda mavjud

Dastlabki fokusni o'zingiz tanlamoqchi bo'lsangiz, kerakli elementga data-autofocus atributini qo'ying.

Klaviatura

TugmaHarakat
TabOyna ichidagi keyingi element (fokus oynadan chiqmaydi)
Shift + TabOldingi element
EscOynani yopadi, fokus ochgan elementga qaytadi

Accessibility

  • Rol va nom. Panel — role="dialog" (confirm() va ConfirmDialog da — role="alertdialog"), aria-labelledby sarlavhaga, aria-describedby izohga ulanadi. Izoh bo'lmasa, aria-describedby umuman qo'yilmaydi.
  • Fokus tuzog'i. Ochiq paytda fokus oyna ichida aylanadi, sahifaning qolgan qismi ekran o'quvchidan yashiriladi va scroll qilinmaydi.
  • Dastlabki fokus: [data-autofocus] → birinchi maydon (input, textarea, select) → birinchi tugma (✕ dan tashqari) → panelning o'zi.
  • Fokusni qaytarish. Yopilgach fokus Dialog.Trigger ga qaytadi. Trigger bo'lmasa (boshqariladigan rejim yoki confirm()), oyna ochilishidan oldin fokusda bo'lgan elementga qaytadi.
  • ✕ tugmasi "Yopish" nomini oladi — labels.close bilan o'zgartiriladi.
  • Kamroq harakat. prefers-reduced-motion yoqilgan bo'lsa, siljish o'rniga faqat shaffoflik animatsiyasi ishlaydi.

Sahifada