Sheet

Extends the Dialog component to display content that complements the main content of the screen.

Installation

Install the following dependencies:

npm install @radix-ui/react-dialog class-variance-authority

Copy and paste the following code into your project.

'use client';
 
import * as SheetPrimitive from '@radix-ui/react-dialog';
import { cva, type VariantProps } from 'class-variance-authority';
import clsx from 'clsx';
import { X } from 'lucide-react';
import { ComponentPropsWithoutRef, ElementRef, forwardRef, HTMLAttributes } from 'react';
import styles from './styles.module.scss';
 
const Sheet = SheetPrimitive.Root;
 
const SheetTrigger = SheetPrimitive.Trigger;
 
const SheetClose = SheetPrimitive.Close;
 
const SheetPortal = SheetPrimitive.Portal;
 
const SheetOverlay = forwardRef<
    ElementRef<typeof SheetPrimitive.Overlay>,
    ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
>(({ className, ...props }, ref) => (
    <SheetPrimitive.Overlay className={clsx(styles.sheet__overlay, className)} {...props} ref={ref} />
));
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
 
const sheetVariants = cva(styles.base, {
    variants: {
        side: {
            top: styles.variant__top,
            bottom: styles.variant__bottom,
            left: styles.variant__left,
            right: styles.variant__right,
        },
    },
    defaultVariants: {
        side: 'right',
    },
});
 
interface SheetContentProps
    extends ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
        VariantProps<typeof sheetVariants> {}
 
const SheetContent = forwardRef<ElementRef<typeof SheetPrimitive.Content>, SheetContentProps>(
    ({ side = 'right', className, children, ...props }, ref) => (
        <SheetPortal>
            <SheetOverlay />
            <SheetPrimitive.Content ref={ref} className={clsx(sheetVariants({ side }), className)} {...props}>
                {children}
                <SheetPrimitive.Close className={styles.sheet__content__close}>
                    <X className={styles.sheet__content__close__icon} />
                    <span className={styles.sr_only}>Close</span>
                </SheetPrimitive.Close>
            </SheetPrimitive.Content>
        </SheetPortal>
    )
);
SheetContent.displayName = SheetPrimitive.Content.displayName;
 
const SheetHeader = ({ className, ...props }: HTMLAttributes<HTMLDivElement>) => (
    <div className={clsx(styles.sheet__header, className)} {...props} />
);
SheetHeader.displayName = 'SheetHeader';
 
const SheetFooter = ({ className, ...props }: HTMLAttributes<HTMLDivElement>) => (
    <div className={clsx(styles.sheet__footer, className)} {...props} />
);
SheetFooter.displayName = 'SheetFooter';
 
const SheetTitle = forwardRef<
    ElementRef<typeof SheetPrimitive.Title>,
    ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
>(({ className, ...props }, ref) => (
    <SheetPrimitive.Title ref={ref} className={clsx(styles.sheet__title, className)} {...props} />
));
SheetTitle.displayName = SheetPrimitive.Title.displayName;
 
const SheetDescription = forwardRef<
    ElementRef<typeof SheetPrimitive.Description>,
    ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
>(({ className, ...props }, ref) => (
    <SheetPrimitive.Description ref={ref} className={clsx(styles.sheet__description, className)} {...props} />
));
SheetDescription.displayName = SheetPrimitive.Description.displayName;
 
export {
    Sheet,
    SheetClose,
    SheetContent,
    SheetDescription,
    SheetFooter,
    SheetHeader,
    SheetOverlay,
    SheetPortal,
    SheetTitle,
    SheetTrigger,
};

Update the import paths to match your project setup.

Usage

import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger } from '@/components/ui/sheet';
<Sheet>
    <SheetTrigger>Open</SheetTrigger>
    <SheetContent>
        <SheetHeader>
            <SheetTitle>Are you absolutely sure?</SheetTitle>
            <SheetDescription>
                This action cannot be undone. This will permanently delete your account and remove your data from our
                servers.
            </SheetDescription>
        </SheetHeader>
    </SheetContent>
</Sheet>

Examples

Side

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.

Size

You can adjust the size of the sheet using CSS classes:

<Sheet>
    <SheetTrigger>Open</SheetTrigger>
    <SheetContent>
        <SheetHeader>
            <SheetTitle>Are you absolutely sure?</SheetTitle>
            <SheetDescription>
                This action cannot be undone. This will permanently delete your account and remove your data from our
                servers.
            </SheetDescription>
        </SheetHeader>
    </SheetContent>
</Sheet>