Chuyển tới nội dung
Component

Dialog

A modal window above a scrim, in five widths. Focus moves into it when it opens and goes back to the trigger when it closes. It uses shadow-high, the shadow kept for floating layers.

Xem trước

Props

  • open
  • defaultOpen
  • size
  • showCloseButton
  • title
import { Button } from "@/components/ui/button"
import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"

<Dialog>
  <DialogTrigger asChild>
    <Button>Rename project</Button>
  </DialogTrigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>Rename project</DialogTitle>
      <DialogDescription>Pick a name your team will recognize.</DialogDescription>
    </DialogHeader>
    <DialogFooter>
      <DialogClose asChild>
        <Button variant="secondary">Cancel</Button>
      </DialogClose>
      <Button>Save</Button>
    </DialogFooter>
  </DialogContent>
</Dialog>

Cách dùng

Khi nào dùng

  • A short task that should block the page until it is done or cancelled, such as renaming a project.
  • A confirmation that is not destructive.
  • A task that needs room, such as a table or a preview, with a larger size.

Khi nào không dùng

  • Confirming a destructive action. Use AlertDialog.
  • Long forms or reading. Give them their own page.
  • Opening a dialog from a dialog. Close the first one before the next one opens, or give the flow its own page.

Biến thể

size

Set on DialogContent. Widest the panel gets: sm 448px (short confirmations), md 512px (forms of a few fields), lg 672px, xl 896px (tables, previews), full the whole viewport minus spacing-lg on each side, in height too. On a narrow screen every size fills the width minus spacing-lg.

  • sm

  • mdmặc định

  • lg

  • xl

  • full

import { Button } from "@/components/ui/button"
import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"

<Dialog>
  <DialogTrigger asChild>
    <Button>Rename project</Button>
  </DialogTrigger>
  <DialogContent size="sm">
    <DialogHeader>
      <DialogTitle>Rename project</DialogTitle>
      <DialogDescription>Pick a name your team will recognize.</DialogDescription>
    </DialogHeader>
    <DialogFooter>
      <DialogClose asChild>
        <Button variant="secondary">Cancel</Button>
      </DialogClose>
      <Button>Save</Button>
    </DialogFooter>
  </DialogContent>
</Dialog>
<Dialog>
  <DialogTrigger asChild>
    <Button>Rename project</Button>
  </DialogTrigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>Rename project</DialogTitle>
      <DialogDescription>Pick a name your team will recognize.</DialogDescription>
    </DialogHeader>
    <DialogFooter>
      <DialogClose asChild>
        <Button variant="secondary">Cancel</Button>
      </DialogClose>
      <Button>Save</Button>
    </DialogFooter>
  </DialogContent>
</Dialog>
<Dialog>
  <DialogTrigger asChild>
    <Button>Rename project</Button>
  </DialogTrigger>
  <DialogContent size="lg">
    <DialogHeader>
      <DialogTitle>Rename project</DialogTitle>
      <DialogDescription>Pick a name your team will recognize.</DialogDescription>
    </DialogHeader>
    <DialogFooter>
      <DialogClose asChild>
        <Button variant="secondary">Cancel</Button>
      </DialogClose>
      <Button>Save</Button>
    </DialogFooter>
  </DialogContent>
</Dialog>
<Dialog>
  <DialogTrigger asChild>
    <Button>Rename project</Button>
  </DialogTrigger>
  <DialogContent size="xl">
    <DialogHeader>
      <DialogTitle>Rename project</DialogTitle>
      <DialogDescription>Pick a name your team will recognize.</DialogDescription>
    </DialogHeader>
    <DialogFooter>
      <DialogClose asChild>
        <Button variant="secondary">Cancel</Button>
      </DialogClose>
      <Button>Save</Button>
    </DialogFooter>
  </DialogContent>
</Dialog>
<Dialog>
  <DialogTrigger asChild>
    <Button>Rename project</Button>
  </DialogTrigger>
  <DialogContent size="full">
    <DialogHeader>
      <DialogTitle>Rename project</DialogTitle>
      <DialogDescription>Pick a name your team will recognize.</DialogDescription>
    </DialogHeader>
    <DialogFooter>
      <DialogClose asChild>
        <Button variant="secondary">Cancel</Button>
      </DialogClose>
      <Button>Save</Button>
    </DialogFooter>
  </DialogContent>
</Dialog>

Ví dụ

