Sheet
Extends the Dialog component to display content that complements the main content of the screen.
import * as stylex from '@stylexjs/stylex';
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';
import { space } from '@/lib/constants.stylex';
export default function SheetDemo() {
return (
<Sheet>
<SheetTrigger render={<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 {...stylex.props(styles.fields)}>
<Label>
Name <Input defaultValue="Pedro Duarte" />
</Label>
<Label>
Username <Input defaultValue="@peduarte" />
</Label>
</div>
<SheetFooter>
<SheetClose render={<Button />}>Save changes</SheetClose>
<SheetClose render={<Button variant="outline" />}>Close</SheetClose>
</SheetFooter>
</SheetContent>
</Sheet>
);
}
const styles = stylex.create({
fields: {
display: 'flex',
flexDirection: 'column',
gap: space.s4,
paddingInline: space.s4,
},
});
Install
npx shadcn@latest add @madeui/sheet
Usage
import {
Sheet,
SheetClose,
SheetContent,
SheetDescription,
SheetFooter,
SheetHeader,
SheetTitle,
SheetTrigger,
} from '@/components/ui/sheet';
Composition
<Sheet>
<SheetTrigger />
<SheetContent>
<SheetHeader>
<SheetTitle />
<SheetDescription />
</SheetHeader>
<SheetFooter>
<SheetClose />
</SheetFooter>
</SheetContent>
</Sheet>
Sides
import * as stylex from '@stylexjs/stylex';
import { Button } from '@/components/ui/button';
import {
Sheet,
SheetContent,
SheetDescription,
SheetHeader,
SheetTitle,
SheetTrigger,
type SheetSide,
} from '@/components/ui/sheet';
import { space } from '@/lib/constants.stylex';
const sides: SheetSide[] = ['top', 'right', 'bottom', 'left'];
export default function SheetSides() {
return (
<div {...stylex.props(styles.row)}>
{sides.map((side) => (
<Sheet key={side}>
<SheetTrigger render={<Button variant="outline" />}>
{side}
</SheetTrigger>
<SheetContent side={side}>
<SheetHeader>
<SheetTitle>Sheet from {side}</SheetTitle>
<SheetDescription>
Slides in from the {side} edge of the screen.
</SheetDescription>
</SheetHeader>
</SheetContent>
</Sheet>
))}
</div>
);
}
const styles = stylex.create({
row: {
display: 'flex',
flexWrap: 'wrap',
gap: space.s2,
},
});
No close button
Set showCloseButton={false} and close the sheet through your own footer
buttons instead.
import { Button } from '@/components/ui/button';
import {
Sheet,
SheetClose,
SheetContent,
SheetDescription,
SheetFooter,
SheetHeader,
SheetTitle,
SheetTrigger,
} from '@/components/ui/sheet';
export default function SheetNoCloseButton() {
return (
<Sheet>
<SheetTrigger render={<Button variant="outline" />}>
Open
</SheetTrigger>
<SheetContent showCloseButton={false}>
<SheetHeader>
<SheetTitle>Publish changes</SheetTitle>
<SheetDescription>
Review your changes, then publish or discard them below.
</SheetDescription>
</SheetHeader>
<SheetFooter>
<SheetClose render={<Button />}>Publish</SheetClose>
<SheetClose render={<Button variant="outline" />}>Discard</SheetClose>
</SheetFooter>
</SheetContent>
</Sheet>
);
}
API reference
Built on Base UI Dialog (same primitive as Dialog). The table below covers the props this library adds or changes — every other prop is forwarded; see the Base UI Dialog API reference.
SheetContent
| Prop | Type | Default | Description |
|---|---|---|---|
side |
'top' | 'right' | 'bottom' | 'left' |
'right' |
Edge of the screen the sheet slides in from. |
showCloseButton |
boolean |
true |
Renders an X close button in the top-right corner. |
style |
StyleXStyles |
— | StyleX styles merged last — always win over the component’s own styles. |