Sheet

A panel that slides in from an edge of the screen to complement the main content, like a filter drawer or a settings panel. Built on Base UI's dialog primitive.

Last updated August 8, 2026

CreditsModifiedPublished

Copied from shadcn/ui.

  • Adds logical side="start"/"end" values on top of the physical top/right/bottom/left, resolved from the ambient direction measured at the trigger — so a sheet can open from the reading-start edge in both LTR and RTL without branching on direction yourself
  • Close button uses end-3 instead of right-3 so it sits in the correct corner regardless of direction

Overview

import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import {
  Sheet,
  SheetClose,
  SheetContent,
  SheetDescription,
  SheetFooter,
  SheetHeader,
  SheetTitle,
  SheetTrigger,
} from "@/components/ui/sheet"
 
export function SheetDemoExample() {
  return (
    <Sheet>
      <SheetTrigger render={<Button variant="outline">Edit profile</Button>} />
      <SheetContent>
        <SheetHeader>
          <SheetTitle>Edit profile</SheetTitle>
          <SheetDescription>
            Make changes to your profile here. Click save when you&apos;re done.
          </SheetDescription>
        </SheetHeader>
        <div className="flex flex-col gap-4 px-4">
          <div className="flex flex-col gap-2">
            <Label htmlFor="sheet-demo-name">Name</Label>
            <Input id="sheet-demo-name" defaultValue="Sadegh Alavi" />
          </div>
          <div className="flex flex-col gap-2">
            <Label htmlFor="sheet-demo-username">Username</Label>
            <Input id="sheet-demo-username" defaultValue="@sadegh" />
          </div>
        </div>
        <SheetFooter>
          <Button type="submit">Save changes</Button>
          <SheetClose render={<Button variant="outline">Cancel</Button>} />
        </SheetFooter>
      </SheetContent>
    </Sheet>
  )
}

Installation

$ npx shadcn@latest add https://ui.persian-labs.ir/r/sheet.json

Usage

import {
  Sheet,
  SheetClose,
  SheetContent,
  SheetDescription,
  SheetFooter,
  SheetHeader,
  SheetTitle,
  SheetTrigger,
} from "@/components/ui/sheet"
 
export function Example() {
  return (
    <Sheet>
      <SheetTrigger render={<Button variant="outline">Open</Button>} />
      <SheetContent>
        <SheetHeader>
          <SheetTitle>Are you absolutely sure?</SheetTitle>
          <SheetDescription>This action cannot be undone.</SheetDescription>
        </SheetHeader>
      </SheetContent>
    </Sheet>
  )
}

Side

Pass side to control which edge the sheet slides in from.

import { Button } from "@/components/ui/button"
import {
  Sheet,
  SheetClose,
  SheetContent,
  SheetDescription,
  SheetFooter,
  SheetHeader,
  SheetTitle,
  SheetTrigger,
} from "@/components/ui/sheet"
 
const sides = ["top", "right", "bottom", "left"] as const
 
export function SheetSideExample() {
  return (
    <div className="flex flex-wrap gap-2">
      {sides.map((side) => (
        <Sheet key={side}>
          <SheetTrigger
            render={
              <Button variant="outline" className="capitalize">
                {side}
              </Button>
            }
          />
          <SheetContent side={side}>
            <SheetHeader>
              <SheetTitle className="capitalize">{side} sheet</SheetTitle>
              <SheetDescription>
                Slides in from the {side} edge of the screen.
              </SheetDescription>
            </SheetHeader>
            <SheetFooter>
              <SheetClose render={<Button variant="outline">Close</Button>} />
            </SheetFooter>
          </SheetContent>
        </Sheet>
      ))}
    </div>
  )
}

RTL

Use side="start" instead of a hardcoded left/right — it opens from the right in RTL and the left in LTR automatically.

import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import {
  Sheet,
  SheetClose,
  SheetContent,
  SheetDescription,
  SheetFooter,
  SheetHeader,
  SheetTitle,
  SheetTrigger,
} from "@/components/ui/sheet"
 
export function SheetRtlExample() {
  return (
    <Sheet>
      <SheetTrigger
        render={<Button variant="outline">ویرایش پروفایل</Button>}
      />
      <SheetContent side="start">
        <SheetHeader>
          <SheetTitle>ویرایش پروفایل</SheetTitle>
          <SheetDescription>
            تغییرات را اعمال کنید و روی ذخیره کلیک کنید.
          </SheetDescription>
        </SheetHeader>
        <div className="flex flex-col gap-4 px-4">
          <div className="flex flex-col gap-2">
            <Label htmlFor="sheet-rtl-name">نام</Label>
            <Input id="sheet-rtl-name" defaultValue="صادق علوی" />
          </div>
          <div className="flex flex-col gap-2">
            <Label htmlFor="sheet-rtl-username">نام کاربری</Label>
            <Input id="sheet-rtl-username" defaultValue="@sadegh" />
          </div>
        </div>
        <SheetFooter>
          <Button type="submit">ذخیره تغییرات</Button>
          <SheetClose render={<Button variant="outline">انصراف</Button>} />
        </SheetFooter>
      </SheetContent>
    </Sheet>
  )
}

API Reference

Sheet

SheetContent