Chuyển tới nội dung
Component

Sheet

A dialog that slides in from an edge of the screen and runs along it: details of a row, filters, settings, a form next to the page it changes. It shares Dialog's scrim, raised surface and close button; only the side that faces the content has a border and page corners.

Xem trước

Props

  • open
  • defaultOpen
  • side
  • size
  • showCloseButton
  • title
import { Button } from "@/components/ui/button"
import { Field, FieldControl, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"
import { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger } from "@/components/ui/sheet"

<Sheet>
  <SheetTrigger asChild>
    <Button variant="secondary">Edit project</Button>
  </SheetTrigger>
  <SheetContent>
    <SheetHeader>
      <SheetTitle>Edit project</SheetTitle>
      <SheetDescription>Changes are visible to everyone on your team.</SheetDescription>
    </SheetHeader>
    <Field>
      <FieldLabel>Name</FieldLabel>
      <FieldControl>
        <Input defaultValue="Werewolf" />
      </FieldControl>
    </Field>
    <SheetFooter>
      <SheetClose asChild>
        <Button variant="secondary">Cancel</Button>
      </SheetClose>
      <Button>Save</Button>
    </SheetFooter>
  </SheetContent>
</Sheet>

Cách dùng

Khi nào dùng

  • Work next to the page: the details of a row, filters, a short form.
  • Navigation on a narrow screen, from the start edge, or a few choices on a phone, from the bottom.

Khi nào không dùng

  • Confirming an action that destroys data. Use AlertDialog.
  • A focused task that stands on its own, such as renaming a project. Use Dialog.
  • A menu of actions. Use DropdownMenu.

Biến thể

side

Set on SheetContent. The edge it slides in from. right for details and forms next to a list; left for navigation; bottom for short choices on a phone; top rarely.

  • top

  • rightmặc định

  • bottom

  • left

import { Button } from "@/components/ui/button"
import { Field, FieldControl, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"
import { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger } from "@/components/ui/sheet"

<Sheet>
  <SheetTrigger asChild>
    <Button variant="secondary">Edit project</Button>
  </SheetTrigger>
  <SheetContent side="top">
    <SheetHeader>
      <SheetTitle>Edit project</SheetTitle>
      <SheetDescription>Changes are visible to everyone on your team.</SheetDescription>
    </SheetHeader>
    <Field>
      <FieldLabel>Name</FieldLabel>
      <FieldControl>
        <Input defaultValue="Werewolf" />
      </FieldControl>
    </Field>
    <SheetFooter>
      <SheetClose asChild>
        <Button variant="secondary">Cancel</Button>
      </SheetClose>
      <Button>Save</Button>
    </SheetFooter>
  </SheetContent>
</Sheet>
<Sheet>
  <SheetTrigger asChild>
    <Button variant="secondary">Edit project</Button>
  </SheetTrigger>
  <SheetContent>
    <SheetHeader>
      <SheetTitle>Edit project</SheetTitle>
      <SheetDescription>Changes are visible to everyone on your team.</SheetDescription>
    </SheetHeader>
    <Field>
      <FieldLabel>Name</FieldLabel>
      <FieldControl>
        <Input defaultValue="Werewolf" />
      </FieldControl>
    </Field>
    <SheetFooter>
      <SheetClose asChild>
        <Button variant="secondary">Cancel</Button>
      </SheetClose>
      <Button>Save</Button>
    </SheetFooter>
  </SheetContent>
</Sheet>
<Sheet>
  <SheetTrigger asChild>
    <Button variant="secondary">Edit project</Button>
  </SheetTrigger>
  <SheetContent side="bottom">
    <SheetHeader>
      <SheetTitle>Edit project</SheetTitle>
      <SheetDescription>Changes are visible to everyone on your team.</SheetDescription>
    </SheetHeader>
    <Field>
      <FieldLabel>Name</FieldLabel>
      <FieldControl>
        <Input defaultValue="Werewolf" />
      </FieldControl>
    </Field>
    <SheetFooter>
      <SheetClose asChild>
        <Button variant="secondary">Cancel</Button>
      </SheetClose>
      <Button>Save</Button>
    </SheetFooter>
  </SheetContent>
</Sheet>
<Sheet>
  <SheetTrigger asChild>
    <Button variant="secondary">Edit project</Button>
  </SheetTrigger>
  <SheetContent side="left">
    <SheetHeader>
      <SheetTitle>Edit project</SheetTitle>
      <SheetDescription>Changes are visible to everyone on your team.</SheetDescription>
    </SheetHeader>
    <Field>
      <FieldLabel>Name</FieldLabel>
      <FieldControl>
        <Input defaultValue="Werewolf" />
      </FieldControl>
    </Field>
    <SheetFooter>
      <SheetClose asChild>
        <Button variant="secondary">Cancel</Button>
      </SheetClose>
      <Button>Save</Button>
    </SheetFooter>
  </SheetContent>
</Sheet>

size

Set on SheetContent. Widest it gets on the left and right (sm 320px, md 448px, lg 672px), tallest on the top and bottom (a third, half, three quarters of the screen). full covers the screen along that side, with no corners.

  • sm

  • mdmặc định

  • lg

  • full

import { Button } from "@/components/ui/button"
import { Field, FieldControl, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"
import { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger } from "@/components/ui/sheet"

<Sheet>
  <SheetTrigger asChild>
    <Button variant="secondary">Edit project</Button>
  </SheetTrigger>
  <SheetContent size="sm">
    <SheetHeader>
      <SheetTitle>Edit project</SheetTitle>
      <SheetDescription>Changes are visible to everyone on your team.</SheetDescription>
    </SheetHeader>
    <Field>
      <FieldLabel>Name</FieldLabel>
      <FieldControl>
        <Input defaultValue="Werewolf" />
      </FieldControl>
    </Field>
    <SheetFooter>
      <SheetClose asChild>
        <Button variant="secondary">Cancel</Button>
      </SheetClose>
      <Button>Save</Button>
    </SheetFooter>
  </SheetContent>
</Sheet>
<Sheet>
  <SheetTrigger asChild>
    <Button variant="secondary">Edit project</Button>
  </SheetTrigger>
  <SheetContent>
    <SheetHeader>
      <SheetTitle>Edit project</SheetTitle>
      <SheetDescription>Changes are visible to everyone on your team.</SheetDescription>
    </SheetHeader>
    <Field>
      <FieldLabel>Name</FieldLabel>
      <FieldControl>
        <Input defaultValue="Werewolf" />
      </FieldControl>
    </Field>
    <SheetFooter>
      <SheetClose asChild>
        <Button variant="secondary">Cancel</Button>
      </SheetClose>
      <Button>Save</Button>
    </SheetFooter>
  </SheetContent>
</Sheet>
<Sheet>
  <SheetTrigger asChild>
    <Button variant="secondary">Edit project</Button>
  </SheetTrigger>
  <SheetContent size="lg">
    <SheetHeader>
      <SheetTitle>Edit project</SheetTitle>
      <SheetDescription>Changes are visible to everyone on your team.</SheetDescription>
    </SheetHeader>
    <Field>
      <FieldLabel>Name</FieldLabel>
      <FieldControl>
        <Input defaultValue="Werewolf" />
      </FieldControl>
    </Field>
    <SheetFooter>
      <SheetClose asChild>
        <Button variant="secondary">Cancel</Button>
      </SheetClose>
      <Button>Save</Button>
    </SheetFooter>
  </SheetContent>
</Sheet>
<Sheet>
  <SheetTrigger asChild>
    <Button variant="secondary">Edit project</Button>
  </SheetTrigger>
  <SheetContent size="full">
    <SheetHeader>
      <SheetTitle>Edit project</SheetTitle>
      <SheetDescription>Changes are visible to everyone on your team.</SheetDescription>
    </SheetHeader>
    <Field>
      <FieldLabel>Name</FieldLabel>
      <FieldControl>
        <Input defaultValue="Werewolf" />
      </FieldControl>
    </Field>
    <SheetFooter>
      <SheetClose asChild>
        <Button variant="secondary">Cancel</Button>
      </SheetClose>
      <Button>Save</Button>
    </SheetFooter>
  </SheetContent>
</Sheet>

Ví dụ

Edit details

import { Button } from "@/components/ui/button"
import { Field, FieldControl, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"
import { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger } from "@/components/ui/sheet"

<Sheet>
  <SheetTrigger asChild>
    <Button variant="secondary">Edit project</Button>
  </SheetTrigger>
  <SheetContent>
    <SheetHeader>
      <SheetTitle>Edit project</SheetTitle>
      <SheetDescription>Changes are visible to everyone on your team.</SheetDescription>
    </SheetHeader>
    <Field>
      <FieldLabel>Name</FieldLabel>
      <FieldControl>
        <Input defaultValue="Werewolf" />
      </FieldControl>
    </Field>
    <SheetFooter>
      <SheetClose asChild>
        <Button variant="secondary">Cancel</Button>
      </SheetClose>
      <Button>Save</Button>
    </SheetFooter>
  </SheetContent>
</Sheet>

From the bottom

Short choices on a phone, with the main action one tap away.

import { Button } from "@/components/ui/button"
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from "@/components/ui/sheet"

<Sheet>
  <SheetTrigger asChild>
    <Button variant="secondary">Sort</Button>
  </SheetTrigger>
  <SheetContent side="bottom" size="sm">
    <SheetHeader>
      <SheetTitle>Sort projects</SheetTitle>
    </SheetHeader>
    <RadioGroup aria-label="Sort projects" defaultValue="recent">
      <RadioGroupItem value="recent" label="Recently edited" />
      <RadioGroupItem value="name" label="Name" />
    </RadioGroup>
  </SheetContent>
</Sheet>

Nên và không nên

Nên

  • Use it for work next to the page: the details of a row, filters, a short form.
  • Give it a title, and put the main action in the footer.
  • Keep it open while the user works in it; close it when the action is done.

Không nên

  • Don't use it for a short confirmation; use AlertDialog or Dialog.
  • Don't open a sheet from a sheet.
  • Don't use it for a menu of actions; use DropdownMenu.

Props

TênKiểuGiá trịMặc địnhMô tả
openboolean--Set on Sheet. Whether it is open, when you control it. Pair it with onOpenChange. Chỉ trên web.
defaultOpenboolean-falseSet on Sheet. Opens it on first render, when you don't control it. Chỉ trên web.
onOpenChangefunction--Set on Sheet. Called with true or false when it opens or closes (trigger, close button, Escape, scrim). Chỉ trên web.
sideenumtop | right | bottom | leftrightSet on SheetContent. The edge it slides in from. right for details and forms next to a list; left for navigation; bottom for short choices on a phone; top rarely.
sizeenumsm | md | lg | fullmdSet on SheetContent. Widest it gets on the left and right (sm 320px, md 448px, lg 672px), tallest on the top and bottom (a third, half, three quarters of the screen). full covers the screen along that side, with no corners.
showCloseButtonboolean-trueSet on SheetContent. The corner close button. Hide it only when the footer has a Cancel or Close. Chỉ trên web.

Slot

TênBắt buộcMô tả
triggerkhôngSheetTrigger with asChild around a Button.
titlecóSheetTitle, required for a11y.
descriptionkhôngOptional SheetDescription.
contentkhôngThe body: fields, details, a list. It scrolls with the panel.
footerkhôngSheetFooter with the actions.

Cấu tạo

PhầnMô tả
rootSheet. Holds the open state.
overlayThe scrim behind the sheet, the same as Dialog's.
contentThe panel: raised fill, shadow-high, p-xl, gap-lg. It covers the full length of its side; the border and the page corners are only on the side that faces the content.
headerTop block for the title and description, gap-sm.
titleThe name of the sheet: 16px medium.
descriptionOptional supporting text: 13px secondary.
footerActions at the end of the panel, however short the content is.
closeIcon button in the corner that closes the sheet, the same as Dialog's.
iconTabler X in the close button, 16px.
hitAreaTransparent ::before on the close button, never smaller than size-target-min.

Khả năng truy cập

Role: dialog

PhímHành động
EscapeCloses the sheet and returns focus to the trigger.
TabCycles focus inside the sheet (focus trap).
  • A modal dialog: it traps focus, hides the rest of the page from assistive tech and closes on Escape or a scrim press.
  • Always provide a SheetTitle (visible or sr-only), so the sheet has a name.
  • The corner close is a button with a visually hidden Close label and a Tabler X. With showCloseButton={false}, the footer must have a Cancel or Close.
  • It slides in only when the user allows motion; under prefers-reduced-motion it fades in. It closes at once.
  • Do not open a sheet from a sheet.

Cài đặt

npx shadcn add https://werewolf-ui.vercel.app/r/sheet.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").