Skip to content

Sheet

Displays content that complements the main content of the screen. Use Drawer when the panel needs drag-to-dismiss gestures.

Code
import {
Button,
Input,
Label,
Sheet,
SheetClose,
SheetContent,
SheetDescription,
SheetFooter,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@falcon/ui-kit";
export function Example() {
return (
<Sheet>
<SheetTrigger render={<Button variant="outline" />}>Open</SheetTrigger>
<SheetContent>
<SheetHeader>
<SheetTitle>Edit account</SheetTitle>
<SheetDescription>
Make changes to this account here. Click save when you are done.
</SheetDescription>
</SheetHeader>
<div className="tw:grid tw:flex-1 tw:auto-rows-min tw:gap-6 tw:px-4">
<div className="tw:grid tw:gap-3">
<Label htmlFor="sheet-demo-name">Account name</Label>
<Input id="sheet-demo-name" defaultValue="North Field Farms" />
</div>
<div className="tw:grid tw:gap-3">
<Label htmlFor="sheet-demo-number">Account number</Label>
<Input id="sheet-demo-number" defaultValue="A-1048" />
</div>
</div>
<SheetFooter>
<Button type="submit">Save changes</Button>
<SheetClose render={<Button variant="outline" />}>Close</SheetClose>
</SheetFooter>
</SheetContent>
</Sheet>
);
}

Use the following composition to build a Sheet:

Sheet
├── SheetTrigger
└── SheetContent
├── SheetHeader
│ ├── SheetTitle
│ └── SheetDescription
└── SheetFooter

Use the side prop on SheetContent to set the edge of the screen where the sheet appears. Values are top, right, bottom, or left.

Code
import {
Button,
Sheet,
SheetClose,
SheetContent,
SheetDescription,
SheetFooter,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@falcon/ui-kit";
const SHEET_SIDES = ["top", "right", "bottom", "left"] as const;
export function Example() {
return (
<div className="tw:flex tw:flex-wrap tw:gap-2">
{SHEET_SIDES.map((side) => (
<Sheet key={side}>
<SheetTrigger
render={<Button variant="outline" className="tw:capitalize" />}
>
{side}
</SheetTrigger>
<SheetContent
side={side}
className="tw:data-[side=bottom]:max-h-[50vh] tw:data-[side=top]:max-h-[50vh]"
>
<SheetHeader>
<SheetTitle>Order activity</SheetTitle>
<SheetDescription>
Review the latest updates before saving your changes.
</SheetDescription>
</SheetHeader>
<div className="tw:[scrollbar-width:none] tw:overflow-y-auto tw:px-4 tw:[&::-webkit-scrollbar]:hidden">
{Array.from({ length: 10 }).map((_, index) => (
<p key={index} className="tw:mb-2 tw:leading-relaxed">
Update {index + 1}: The order record includes item quantities,
delivery timing, pricing, and notes for the receiving team.
</p>
))}
</div>
<SheetFooter>
<Button type="submit">Save changes</Button>
<SheetClose render={<Button variant="outline" />}>
Cancel
</SheetClose>
</SheetFooter>
</SheetContent>
</Sheet>
))}
</div>
);
}

Use showCloseButton={false} on SheetContent to hide the close button.

Code
import {
Button,
Sheet,
SheetClose,
SheetContent,
SheetDescription,
SheetFooter,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@falcon/ui-kit";
export function Example() {
return (
<Sheet>
<SheetTrigger render={<Button variant="outline" />}>
Open Sheet
</SheetTrigger>
<SheetContent showCloseButton={false}>
<SheetHeader>
<SheetTitle>No Close Button</SheetTitle>
<SheetDescription>
This sheet does not have a close button in the top-right corner. Use
the action below, click outside, or press Escape to close.
</SheetDescription>
</SheetHeader>
<SheetFooter>
<SheetClose render={<Button variant="outline" />}>Close</SheetClose>
</SheetFooter>
</SheetContent>
</Sheet>
);
}

Groups a sheet’s parts. Open it with a nested SheetTrigger or the open/defaultOpen props; there is no detached-trigger or imperative API.

children?: React.ReactNode

The content of the sheet. Render functions are not supported.

defaultOpen?: boolean

Whether the sheet is initially open. To render a controlled sheet, use open instead. Defaults to false.

defaultTriggerId?: string | null

ID of the trigger associated with an initially open sheet.

disablePointerDismissal?: boolean

Whether to prevent closing on outside presses. Defaults to false.

modal?: boolean | "trap-focus"

Determines whether the sheet is modal while open. true traps focus, locks page scroll, and disables outside pointer interactions. false allows interaction with the rest of the document. 'trap-focus' traps focus without locking scroll or disabling outside pointer interactions. Defaults to true.

onOpenChange?: ((open: boolean, eventDetails: SheetPrimitive.Root.ChangeEventDetails) => void)

Receives the open state and change-event details when the sheet opens or closes.

onOpenChangeComplete?: ((open: boolean) => void)

Receives the open state after opening or closing animations complete.

open?: boolean

Whether the sheet is currently open.

triggerId?: string | null

ID of the trigger associated with a controlled sheet.

Closes the sheet. Renders a <button> element and accepts standard <button> props. Use render to replace the element.

className?: string | ((state: DialogCloseState) => string | undefined)

CSS class applied to the element, or a function that returns a class based on its state.

nativeButton?: boolean

Whether the component renders a native <button> element when replacing it via the render prop. Set to false if the rendered element is not a button. Defaults to true.

render?: React.ReactElement<any, string | React.JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DialogCloseState>

Allows replacing the component’s HTML element with a different tag, or composing it with another component. Accepts a React element or a function that returns the element to render.

style?: React.CSSProperties | ((state: DialogCloseState) => React.CSSProperties | undefined)

Style applied to the element, or a function that returns a style object based on the component’s state.

Includes the portal, backdrop, and default close button. Renders a <div> element and accepts standard <div> props. Use render to replace the element. Use it with SheetTitle and SheetDescription so the sheet has an accessible name and description.

className?: string

CSS class applied to the sheet.

finalFocus?: boolean | React.RefObject<HTMLElement | null> | ((closeType: InteractionType) => boolean | HTMLElement | null | void)

Determines the element to focus when the sheet closes. Pass false to prevent focus movement, true for the default behavior, an element ref, or a function that selects an element from the interaction type.

initialFocus?: boolean | React.RefObject<HTMLElement | null> | ((openType: InteractionType) => boolean | HTMLElement | null | void)

Determines the element to focus when the sheet opens. Pass false to prevent focus movement, true for the default behavior, an element ref, or a function that selects an element from the interaction type.

render?: React.ReactElement<any, string | React.JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DialogPopupState>

Allows replacing the sheet’s HTML element with a different tag, or composing it with another component. Accepts a React element or a function that returns the element to render.

showCloseButton?: boolean = true

Whether to render the built-in close button. Defaults to true.

side?: "bottom" | "left" | "right" | "top" = "right"

Which edge of the viewport the sheet opens from. Defaults to right.

style?: React.CSSProperties | ((state: DialogPopupState) => React.CSSProperties | undefined)

Style applied to the sheet, or a function that returns a style object based on the sheet’s state.

Provides the sheet’s accessible description. Renders a <p> element and accepts standard <p> props. Use render to replace the element.

className?: string

CSS class applied to the element.

render?: React.ReactElement<any, string | React.JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DialogDescriptionState>

Allows replacing the component’s HTML element with a different tag, or composing it with another component. Accepts a React element or a function that returns the element to render.

style?: React.CSSProperties | ((state: DialogDescriptionState) => React.CSSProperties | undefined)

Style applied to the element, or a function that returns a style object based on the component’s state.

Contains sheet actions. Renders a <div> element and accepts standard <div> props.

Groups SheetTitle and SheetDescription. Renders a <div> element and accepts standard <div> props.

Provides the sheet’s accessible name. Renders an <h2> element and accepts standard <h2> props. Use render to replace the element.

className?: string

CSS class applied to the element.

render?: React.ReactElement<any, string | React.JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DialogTitleState>

Allows replacing the component’s HTML element with a different tag, or composing it with another component. Accepts a React element or a function that returns the element to render.

style?: React.CSSProperties | ((state: DialogTitleState) => React.CSSProperties | undefined)

Style applied to the element, or a function that returns a style object based on the component’s state.

Opens the associated sheet. Renders a <button> element and accepts standard <button> props. Use render to replace the element.

className?: string | ((state: DialogTriggerState) => string | undefined)

CSS class applied to the element, or a function that returns a class based on its state.

id?: string

ID of the trigger. In addition to being forwarded to the rendered element, it identifies the active trigger in controlled mode with triggerId.

nativeButton?: boolean

Whether the component renders a native <button> element when replacing it via the render prop. Set to false if the rendered element is not a button. Defaults to true.

render?: React.ReactElement<any, string | React.JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DialogTriggerState>

Allows replacing the component’s HTML element with a different tag, or composing it with another component. Accepts a React element or a function that returns the element to render.

style?: React.CSSProperties | ((state: DialogTriggerState) => React.CSSProperties | undefined)

Style applied to the element, or a function that returns a style object based on the component’s state.