- Accordion
- Alert
- Alert Dialog
- Autocomplete
- Auth Surface
- Avatar
- Badge
- Browse Catalog Dialog
- Button
- Card
- Checkbox
- Checkbox Group
- Collapsible
- Combobox
- Command
- Connector Setup Dialog
- Cookie Banner
- Dialog
- Directory Card
- Directory Detail
- Directory Skeleton
- DrawerНовое
- Token Parts Input
- Empty
- Field
- Fieldset
- File Preview Modal
- File Preview Skeleton
- Form
- Frame
- Group
- Icon
- Input
- Input Group
- Kbd
- Label
- Legal Shell
- Menu
- Mermaid Diagram
- Mind Map Diagram
- Not Found Screen
- Onboarding Frame
- Popover
- PDF Thumbnail
- Personalization Landing
- Preview Card
- Pricing Page
- Progress
- Radio Group
- Ring Spinner
- Scroll Area
- Select
- Separator
- Settings Page
- Settings Skills
- Settings Connectors
- Settings Capabilities
- Settings Usage
- Settings Account
- Settings Billing
- Sheet
- Sidebar
- Skeleton
- Skill Create Dialog
- Slider
- Spinner
- Stat
- Switch
- Table
- Tabs
- Textarea
- Toast
- Toggle
- Tooltip
- Компоненты AI
- Chat Conversation
- Chat Message
- Chat Response
- Chat Suggestion
- Chat Prompt Input
- Slash Highlighted Textarea
- Chat Search Dialog
- Chat Skill Doc
- Chat Connector Detail
- Chat Attachments
- Chat File Card
- Chat Token Chip
- Chat Code Block
- Chat Image
- Chat Inline Citation
- Chat Sources
- Chat Web Search
- Chat Research
- Chat Source
- Chat Actions
- Chat Context
- Chat Loader
- Chat Compaction
- Chat Timeline
- Chat Snippet
- Chat Terminal
- Chat Stack Trace
- Chat Test Results
- Chat File Tree
- Chat Environment Variables
- Chat Audio Player
- Chat Transcription
- Chat Speech Input
- Chat Mic Selector
- Chat Voice Selector
- Chat Agent
- Chat Persona
- Chat Connection
- Chat Connector Suggestion
- Chat Queue
- Chat Checkpoint
- Chat Confirmation
- Chat Artifact
- Chat JSX Preview
- Chat Schema Display
- Chat Package Info
- Chat Commit
- Chat Plan
- Chat Open In Chat
- Chat Sandbox
- Chat Model Selector
- Chat Canvas
- Chat Node
- Chat Edge
Dialog
Всплывающее окно, которое открывается поверх всей страницы.
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogClose,
DialogDescription,
DialogFooter,
DialogHeader,
DialogPanel,
DialogPopup,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import { Field, FieldLabel } from "@/components/ui/field";
import { Form } from "@/components/ui/form";
import { Input } from "@/components/ui/input";
export default function Particle() {
return (
<Dialog>
<DialogTrigger render={<Button variant="outline" />}>
Открыть диалог
</DialogTrigger>
<DialogPopup className="sm:max-w-sm">
<DialogHeader>
<DialogTitle>Редактировать профиль</DialogTitle>
<DialogDescription>
Внесите изменения в профиль. Нажмите «Сохранить», когда закончите.
</DialogDescription>
</DialogHeader>
<Form className="contents">
<DialogPanel className="grid gap-4">
<Field>
<FieldLabel>Имя</FieldLabel>
<Input defaultValue="Маргарита Соколова" type="text" />
</Field>
<Field>
<FieldLabel>Имя пользователя</FieldLabel>
<Input defaultValue="@maggie.welsh" type="text" />
</Field>
</DialogPanel>
<DialogFooter>
<DialogClose render={<Button variant="ghost" />}>
Отмена
</DialogClose>
<Button type="submit">Сохранить</Button>
</DialogFooter>
</Form>
</DialogPopup>
</Dialog>
);
}
Установка
pnpm dlx shadcn@latest add @oracul/dialog
Использование
import {
Dialog,
DialogClose,
DialogDescription,
DialogPanel,
DialogFooter,
DialogHeader,
DialogPopup,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"<Dialog>
<DialogTrigger>Open Dialog</DialogTrigger>
<DialogPopup>
<DialogHeader>
<DialogTitle>Dialog Title</DialogTitle>
<DialogDescription>Dialog Description</DialogDescription>
</DialogHeader>
<DialogPanel>Content</DialogPanel>
<DialogFooter>
<DialogClose>Close</DialogClose>
</DialogFooter>
</DialogPopup>
</Dialog>API
Dialog
Корневой компонент. Псевдоним для Dialog.Root из Base UI.
DialogTrigger
Кнопка-триггер, открывающая диалог. Псевдоним для Dialog.Trigger из Base UI.
DialogCreateHandle
Создаёт хэндл для отсоединённых триггеров диалога. Используйте его, когда триггер и всплывающее окно нужно согласовать между разными частями дерева.
DialogPopup
Контейнер всплывающего окна, отображающий содержимое диалога. Также экспортируется как DialogContent.
| Свойство | Тип | По умолчанию | Описание |
|---|---|---|---|
showCloseButton | boolean | true | Если true, отображает кнопку закрытия в правом верхнем углу |
bottomStickOnMobile | boolean | true | Если true, прилипает к нижней части экрана на мобильных устройствах |
closeProps | Dialog.Close.Props | - | Свойства, передаваемые внутренней кнопке закрытия; удобно для переопределения aria-label |
portalProps | Dialog.Portal.Props | - | Свойства, передаваемые внутреннему порталу (keepMounted, container и т. д.); см. API портала Dialog в Base UI |
DialogHeader
Контейнер для заголовка и описания диалога. Поддерживает свойство render для полиморфной композиции (например, render={<Link href="/" />}).
DialogFooter
Секция футера для кнопок действий. Поддерживает свойство render для полиморфной композиции.
| Свойство | Тип | По умолчанию | Описание |
|---|---|---|---|
variant | "default" | "bare" | "default" | Управляет оформлением футера. default включает рамку и фон, bare убирает их |
Пример:
// Default variant (with border and background)
<DialogFooter>
<DialogClose>Cancel</DialogClose>
<Button>Save</Button>
</DialogFooter>
// Bare variant (no border or background)
<DialogFooter variant="bare">
<DialogClose>Cancel</DialogClose>
<Button>Save</Button>
</DialogFooter>DialogTitle
Компонент заголовка. Псевдоним для Dialog.Title из Base UI.
DialogDescription
Компонент описания. Псевдоним для Dialog.Description из Base UI.
DialogPanel
Прокручиваемый контейнер содержимого. Автоматически оборачивает содержимое в компонент ScrollArea. Поддерживает свойство render для полиморфной композиции.
| Свойство | Тип | По умолчанию | Описание |
|---|---|---|---|
scrollFade | boolean | true | Если true, показывает эффект затухания у краёв прокрутки |
Пример:
<DialogPanel>
{/* Long content that will scroll if it exceeds the dialog height */}
<div>...</div>
</DialogPanel>DialogClose
Компонент кнопки закрытия. Псевдоним для Dialog.Close из Base UI.
DialogPortal
Компонент портала для рендеринга вне иерархии DOM. Псевдоним для Dialog.Portal из Base UI.
DialogBackdrop
Компонент подложки/оверлея. Также экспортируется как DialogOverlay. Псевдоним для Dialog.Backdrop из Base UI.
DialogViewport
Компонент области просмотра для позиционирования. Псевдоним для Dialog.Viewport из Base UI.
Примеры
Открытие из меню
"use client";
import { useState } from "react";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogClose,
DialogDescription,
DialogFooter,
DialogHeader,
DialogPopup,
DialogTitle,
} from "@/components/ui/dialog";
import {
Menu,
MenuItem,
MenuPopup,
MenuTrigger,
} from "@/components/ui/menu";
export default function Particle() {
const [dialogOpen, setDialogOpen] = useState(false);
return (
<>
<Menu>
<MenuTrigger render={<Button variant="outline" />}>
Открыть меню
</MenuTrigger>
<MenuPopup align="start">
<MenuItem onClick={() => setDialogOpen(true)}>
Открыть диалог
</MenuItem>
</MenuPopup>
</Menu>
<Dialog onOpenChange={setDialogOpen} open={dialogOpen}>
<DialogPopup>
<DialogHeader>
<DialogTitle>Настройки</DialogTitle>
<DialogDescription>Измените свои предпочтения</DialogDescription>
</DialogHeader>
<DialogFooter>
<DialogClose render={<Button variant="ghost" />}>
Закрыть
</DialogClose>
</DialogFooter>
</DialogPopup>
</Dialog>
</>
);
}
Диалог с минималистичным футером
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogClose,
DialogDescription,
DialogFooter,
DialogHeader,
DialogPanel,
DialogPopup,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import { Field, FieldLabel } from "@/components/ui/field";
import { Form } from "@/components/ui/form";
import { Input } from "@/components/ui/input";
export default function Particle() {
return (
<Dialog>
<DialogTrigger render={<Button variant="outline" />}>
Открыть окно
</DialogTrigger>
<DialogPopup className="sm:max-w-sm">
<DialogHeader>
<DialogTitle>Редактирование профиля</DialogTitle>
<DialogDescription>
Внесите изменения в свой профиль. Нажмите «Сохранить», когда
закончите.
</DialogDescription>
</DialogHeader>
<Form className="contents">
<DialogPanel className="grid gap-4">
<Field>
<FieldLabel>Имя</FieldLabel>
<Input defaultValue="Маргарита Уэлш" type="text" />
</Field>
<Field>
<FieldLabel>Имя пользователя</FieldLabel>
<Input defaultValue="@maggie.welsh" type="text" />
</Field>
</DialogPanel>
<DialogFooter variant="bare">
<DialogClose render={<Button variant="ghost" />}>
Отмена
</DialogClose>
<Button type="submit">Сохранить</Button>
</DialogFooter>
</Form>
</DialogPopup>
</Dialog>
);
}
Диалог с прокруткой внутри
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogClose,
DialogFooter,
DialogHeader,
DialogPanel,
DialogPopup,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
export default function Particle() {
return (
<Dialog>
<DialogTrigger render={<Button variant="outline" />}>
Условия использования
</DialogTrigger>
<DialogPopup className="sm:max-w-md" showCloseButton={false}>
<DialogHeader>
<DialogTitle>Условия использования</DialogTitle>
</DialogHeader>
<DialogPanel>
<div className="flex flex-col gap-4 [&_strong]:font-semibold [&_strong]:text-foreground">
<div className="flex flex-col gap-4">
<div className="flex flex-col gap-1">
<p>
<strong>Принятие условий</strong>
</p>
<p>
Получая доступ к этому сайту и используя его, пользователи
соглашаются соблюдать настоящие Условия использования. Если
пользователь не согласен с этими условиями, ему следует
немедленно прекратить использование сайта.
</p>
</div>
<div className="flex flex-col gap-1">
<p>
<strong>Обязанности владельца учётной записи</strong>
</p>
<p>
Пользователи несут ответственность за сохранение
конфиденциальности своих учётных данных. Любые действия,
совершённые под учётной записью пользователя, являются
исключительной ответственностью её владельца. Пользователи
обязаны незамедлительно уведомлять администрацию сайта о любом
несанкционированном доступе к учётной записи.
</p>
</div>
<div className="flex flex-col gap-1">
<p>
<strong>Использование контента и ограничения</strong>
</p>
<p>
Сайт и размещённый на нём оригинальный контент защищены
законами об интеллектуальной собственности. Пользователи не
вправе воспроизводить, распространять, изменять, создавать
производные работы или использовать контент в коммерческих
целях без явного письменного разрешения владельцев сайта.
</p>
</div>
<div className="flex flex-col gap-1">
<p>
<strong>Ограничение ответственности</strong>
</p>
<p>
Сайт предоставляет контент «как есть», без каких-либо
гарантий. Владельцы сайта не несут ответственности за прямой,
косвенный, случайный, последующий или штрафной ущерб,
возникший в результате взаимодействия пользователя с
платформой.
</p>
</div>
<div className="flex flex-col gap-1">
<p>
<strong>Правила поведения пользователей</strong>
</p>
<ul className="list-disc pl-6">
<li>Не загружать вредоносный или опасный контент</li>
<li>Уважать права других пользователей</li>
<li>Избегать действий, способных нарушить работу сайта</li>
<li>Соблюдать применимые местные и международные законы</li>
</ul>
</div>
<div className="flex flex-col gap-1">
<p>
<strong>Изменение условий</strong>
</p>
<p>
Сайт оставляет за собой право в любое время вносить изменения
в настоящие условия. Продолжение использования сайта после
внесения изменений означает согласие с новыми условиями.
</p>
</div>
<div className="flex flex-col gap-1">
<p>
<strong>Прекращение доступа</strong>
</p>
<p>
Сайт может прекратить или приостановить доступ пользователя
без предварительного уведомления за нарушение настоящих
условий или по любой иной причине, которую администрация
сочтёт уместной.
</p>
</div>
<div className="flex flex-col gap-1">
<p>
<strong>Применимое право</strong>
</p>
<p>
Настоящие условия регулируются законодательством юрисдикции, в
которой преимущественно работает сайт, без учёта коллизионных
норм права.
</p>
</div>
</div>
</div>
</DialogPanel>
<DialogFooter>
<DialogClose render={<Button variant="ghost" />}>Отмена</DialogClose>
<Button type="button">Принимаю</Button>
</DialogFooter>
</DialogPopup>
</Dialog>
);
}
Вложенные диалоги
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogClose,
DialogDescription,
DialogFooter,
DialogHeader,
DialogPanel,
DialogPopup,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import { Field, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";
export default function Particle() {
return (
<Dialog>
<DialogTrigger render={<Button variant="outline" />}>
Открыть
</DialogTrigger>
<DialogPopup showCloseButton={false}>
<DialogHeader>
<DialogTitle>Управление участником команды</DialogTitle>
<DialogDescription>
Просмотр и управление пользователем в вашей команде.
</DialogDescription>
</DialogHeader>
<DialogPanel className="grid gap-4">
<div className="grid gap-1">
<p className="text-muted-foreground text-sm">Имя</p>
<p className="font-medium text-sm">Борис Балаглу</p>
</div>
<div className="grid gap-1">
<p className="text-muted-foreground text-sm">Эл. почта</p>
<p className="font-medium text-sm">bora@example.com</p>
</div>
</DialogPanel>
<DialogFooter>
<Dialog>
<DialogTrigger render={<Button variant="outline" />}>
Редактировать
</DialogTrigger>
<DialogPopup showCloseButton={false}>
<DialogHeader>
<DialogTitle>Редактирование данных</DialogTitle>
<DialogDescription>
Измените информацию об участнике.
</DialogDescription>
</DialogHeader>
<DialogPanel className="grid gap-4">
<Field>
<FieldLabel>Имя</FieldLabel>
<Input defaultValue="Борис Балаглу" type="text" />
</Field>
<Field>
<FieldLabel>Эл. почта</FieldLabel>
<Input defaultValue="bora@example.com" type="text" />
</Field>
</DialogPanel>
<DialogFooter>
<DialogClose render={<Button variant="ghost" />}>
Отмена
</DialogClose>
<Button type="submit">Сохранить изменения</Button>
</DialogFooter>
</DialogPopup>
</Dialog>
</DialogFooter>
</DialogPopup>
</Dialog>
);
}
Подтверждение закрытия
"use client";
import { useState } from "react";
import {
AlertDialog,
AlertDialogClose,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogPopup,
AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogClose,
DialogDescription,
DialogFooter,
DialogHeader,
DialogPanel,
DialogPopup,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import { Field } from "@/components/ui/field";
import { Form } from "@/components/ui/form";
import { Textarea } from "@/components/ui/textarea";
export default function Particle() {
const [dialogOpen, setDialogOpen] = useState(false);
const [confirmOpen, setConfirmOpen] = useState(false);
const [value, setValue] = useState("");
return (
<Dialog
onOpenChange={(o) => {
if (!o && value) {
setConfirmOpen(true);
} else {
setDialogOpen(o);
}
}}
open={dialogOpen}
>
<DialogTrigger render={<Button variant="outline" />}>
Написать
</DialogTrigger>
<DialogPopup showCloseButton={false}>
<DialogHeader>
<DialogTitle>Новое сообщение</DialogTitle>
<DialogDescription>
Введите текст и попробуйте закрыть окно.
</DialogDescription>
</DialogHeader>
<Form
className="contents"
onSubmit={(event) => {
event.preventDefault();
// Close the dialog when submitting
setDialogOpen(false);
}}
>
<DialogPanel>
<Field>
<Textarea
onChange={(e) => setValue(e.target.value)}
value={value}
/>
</Field>
</DialogPanel>
<DialogFooter>
<DialogClose render={<Button variant="ghost" />}>
Отмена
</DialogClose>
<Button
onClick={() => {
setValue("");
setDialogOpen(false);
}}
>
Отправить
</Button>
</DialogFooter>
</Form>
</DialogPopup>
{/* Confirmation dialog */}
<AlertDialog onOpenChange={setConfirmOpen} open={confirmOpen}>
<AlertDialogPopup>
<AlertDialogHeader>
<AlertDialogTitle>Отменить изменения?</AlertDialogTitle>
<AlertDialogDescription>
Ваше сообщение будет потеряно.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogClose render={<Button variant="ghost" />}>
Назад
</AlertDialogClose>
<Button
onClick={() => {
setConfirmOpen(false);
setValue("");
setDialogOpen(false);
}}
>
Отменить
</Button>
</AlertDialogFooter>
</AlertDialogPopup>
</AlertDialog>
</Dialog>
);
}
На этой странице