Default

import { Button } from "@/components/ui/button"
import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"

<Dialog>
  <DialogTrigger asChild>
    <Button>Rename project</Button>
  </DialogTrigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>Rename project</DialogTitle>
      <DialogDescription>Pick a name your team will recognize.</DialogDescription>
    </DialogHeader>
    <DialogFooter>
      <DialogClose asChild>
        <Button variant="secondary">Cancel</Button>
      </DialogClose>
      <Button>Save</Button>
    </DialogFooter>
  </DialogContent>
</Dialog>

Nên và không nên

Nên

  • Use a dialog for a short task or a confirmation that should block the page until done or cancelled.
  • Pick the smallest size that fits the content: sm for a sentence and two buttons, md for a short form, lg or xl for tables and previews. Long content scrolls inside the panel, which stays spacing-lg from the viewport edges.
  • Let Escape, the close button and a scrim click close it.
  • Open and close without animation (current behavior). If an animation is added later, reduced motion gets a fade only.
  • Return focus to the trigger on close.

Không nên

  • Don't use Dialog to confirm a destructive action. Use AlertDialog, which focuses Cancel first and doesn't close on a scrim click.
  • Don't open a dialog from a dialog.
  • Don't use a dialog for long forms or reading; use a page or sheet. A bigger size does not make a long form short.
  • Don't use size full for a short task; the user loses sight of the page they came from.
  • Don't leave out DialogTitle. If it shouldn't show, make it sr-only.
  • Don't remove shadow-high from the panel. A dialog floats above the page, so a border alone isn't enough.

Props

TênKiểuGiá trịMặc địnhMô tả
openboolean--Set on Dialog. Whether the dialog is open, when you control it. Pair it with onOpenChange. Chỉ trên web.
defaultOpenboolean-falseSet on Dialog. Opens the dialog on first render, when you don't control it. Chỉ trên web.
onOpenChangefunction--Set on Dialog. Called with true or false when the dialog opens or closes (trigger, close button, Escape, scrim). Chỉ trên web.
modalboolean-trueSet on Dialog. true traps focus and hides the rest of the page from assistive tech. Keep it true; false only for a panel the user works next to, which is better as a sheet. Chỉ trên web.
sizeenumsm | md | lg | xl | fullmdSet on DialogContent. Widest the panel gets: sm 448px (short confirmations), md 512px (forms of a few fields), lg 672px, xl 896px (tables, previews), full the whole viewport minus spacing-lg on each side, in height too. On a narrow screen every size fills the width minus spacing-lg.
showCloseButtonboolean-trueDialogContent: show the corner close button. DialogFooter takes the same prop (default false) to add a secondary Close button. Chỉ trên web.

Slot

TênBắt buộcMô tả
triggerkhôngElement that opens the dialog.
titlecóDialog title (required for a11y).
descriptionkhôngOptional supporting text.
contentkhôngMain body.
footerkhôngActions.

Cấu tạo

PhầnMô tả
rootRoot. Controls open state.
overlayScrim behind the content. color-overlay-scrim.
contentThe floating panel: raised surface, radius-page, shadow-high, border.
headerTop block for title and description.
titleAccessible name of the dialog.
descriptionOptional supporting text.
footerActions row at the bottom.
closeIcon button that dismisses the dialog.
iconTabler XIcon inside the close control, 16px.
hitAreaTransparent ::before on the close control, never smaller than size-target-min.

Khả năng truy cập

Role: dialog

PhímHành động
EscapeCloses the dialog and returns focus to the trigger.
TabCycles focus inside the dialog (focus trap).
  • Traps focus and closes on Escape. Hides the rest of the page from assistive tech (aria-hidden on siblings); it does not set aria-modal.
  • Always provide a DialogTitle (visible or sr-only) so the dialog has an accessible name.
  • The corner close is a DialogClose with an sr-only "Close" label and a Tabler XIcon. If showCloseButton is false on DialogContent, the footer must have a Cancel or Close.
  • Do not nest dialogs.

Cài đặt

npx shadcn add https://werewolf-ui.vercel.app/r/dialog.json

Lệnh này thêm luôn styles/werewolf.css, bộ token mà mọi component dùng, và các component khác mà nó cần. Import file đó một lần trong CSS gốc, ngay sau @import "tailwindcss", với đường dẫn tính từ file CSS đó (từ app/globals.css là @import "../styles/werewolf.css").