Sheet
A full-screen surface inset from every edge, with the page blurred behind it.
Installation
$
Usage
import { Sheet, SheetTrigger, SheetContent, SheetHeader, SheetFooter, SheetTitle, SheetDescription } from "@/components/ui/sheet"Examples
Default
With Sections
SheetHeader and SheetFooter frame the body; showCancelButton adds a ghost Cancel beside the primary action.
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
| showCloseButtonSheetContent | boolean | true | Shows the X close button in the top-right corner. |
| showCancelButtonSheetFooter | boolean | false | Renders a ghost Cancel button that closes the sheet. |
| openSheet | boolean | - | Controlled open state. Pair with onOpenChange. |
| onOpenChangeSheet | (open: boolean) => void | - | Called when the open state changes. |
| defaultOpenSheet | boolean | false | Uncontrolled initial open state. |
| modalSheet | boolean | true | When true, blocks interaction with the page behind the sheet. |
| renderSheetTrigger, SheetClose | React.ReactElement | - | Replaces the default trigger or close button with your own element, e.g. render={<Button>Open</Button>}. Base UI merges props onto it. |
"use client"
import * as React from "react"
import { Dialog as SheetPrimitive } from "@base-ui/react/dialog"
import { XIcon } from "lucide-react"
import { cn } from "@/registry/lib/utils"
import { Button } from "@/registry/ui/button"
import { blurredOverlayClass } from "@/registry/lib/tokens"
function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
return <SheetPrimitive.Root data-slot="sheet" {...props} />
}
function SheetTrigger({
...props
}: React.ComponentProps<typeof SheetPrimitive.Trigger>) {
return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />
}
function SheetClose({
...props
}: React.ComponentProps<typeof SheetPrimitive.Close>) {
return <SheetPrimitive.Close data-slot="sheet-close" {...props} />
}
function SheetPortal({
...props
}: React.ComponentProps<typeof SheetPrimitive.Portal>) {
return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />
}
function SheetOverlay({
className,
...props
}: React.ComponentProps<typeof SheetPrimitive.Backdrop>) {
return (
<SheetPrimitive.Backdrop
data-slot="sheet-overlay"
className={cn(
blurredOverlayClass,
className
)}
{...props}
/>
)
}
function SheetContent({
className,
children,
showCloseButton = true,
...props
}: React.ComponentProps<typeof SheetPrimitive.Popup> & {
showCloseButton?: boolean
}) {
return (
<SheetPortal>
<SheetOverlay />
<SheetPrimitive.Popup
data-slot="sheet-content"
className={cn(
"bg-background transition-[opacity,scale] motion-reduce:transition-[opacity] ease-out duration-200 data-[ending-style]:duration-150 data-[starting-style]:opacity-0 data-[ending-style]:opacity-0 data-[starting-style]:scale-95 data-[ending-style]:scale-95 fixed inset-4 z-50 flex flex-col gap-4 rounded-xl p-6 shadow-ring-md outline-none sm:inset-6 md:inset-10 lg:inset-16",
className
)}
{...props}
>
{children}
{showCloseButton && (
<SheetPrimitive.Close
data-slot="sheet-close"
className="tap-target ring-offset-background focus-visible:ring-ring-focus absolute top-4 right-4 rounded-xs opacity-70 transition-opacity ease-out hover:opacity-100 focus-visible:ring-[3px] focus-visible:ring-offset-2 outline-none disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
>
<XIcon />
<span className="sr-only">Close</span>
</SheetPrimitive.Close>
)}
</SheetPrimitive.Popup>
</SheetPortal>
)
}
function SheetHeader({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="sheet-header"
className={cn("flex flex-col gap-2 pr-8", className)}
{...props}
/>
)
}
function SheetFooter({
className,
showCancelButton = false,
children,
...props
}: React.ComponentProps<"div"> & {
showCancelButton?: boolean
}) {
return (
<div
data-slot="sheet-footer"
className={cn(
"mt-auto flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
className
)}
{...props}
>
{showCancelButton && (
<SheetPrimitive.Close render={<Button variant="ghost">Cancel</Button>} />
)}
{children}
</div>
)
}
function SheetTitle({
className,
...props
}: React.ComponentProps<typeof SheetPrimitive.Title>) {
return (
<SheetPrimitive.Title
data-slot="sheet-title"
className={cn("text-lg leading-none font-semibold", className)}
{...props}
/>
)
}
function SheetDescription({
className,
...props
}: React.ComponentProps<typeof SheetPrimitive.Description>) {
return (
<SheetPrimitive.Description
data-slot="sheet-description"
className={cn("text-muted-foreground text-sm", className)}
{...props}
/>
)
}
export {
Sheet,
SheetTrigger,
SheetClose,
SheetContent,
SheetHeader,
SheetFooter,
SheetTitle,
SheetDescription,
}