Docs
Sheet
Sheet
Extends the Dialog component to display content that complements the main content of the screen.
Loading...
Installation
Add the following components:
Copy and paste the following code into your project.
"use client";
import type { VariantProps } from "cva";
import { cva } from "cva";
import type { ModalRenderProps } from "react-aria-components";
import {
Dialog,
DialogTrigger,
Heading,
Modal,
ModalOverlay,
} from "react-aria-components";
import { dialogVariants } from "@/components/ui/dialog";
import { autoRef, cn, withRenderProps } from "@/lib/utils";
/* -------------------------------------------------------------------------- */
/* Variants */
/* -------------------------------------------------------------------------- */
export const sheetVariants = {
root: cva({
base: cn(
"tp-sheet-base",
"fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out",
"s-entering:animate-in s-exiting:animate-out s-entering:duration-300 s-exiting:duration-500",
),
variants: {
side: {
top: "inset-x-0 top-0 border-b s-exiting:slide-out-to-top s-entering:slide-in-from-top",
bottom:
"inset-x-0 bottom-0 border-t s-exiting:slide-out-to-bottom s-entering:slide-in-from-bottom",
left: "inset-y-0 left-0 h-full w-3/4 border-r s-exiting:slide-out-to-left s-entering:slide-in-from-left sm:max-w-sm",
right:
"inset-y-0 right-0 h-full w-3/4 border-l s-exiting:slide-out-to-right s-entering:slide-in-from-right sm:max-w-sm",
},
},
defaultVariants: {
side: "right",
},
}),
overlay: cva({
base: dialogVariants.overlay(),
}),
};
/* -------------------------------------------------------------------------- */
/* Components */
/* -------------------------------------------------------------------------- */
/* --------------------------------- Trigger -------------------------------- */
export const SheetTrigger = DialogTrigger;
/* ---------------------------------- Root ---------------------------------- */
export interface SheetProps
extends Omit<React.ComponentPropsWithRef<typeof Modal>, "children">,
VariantProps<typeof sheetVariants.root> {
children?:
| React.ReactNode
| ((values: ModalRenderProps & { close: () => void }) => React.ReactNode);
blurBackground?: boolean;
}
export const Sheet = autoRef(
({
className,
children,
isDismissable = true,
side,
...props
}: SheetProps) => {
return (
<>
<ModalOverlay className={sheetVariants.overlay()} />
<Modal
isDismissable={isDismissable}
className={cn(sheetVariants.root({ side }), className)}
{...props}
>
{(modalValues) => (
<Dialog className="relative outline-none">
{({ close }) => (
<>{withRenderProps(children)({ ...modalValues, close })}</>
)}
</Dialog>
)}
</Modal>
</>
);
},
);
/* --------------------------------- Header --------------------------------- */
export type SheetHeaderProps = React.ComponentPropsWithRef<"div">;
export const SheetHeader = autoRef(
({ className, ...props }: SheetHeaderProps) => (
<div
className={cn(
"flex flex-col space-y-2 text-center sm:text-left",
className,
)}
{...props}
/>
),
);
/* --------------------------------- Footer --------------------------------- */
export type SheetFooterProps = React.ComponentPropsWithRef<"div">;
export const SheetFooter = autoRef(
({ className, ...props }: SheetFooterProps) => (
<div
className={cn(
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
className,
)}
{...props}
/>
),
);
/* ---------------------------------- Title --------------------------------- */
export type SheetTitleProps = React.ComponentPropsWithRef<typeof Heading>;
export const SheetTitle = autoRef(
({ className, ...props }: SheetTitleProps) => (
<Heading
slot="title"
className={cn("text-lg font-semibold text-foreground", className)}
{...props}
/>
),
);
/* ------------------------------- Description ------------------------------- */
export type SheetDescriptionProps = React.ComponentPropsWithRef<"p">;
export const SheetDescription = autoRef(
({ className, ...props }: SheetDescriptionProps) => (
<p
slot="description"
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
),
);