Slideout Menu
Flexible slideout menu components for creating side panels, navigation drawers, and modal-like experiences that slide in from the edge of the screen.
1. Basic Slideout
The simplest slideout menu with title, description, and content.
<>
<Button onClick={() => setIsOpen1(true)}>Open Slideout</Button>
<Slideout
open={isOpen1}
onOpenChange={setIsOpen1}
title="Slideout Title"
description="This is a basic slideout menu with a title and description."
content={
<div className="space-y-4 flex-1">
<p className="text-primary">
This is the main content area of the slideout. You can put any
content here.
</p>
<p className="text-primary">
The slideout slides in from the right side of the screen and
includes a backdrop overlay.
</p>
</div>
}
footer={
<div className="flex gap-3 justify-end">
<Button onClick={() => setIsOpen1(false)} variant={"secondary"}>
Cancel
</Button>
<Button>Save Changes</Button>
</div>
}
/>
</>2. Navigation Menu
Use slideout for mobile navigation with icons and structured menu items.
<>
<Button onClick={() => setIsOpen2(true)} leftIcon={Menu}>
Open Menu
</Button>
<Slideout
open={isOpen2}
onOpenChange={setIsOpen2}
title="Navigation"
description="Browse through our menu"
content={
<nav className="space-y-1">
{[
{ icon: User, label: "Profile", badge: null },
{ icon: Settings, label: "Settings", badge: null },
{ icon: Bell, label: "Notifications", badge: "3" },
{ icon: ShoppingCart, label: "Cart", badge: "12" },
].map(item => (
<button
key={item.label}
className="w-full flex items-center justify-between px-4 py-3 rounded-lg hover:bg-gray-100 transition-colors"
>
<div className="flex items-center gap-3">
<item.icon size={20} className="text-gray-600" />
<span className="font-medium text-gray-900">
{item.label}
</span>
</div>
{item.badge && (
<span className="px-2 py-1 text-xs font-semibold bg-utility-blue-100 text-utility-blue-700 rounded-full">
{item.badge}
</span>
)}
</button>
))}
</nav>
}
footer={
<Button onClick={() => setIsOpen2(false)} className="w-full">
Close Menu
</Button>
}
/>
</>3. Settings Panel
Create a settings panel with form controls and toggles.
<>
<Button onClick={() => setIsOpen3(true)} leftIcon={Settings}>
Open Settings
</Button>
<Slideout
open={isOpen3}
onOpenChange={setIsOpen3}
title="Settings"
description="Manage your account preferences"
content={
<div className="space-y-6">
<Input
type="text"
placeholder="Enter your name"
leftIcon={User01}
/>
<Input
type="email"
placeholder="Enter your email"
leftIcon={Mail01}
/>
</div>
}
footer={
<div className="flex items-center justify-between">
<div>
<p className="font-medium text-gray-900">Marketing Emails</p>
<p className="text-sm text-quaternary">
Receive promotional content
</p>
</div>
<Switch />
</div>
}
/>
</>
4. Shopping Cart
E-commerce cart slideout with product list and checkout.
<>
<Button onClick={() => setIsOpen4(true)} leftIcon={ShoppingCart}>
View Cart (3)
</Button>
<Slideout
open={isOpen4}
onOpenChange={setIsOpen4}
title="Shopping Cart"
description="3 items in your cart"
content={
<div className="space-y-4">
{[
{ name: "Wireless Headphones", price: 99.99, qty: 1 },
{ name: "Smart Watch", price: 249.99, qty: 1 },
{ name: "Phone Case", price: 19.99, qty: 1 },
].map((item, i) => (
<div
key={i}
className="flex gap-4 p-4 border border-gray-200 rounded-lg"
>
<div className="w-20 h-20 bg-gray-100 rounded-lg flex items-center justify-center text-gray-400">
IMG
</div>
<div className="flex-1">
<h4 className="font-medium text-gray-900">
{item.name}
</h4>
<p className="text-sm text-quaternary mt-1">
Quantity: {item.qty}
</p>
<p className="font-semibold text-gray-900 mt-2">
${item.price}
</p>
</div>
<button className="text-gray-400 hover:text-red-600">
<X size={20} />
</button>
</div>
))}
<div className="border-t border-gray-200 pt-4 space-y-2">
<div className="flex justify-between text-secondary">
<span>Subtotal</span>
<span>$369.97</span>
</div>
<div className="flex justify-between text-secondary">
<span>Shipping</span>
<span>$10.00</span>
</div>
<div className="flex justify-between text-lg font-bold text-gray-900 pt-2 border-t border-gray-200">
<span>Total</span>
<span>$379.97</span>
</div>
</div>
</div>
}
footer={<Button className="w-full">Proceed to Checkout</Button>}
/>
</>
5. Notification Panel
Display notifications and updates in a slideout panel.
<div className="border border-gray-200 rounded-lg p-8 mb-4">
<Button onClick={() => setIsOpen5(true)} leftIcon={Bell} className="relative">
Notifications
<span className="absolute -top-1 -right-1 w-5 h-5 bg-red-500 text-white text-xs rounded-full flex items-center justify-center">
5
</span>
</Button>
<SlideoutCustom.Root open={isOpen5} onOpenChange={setIsOpen5}>
<SlideoutCustom.Content>
<SlideoutCustom.Header>
<SlideoutCustom.Title>Notifications</SlideoutCustom.Title>
<SlideoutCustom.Description>
You have 5 unread notifications
</SlideoutCustom.Description>
</SlideoutCustom.Header>
<SlideoutCustom.Body>
<div className="space-y-3">
{[
{
type: "success",
title: "Payment received",
desc: "Your payment of $99.99 was processed",
time: "2m ago",
},
{
type: "info",
title: "New message",
desc: "You have a new message from John",
time: "1h ago",
},
{
type: "warning",
title: "Update available",
desc: "A new version is available",
time: "3h ago",
},
{
type: "success",
title: "Order shipped",
desc: "Your order #1234 has been shipped",
time: "1d ago",
},
{
type: "info",
title: "Welcome!",
desc: "Thanks for signing up",
time: "2d ago",
},
].map((notif, i) => (
<div
key={i}
className="p-4 border border-gray-200 rounded-lg hover:bg-secondary cursor-pointer"
>
<div className="flex gap-3">
<div
className={`mt-1 w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 ${
notif.type === "success"
? "bg-green-100"
: notif.type === "warning"
? "bg-yellow-100"
: "bg-blue-100"
}`}
>
<Check
size={16}
className={
notif.type === "success"
? "text-success-primary"
: notif.type === "warning"
? "text-yellow-600"
: "text-blue-600"
}
/>
</div>
<div className="flex-1 min-w-0">
<p className="font-medium text-gray-900">
{notif.title}
</p>
<p className="text-sm text-quaternary mt-1">
{notif.desc}
</p>
<p className="text-xs text-gray-400 mt-2">
{notif.time}
</p>
</div>
</div>
</div>
))}
</div>
</SlideoutCustom.Body>
<SlideoutCustom.Footer>
<Button className="w-full">Mark all as read</Button>
</SlideoutCustom.Footer>
</SlideoutCustom.Content>
</SlideoutCustom.Root>
</div>
API Reference
Slideout Props (Simple API)
| Prop | Type | Default | Description |
|---|---|---|---|
| open | boolean | — | Controls the open state |
| onOpenChange | (open: boolean) => void | — | Callback when open state changes |
| title | string | — | Header title |
| description | string | — | Header description |
| content | ReactNode | — | Main content area |
| footer | ReactNode | — | Footer content |
| showCloseButton | boolean | true | Show close button in header |
SlideoutCustom Components
| Component | Description |
|---|---|
| Root | Main wrapper with drawer functionality |
| Trigger | Button to open the slideout |
| Content | Main slideout panel container |
| Header | Header section with close button |
| Title | Title text component |
| Description | Description text component |
| Body | Scrollable content area |
| Footer | Footer section for actions |