Search for a command to run...
Extends the Dialog component to display content that complements the main content of the screen.
npx shadcn@latest add @zaidan/sheetpnpx shadcn add @zaidan/sheetyarn dlx shadcn@latest add @zaidan/sheetbunx shadcn@latest add @zaidan/sheetInstall the following dependencies:
npm i @kobalte/corepnpm add @kobalte/coreyarn add @kobalte/corebun add @kobalte/coreCopy and paste the following code into your project.
1import * as SheetPrimitive from "@kobalte/core/dialog";2import type { PolymorphicProps } from "@kobalte/core/polymorphic";3import { X } from "lucide-solid";4import type { Component, ComponentProps, ValidComponent } from "solid-js";5import { mergeProps, Show, splitProps } from "solid-js";6import { cn } from "~/lib/utils";7import { Button } from "./button";8
9const Sheet: Component<SheetPrimitive.DialogRootProps> = (props) => {10 return <SheetPrimitive.Root data-slot="sheet" {...props} />;11};12
13type SheetTriggerProps<T extends ValidComponent = "button"> = PolymorphicProps<14 T,15 SheetPrimitive.DialogTriggerProps<T>16>;17
18const SheetTrigger = <T extends ValidComponent = "button">(props: SheetTriggerProps<T>) => {19 return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />;20};21
22type SheetCloseProps<T extends ValidComponent = "button"> = PolymorphicProps<23 T,24 SheetPrimitive.DialogCloseButtonProps<T>25>;26
27const SheetClose = <T extends ValidComponent = "button">(props: SheetCloseProps<T>) => {28 return <SheetPrimitive.CloseButton data-slot="sheet-close" {...props} />;29};30
31const SheetPortal = (props: SheetPrimitive.DialogPortalProps) => {32 return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />;33};34
35type SheetOverlayProps<T extends ValidComponent = "div"> = PolymorphicProps<36 T,37 SheetPrimitive.DialogOverlayProps<T>38> &39 Pick<ComponentProps<T>, "class">;40
41const SheetOverlay = <T extends ValidComponent = "div">(props: SheetOverlayProps<T>) => {42 const [local, others] = splitProps(props as SheetOverlayProps, ["class"]);43 return (44 <SheetPrimitive.Overlay45 data-slot="sheet-overlay"46 class={cn("fixed inset-0 z-50 z-sheet-overlay", local.class)}47 {...others}48 />49 );50};51
52type SheetContentProps<T extends ValidComponent = "div"> = PolymorphicProps<53 T,54 SheetPrimitive.DialogContentProps<T>55> &56 Pick<ComponentProps<T>, "class" | "children"> & {57 side?: "top" | "right" | "bottom" | "left";58 showCloseButton?: boolean;59 };60
61const SheetContent = <T extends ValidComponent = "div">(props: SheetContentProps<T>) => {62 const mergedProps = mergeProps(63 { side: "right", showCloseButton: true } as SheetContentProps,64 props,65 );66 const [local, others] = splitProps(mergedProps, ["class", "children", "side", "showCloseButton"]);67 return (68 <SheetPortal>69 <SheetOverlay />70 <SheetPrimitive.Content71 data-slot="sheet-content"72 data-side={local.side}73 class={cn("z-sheet-content", local.class)}74 {...others}75 >76 {local.children}77 <Show when={local.showCloseButton}>78 <SheetPrimitive.CloseButton79 as={Button}80 variant="ghost"81 size="icon-sm"82 data-slot="sheet-close"83 class="z-sheet-close"84 >85 <X />86 <span class="sr-only">Close</span>87 </SheetPrimitive.CloseButton>88 </Show>89 </SheetPrimitive.Content>90 </SheetPortal>91 );92};93
94type SheetHeaderProps = ComponentProps<"div">;95
96const SheetHeader = (props: SheetHeaderProps) => {97 const [local, others] = splitProps(props, ["class"]);98 return (99 <div100 data-slot="sheet-header"101 class={cn("z-sheet-header flex flex-col", local.class)}102 {...others}103 />104 );105};106
107type SheetFooterProps = ComponentProps<"div">;108
109const SheetFooter = (props: SheetFooterProps) => {110 const [local, others] = splitProps(props, ["class"]);111 return (112 <div113 data-slot="sheet-footer"114 class={cn("z-sheet-footer mt-auto flex flex-col", local.class)}115 {...others}116 />117 );118};119
120type SheetTitleProps<T extends ValidComponent = "h2"> = PolymorphicProps<121 T,122 SheetPrimitive.DialogTitleProps<T>123> &124 Pick<ComponentProps<T>, "class">;125
126const SheetTitle = <T extends ValidComponent = "h2">(props: SheetTitleProps<T>) => {127 const [local, others] = splitProps(props as SheetTitleProps, ["class"]);128 return (129 <SheetPrimitive.Title130 data-slot="sheet-title"131 class={cn("z-sheet-title", local.class)}132 {...others}133 />134 );135};136
137type SheetDescriptionProps<T extends ValidComponent = "p"> = PolymorphicProps<138 T,139 SheetPrimitive.DialogDescriptionProps<T>140> &141 Pick<ComponentProps<T>, "class">;142
143const SheetDescription = <T extends ValidComponent = "p">(props: SheetDescriptionProps<T>) => {144 const [local, others] = splitProps(props as SheetDescriptionProps, ["class"]);145 return (146 <SheetPrimitive.Description147 data-slot="sheet-description"148 class={cn("z-sheet-description", local.class)}149 {...others}150 />151 );152};153
154export {155 Sheet,156 SheetTrigger,157 SheetClose,158 SheetContent,159 SheetHeader,160 SheetFooter,161 SheetTitle,162 SheetDescription,163};Here are the source code of all the examples from the preview page:
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";function SheetWithForm() { return ( <Example title="With Form"> <Sheet> <SheetTrigger as={Button} variant="outline"> Open </SheetTrigger> <SheetContent> <SheetHeader> <SheetTitle>Edit profile</SheetTitle> <SheetDescription> Make changes to your profile here. Click save when you're done. </SheetDescription> </SheetHeader> <div class="px-4"> <div class="flex flex-col gap-4"> <div class="flex flex-col gap-2"> <Label for="sheet-demo-name">Name</Label> <Input id="sheet-demo-name" value="Pedro Duarte" /> </div> <div class="flex flex-col gap-2"> <Label for="sheet-demo-username">Username</Label> <Input id="sheet-demo-username" value="@peduarte" /> </div> </div> </div> <SheetFooter> <Button type="submit">Save changes</Button> <SheetClose as={Button} variant="outline"> Close </SheetClose> </SheetFooter> </SheetContent> </Sheet> </Example> );}import { Button } from "~/components/ui/button";import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger,} from "~/components/ui/sheet";function SheetNoCloseButton() { return ( <Example title="No Close Button"> <Sheet> <SheetTrigger as={Button} variant="outline"> No Close Button </SheetTrigger> <SheetContent showCloseButton={false}> <SheetHeader> <SheetTitle>No Close Button</SheetTitle> <SheetDescription> This sheet doesn't have a close button in the top-right corner. You can only close it using the button below. </SheetDescription> </SheetHeader> </SheetContent> </Sheet> </Example> );}Use the side property to <SheetContent /> to indicate the edge of the screen where the component will appear. The values can be top, right, bottom or left.
import { For, Index } from "solid-js";import { Button } from "~/components/ui/button";import { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger,} from "~/components/ui/sheet";const SHEET_SIDES = ["top", "right", "bottom", "left"] as const;
function SheetWithSides() { return ( <Example title="Sides"> <div class="flex flex-wrap gap-2"> <For each={SHEET_SIDES}> {(side) => ( <Sheet> <SheetTrigger as={Button} variant="outline" class="capitalize"> {side} </SheetTrigger> <SheetContent side={side} class="data-[side=bottom]:max-h-[50vh] data-[side=top]:max-h-[50vh]" > <SheetHeader> <SheetTitle>Edit profile</SheetTitle> <SheetDescription> Make changes to your profile here. Click save when you're done. </SheetDescription> </SheetHeader> <div class="no-scrollbar overflow-y-auto px-4"> <Index each={Array.from({ length: 10 })}> {() => ( <p class="mb-4 style-lyra:mb-2 leading-normal style-lyra:leading-relaxed"> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </p> )} </Index> </div> <SheetFooter> <Button type="submit">Save changes</Button> <SheetClose as={Button} variant="outline"> Cancel </SheetClose> </SheetFooter> </SheetContent> </Sheet> )} </For> </div> </Example> );}You can adjust the size of the sheet using CSS classes:
1<Sheet>2 <SheetTrigger>Open</SheetTrigger>3 <SheetContent class="w-[400px] sm:w-[540px]">4 <SheetHeader>5 <SheetTitle>Are you absolutely sure?</SheetTitle>6 <SheetDescription>7 This action cannot be undone. This will permanently delete your account8 and remove your data from our servers.9 </SheetDescription>10 </SheetHeader>11 </SheetContent>12</Sheet>