UIPackage
Menu

Framework

Change language

Boilerplate repo

Sheet

sheetui

Side-mounted modal that slides in from the top, right, bottom, or left edge. Use for filter panels, edit drawers, and mobile menus.

Also available for Vue ->

When to use which

Decision Guide

Dialogs capture immediate user focus for critical actions. Sheets slide in from screen edges for deep secondary forms, while Popovers provide lightweight contextual cards.

ComponentRole
Dialog

Critical confirmations, destructive warnings, or focused single-purpose tasks requiring user resolution.

Modal Window
Sheetcurrent

Complex edit forms, filter panes, or shopping carts that retain underlying page context.

Off-Canvas Slide-Over
Drawer

Mobile bottom sheets, touch-friendly sliding panels, or secondary inspection trays.

Edge Panel / Bottom Sheet
Popover

Small contextual dropdowns, color pickers, date pickers, or inline configuration flyouts.

Contextual Floating Card
  • Urgent confirmation or focused prompt → Dialog (view)
  • Side panel for deep form editing → Sheet
  • Mobile bottom sheet or gesture tray → Drawer (view)
  • Anchored contextual flyout or controls → Popover (view)

Installation

$npx shadcn@latest add https://uipkge.dev/r/react/sheet.json
Named registry:npx shadcn@latest add @uipkge-react/sheetInstalls to:components/ui/sheet/

Examples

Loading interactive previews…

Props

NameType / ValuesDefaultRequired
side'top' | 'right' | 'bottom' | 'left'optional

Used by

Files installed (2)

  • components/ui/sheet/sheet.tsx5.3 kB
    'use client'
    
    import * as React from 'react'
    import * as DialogPrimitive from '@radix-ui/react-dialog'
    import { X } from 'lucide-react'
    import { cn } from '@/lib/utils'
    
    const Sheet = DialogPrimitive.Root
    
    const SheetTrigger = React.forwardRef<
      React.ElementRef<typeof DialogPrimitive.Trigger>,
      React.ComponentPropsWithoutRef<typeof DialogPrimitive.Trigger>
    >(({ ...props }, ref) => <DialogPrimitive.Trigger ref={ref} data-uipkge="" data-slot="sheet-trigger" {...props} />)
    SheetTrigger.displayName = DialogPrimitive.Trigger.displayName
    
    const SheetClose = React.forwardRef<
      React.ElementRef<typeof DialogPrimitive.Close>,
      React.ComponentPropsWithoutRef<typeof DialogPrimitive.Close>
    >(({ ...props }, ref) => <DialogPrimitive.Close ref={ref} data-uipkge="" data-slot="sheet-close" {...props} />)
    SheetClose.displayName = DialogPrimitive.Close.displayName
    
    const SheetOverlay = React.forwardRef<
      React.ElementRef<typeof DialogPrimitive.Overlay>,
      React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
    >(({ className, ...props }, ref) => (
      <DialogPrimitive.Overlay
        ref={ref}
        data-uipkge=""
        data-slot="sheet-overlay"
        className={cn(
          'motion-safe:data-[state=open]:animate-in motion-safe:data-[state=closed]:animate-out motion-safe:data-[state=open]:ease-emphasized motion-safe:data-[state=open]:blur-in-2 motion-safe:data-[state=closed]:blur-out-2 motion-safe:data-[state=closed]:fade-out-0 motion-safe:data-[state=open]:fade-in-0 bg-foreground/50 fixed inset-0 z-50',
          className,
        )}
        {...props}
      />
    ))
    SheetOverlay.displayName = DialogPrimitive.Overlay.displayName
    
    interface SheetContentProps extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> {
      side?: 'top' | 'right' | 'bottom' | 'left'
    }
    
    const SheetContent = React.forwardRef<React.ElementRef<typeof DialogPrimitive.Content>, SheetContentProps>(
      ({ side = 'right', className, children, ...props }, ref) => (
        <DialogPrimitive.Portal>
          <SheetOverlay />
          <DialogPrimitive.Content
            ref={ref}
            data-uipkge=""
            data-slot="sheet-content"
            className={cn(
              'bg-background motion-safe:data-[state=open]:animate-in motion-safe:data-[state=closed]:animate-out motion-safe:data-[state=open]:ease-emphasized motion-safe:data-[state=open]:blur-in-2 motion-safe:data-[state=closed]:blur-out-2 fixed z-50 flex flex-col gap-4 overflow-hidden shadow-lg transition ease-in-out motion-safe:data-[state=closed]:duration-200 motion-safe:data-[state=open]:duration-300',
              side === 'right' &&
                'motion-safe:data-[state=closed]:slide-out-to-right motion-safe:data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm',
              side === 'left' &&
                'motion-safe:data-[state=closed]:slide-out-to-left motion-safe:data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm',
              side === 'top' &&
                'motion-safe:data-[state=closed]:slide-out-to-top motion-safe:data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b',
              side === 'bottom' &&
                'motion-safe:data-[state=closed]:slide-out-to-bottom motion-safe:data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t',
              className,
            )}
            {...props}
          >
            {children}
    
            <DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none">
              <X className="size-4" aria-hidden="true" />
              <span className="sr-only">Close</span>
            </DialogPrimitive.Close>
          </DialogPrimitive.Content>
        </DialogPrimitive.Portal>
      ),
    )
    SheetContent.displayName = DialogPrimitive.Content.displayName
    
    const SheetHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
      <div data-uipkge="" data-slot="sheet-header" className={cn('flex flex-col gap-1.5 p-4', className)} {...props} />
    )
    SheetHeader.displayName = 'SheetHeader'
    
    const SheetFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
      <div
        data-uipkge=""
        data-slot="sheet-footer"
        className={cn('mt-auto flex flex-col gap-2 p-4', className)}
        {...props}
      />
    )
    SheetFooter.displayName = 'SheetFooter'
    
    const SheetTitle = React.forwardRef<
      React.ElementRef<typeof DialogPrimitive.Title>,
      React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
    >(({ className, ...props }, ref) => (
      <DialogPrimitive.Title
        ref={ref}
        data-uipkge=""
        data-slot="sheet-title"
        className={cn('text-foreground font-semibold', className)}
        {...props}
      />
    ))
    SheetTitle.displayName = DialogPrimitive.Title.displayName
    
    const SheetDescription = React.forwardRef<
      React.ElementRef<typeof DialogPrimitive.Description>,
      React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
    >(({ className, ...props }, ref) => (
      <DialogPrimitive.Description
        ref={ref}
        data-uipkge=""
        data-slot="sheet-description"
        className={cn('text-muted-foreground text-sm', className)}
        {...props}
      />
    ))
    SheetDescription.displayName = DialogPrimitive.Description.displayName
    
    export {
      Sheet,
      SheetTrigger,
      SheetClose,
      SheetOverlay,
      SheetContent,
      SheetHeader,
      SheetFooter,
      SheetTitle,
      SheetDescription,
    }
    
  • components/ui/sheet/index.ts0.2 kB

Raw manifest:https://uipkge.dev/r/react/sheet.json