Sheet

Slide-over panel from the edge of the screen. Install Sheet from the VLLNT UI registry with the shadcn CLI.

Report a bug

Slide-over panel from the edge of the screen. Part of the overlay family in VLLNT UI, it ships as a machine-readable registry entry — copy the source directly into your app with the shadcn CLI and own it, no runtime dependency on a component library.

Preview

Switch between light and dark to inspect the embedded Storybook preview.

Installation

Add Sheet to your project with the shadcn CLI. The source lands in your codebase, ready to adapt:

pnpm dlx shadcn@latest add https://ui.vllnt.ai/r/sheet.json

Source

"use client"; import * as SheetPrimitive from "@radix-ui/react-dialog"; import { cva, type VariantProps } from "class-variance-authority"; import { X } from "lucide-react"; import { cn } from "../../lib/utils"; const Sheet = SheetPrimitive.Root; const SheetTrigger = SheetPrimitive.Trigger; const SheetClose = SheetPrimitive.Close; const SheetPortal = SheetPrimitive.Portal; const SheetOverlay = ({ className, ref, ...props }: React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay> & { ref?: React.Ref<React.ComponentRef<typeof SheetPrimitive.Overlay>>; }) => ( <SheetPrimitive.Overlay className={cn( "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", className, )} {...props} ref={ref} /> ); SheetOverlay.displayName = SheetPrimitive.Overlay.displayName; const sheetVariants = cva( "fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=open]:animate-in data-[state=closed]:animate-out", { defaultVariants: { side: "right", }, variants: { side: { bottom: "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom", left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm", right: "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm", top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top", }, }, }, ); type SheetContentProps = {} & React.ComponentPropsWithoutRef< typeof SheetPrimitive.Content > & VariantProps<typeof sheetVariants>; const SheetContent = ({ children, className, ref, side = "right", ...props }: SheetContentProps & { ref?: React.Ref<React.ComponentRef<typeof SheetPrimitive.Content>>; }) => ( <SheetPortal> <SheetOverlay /> <SheetPrimitive.Content className={cn(sheetVariants({ side }), className)} ref={ref} {...props} > <SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary"> <X className="size-4" /> <span className="sr-only">Close</span> </SheetPrimitive.Close> {children} </SheetPrimitive.Content> </SheetPortal> ); SheetContent.displayName = SheetPrimitive.Content.displayName; const SheetHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( <div className={cn( "flex flex-col space-y-2 text-center sm:text-left", className, )} {...props} /> ); SheetHeader.displayName = "SheetHeader"; const SheetFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( <div className={cn( "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className, )} {...props} /> ); SheetFooter.displayName = "SheetFooter"; const SheetTitle = ({ className, ref, ...props }: React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title> & { ref?: React.Ref<React.ComponentRef<typeof SheetPrimitive.Title>>; }) => ( <SheetPrimitive.Title className={cn("text-lg font-semibold text-foreground", className)} ref={ref} {...props} /> ); SheetTitle.displayName = SheetPrimitive.Title.displayName; const SheetDescription = ({ className, ref, ...props }: React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description> & { ref?: React.Ref<React.ComponentRef<typeof SheetPrimitive.Description>>; }) => ( <SheetPrimitive.Description className={cn("text-sm text-muted-foreground", className)} ref={ref} {...props} /> ); SheetDescription.displayName = SheetPrimitive.Description.displayName; export { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, };

Stories

Explore every variant and state in the interactive Storybook:

Preview

Switch between light and dark to inspect the embedded Storybook preview.

Dependencies

  • @vllnt/ui@^0.3.0