FluxUI Pro is live - modern UI, powerful animations, zero hassle.
Components
Drawer

Drawer

Animated drawer component with backdrop blur and customizable positioning from all sides.

Installation

1

Install the packages

npm i motion clsx tailwind-merge
2

Add util file

lib/util.ts
import { ClassValue, clsx } from "clsx"; import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); }
3

Copy and paste the following code into your project

drawer.tsx
"use client"; import { cn } from "@/lib/utils"; import { motion, AnimatePresence } from "motion/react"; import React, { useEffect } from "react"; import { FiX } from "react-icons/fi"; interface DrawerProps { isOpen?: boolean; onClose?: () => void; position?: "left" | "right" | "top" | "bottom"; children?: React.ReactNode; title?: string; } const Drawer: React.FC<DrawerProps> = ({ isOpen = false, onClose = () => {}, position = "right", children, title = "Drawer Title" }) => { useEffect(() => { if (isOpen) { document.body.style.overflow = "hidden"; } else { document.body.style.overflow = "unset"; } return () => { document.body.style.overflow = "unset"; }; }, [isOpen]); const positionClasses = { left: "left-0 top-0 h-full w-80", right: "right-0 top-0 h-full w-80", top: "top-0 left-0 w-full h-80", bottom: "bottom-0 left-0 w-full h-80", }; const slideDirection = { left: { x: "-100%" }, right: { x: "100%" }, top: { y: "-100%" }, bottom: { y: "100%" }, }; return ( <AnimatePresence> {isOpen && ( <> {/* Backdrop */} <motion.div className="fixed inset-0 z-40 bg-black/50 backdrop-blur-sm" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} onClick={onClose} /> {/* Drawer */} <motion.div className={cn( "fixed z-50 bg-white dark:bg-neutral-900 border border-neutral-300 dark:border-neutral-700 shadow-xl", positionClasses[position] )} initial={{ ...slideDirection[position], opacity: 0 }} animate={{ x: 0, y: 0, opacity: 1 }} exit={{ ...slideDirection[position], opacity: 0 }} transition={{ duration: 0.3, ease: "easeOut" }} > {/* Header */} <div className="flex items-center justify-between p-4 border-b border-neutral-200 dark:border-neutral-700"> <h2 className="text-lg font-semibold text-neutral-900 dark:text-white"> {title} </h2> <button onClick={onClose} className="text-neutral-400 hover:text-neutral-600 dark:hover:text-neutral-200 transition-colors" > <FiX className="h-5 w-5" /> </button> </div> {/* Content */} <div className="p-4 overflow-y-auto flex-1"> {children || ( <p className="text-neutral-600 dark:text-neutral-300"> This is the drawer content. You can put any content here. </p> )} </div> </motion.div> </> )} </AnimatePresence> ); }; export default Drawer;
4

Update the import paths to match your project setup

Props

PropTypeDefaultDescription
isOpenbooleanfalseControls the visibility of the drawer.
onClosefunction() => {}Callback function when drawer is closed.
positionstringrightPosition of the drawer (left, right, top, bottom).
childrenReactNodenullContent to be displayed inside the drawer.
titlestringDrawer TitleTitle displayed in the drawer header.