Back to Dictionary
Page & View Transitions
●○○Ready to Use
Recommended default

Drawer / Sidebar Slide

A panel that slides in from the left or right edge of the screen, pushing content or overlapping it with a dark backdrop.

Use

Mobile navigation menus

Avoid

Quick confirmations (use Modal or Toast)

Safer Alternative

No safer default listed.

Risk Level

Low risk

Live Demo

Dashboard

Click the menu icon in the top left or the button below to open the sidebar drawer.

What It Is

A panel that slides in from the left or right edge of the screen, pushing content or overlapping it with a dark backdrop.

When to Use

  • Mobile navigation menus
  • Filtering and sorting options
  • Detail inspection panels in dense dashboards

When NOT to Use

  • Quick confirmations (use Modal or Toast)

Configuration Tips

  • 01Slide in from the right for details/actions, from the left for global navigation
  • 02Include a swipe-to-dismiss gesture for mobile users

You've Seen It In

LinearStripe DashboardShopify

AI Implementation Prompts

Move from a fast scaffold to production details, then tune timing and edge states.

Add a sidebar drawer that slides in from the right when clicking the edit button. Include a dark backdrop.

Reference Implementation

The same implementation approach used by the live preview, kept compact enough to inspect and adapt.

"use client";
import { useState, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { Menu, X } from 'lucide-react';

export function DrawerSidebarSlideDemo({ isPlaying = false }: { isPlaying?: boolean }) {
    const [isOpen, setIsOpen] = useState(false);

    useEffect(() => {
        if (!isPlaying) {
            setIsOpen(false);
            return;
        }
        const interval = setInterval(() => {
            setIsOpen(true);
            setTimeout(() => setIsOpen(false), 2000);
        }, 3000);
        return () => clearInterval(interval);
    }, [isPlaying]);

    return (
        <div className="relative flex h-64 w-full flex-col items-center justify-center overflow-hidden rounded-2xl bg-white p-6 shadow-sm ring-1 ring-stone-200">

            {"text-stone-400 italic">/* Mock App Header */}
            <div className="absolute top-0 left-0 right-0 h-14 bg-white border-b border-stone-200 flex items-center px-4 justify-between z-0">
                <button
                    onClick={() => setIsOpen(true)}
                    className="p-2 hover:bg-stone-100 rounded-lg transition-colors text-stone-600 focus:outline-none focus:ring-2 focus:ring-stone-400"
                >
                    <Menu className="w-5 h-5" />
                </button>
                <div className="w-24 h-4 bg-stone-200 rounded-full" />
                <div className="w-8 h-8 rounded-full bg-stone-200" />
            </div>

            <div className="flex flex-col items-center text-center space-y-4 max-w-xs mt-10">
                <div className="text-stone-500 font-medium">Dashboard</div>
                <p className="text-sm text-stone-400">Click the menu icon in the top left or the button below to open the sidebar drawer.</p>
                <button
                    onClick={() => setIsOpen(true)}
                    className="px-4 py-2 bg-stone-800 text-white rounded-lg text-sm font-medium shadow-sm hover:bg-stone-700 transition"
                >
                    Open Drawer
                </button>
            </div>

            <AnimatePresence>
                {isOpen && (
                    <>
                        {"text-stone-400 italic">/* Backdrop */}
                        <motion.div
                            initial={{ opacity: 0 }}
                            animate={{ opacity: 1 }}
                            exit={{ opacity: 0 }}
                            onClick={() => setIsOpen(false)}
                            className="absolute inset-0 bg-stone-900/20 backdrop-blur-sm z-10"
                        />

                        {"text-stone-400 italic">/* Drawer */}
                        <motion.div
                            initial={{ x: '-100%' }}
                            animate={{ x: 0 }}
                            exit={{ x: '-100%' }}
                            transition={{ type: 'spring', bounce: 0, duration: 0.4 }}
                            className="absolute top-0 left-0 bottom-0 w-64 bg-white shadow-2xl z-20 flex flex-col"
                        >
                            <div className="p-4 flex items-center justify-between border-b border-stone-100">
                                <span className="font-semibold text-stone-900">Navigation</span>
                                <button
                                    onClick={() => setIsOpen(false)}
                                    className="p-1.5 hover:bg-stone-100 rounded-md transition-colors text-stone-500 focus:outline-none focus:ring-2 focus:ring-stone-400"
                                >
                                    <X className="w-4 h-4" />
                                </button>
                            </div>
                            <div className="p-4 space-y-1 flex-grow">
                                {['Home', 'Profile', 'Settings', 'Analytics', 'Help'].map((item, i) => (
                                    <motion.div
                                        initial={{ opacity: 0, x: -10 }}
                                        animate={{ opacity: 1, x: 0 }}
                                        transition={{ delay: 0.1 + i * 0.05 }}
                                        key={item}
                                        className="px-3 py-2.5 hover:bg-stone-50 rounded-lg cursor-pointer text-stone-700 text-sm font-medium transition-colors"
                                        onClick={() => setIsOpen(false)}
                                    >
                                        {item}
                                    </motion.div>
                                ))}
                            </div>
                            <div className="p-4 border-t border-stone-100 text-xs text-stone-400">
                                v1.0.0
                            </div>
                        </motion.div>
                    </>
                )}
            </AnimatePresence>
        </div>
    );
}