Nested Menu Drawer
attn-ui/nested-drawerFreeComponent
A fully accessible, animated drawer component with nested navigation support and smooth transitions.
Install it
npx shadcn@latest add https://attnui.com/r/nested-drawer.jsonSource
1"use client";23import { motion, AnimatePresence } from "motion/react";4import * as React from "react";5import Link from "next/link";6import { ChevronRight, ChevronLeft, type LucideIcon } from "lucide-react";7import { cn } from "@/lib/utils";89const ANIMATION_DURATION = 0.4;10const EASING = [0.32, 0.72, 0, 1] as const;1112export type MenuItem = {13 id: string;14 title: string;15 description?: string;16 icon?: LucideIcon;17 children?: MenuItem[];18 href?: string;19};2021type NestedDrawerContext = {22 menuStack: MenuItem[][];23 currentMenu: MenuItem[];24 direction: "forward" | "backward";25 navigateToMenu: (items: MenuItem[]) => void;26 navigateBack: () => void;27 canGoBack: boolean;28 open: boolean;29 setOpen: (open: boolean) => void;30};3132const NestedDrawerContext = React.createContext<33 NestedDrawerContext | undefined34>(undefined);3536const useNestedDrawer = () => {37 const context = React.useContext(NestedDrawerContext);38 if (!context) {39 throw new Error(40 "NestedDrawer compound components must be used within NestedDrawer"41 );42 }43 return context;44};4546type TNestedDrawerProps = {47 children: React.ReactNode;48 initialMenu: MenuItem[];49};5051export function NestedDrawer({ children, initialMenu }: TNestedDrawerProps) {52 const [open, setOpen] = React.useState(false);53 const [menuStack, setMenuStack] = React.useState<MenuItem[][]>([initialMenu]);54 const [direction, setDirection] = React.useState<"forward" | "backward">(55 "forward"56 );5758 const currentMenu = menuStack[menuStack.length - 1];59 const canGoBack = menuStack.length > 1;6061 const navigateToMenu = React.useCallback((items: MenuItem[]) => {62 setDirection("forward");63 setMenuStack((prev) => [...prev, items]);64 }, []);6566 const navigateBack = React.useCallback(() => {67 if (menuStack.length > 1) {68 setDirection("backward");69 setMenuStack((prev) => prev.slice(0, -1));70 }71 }, [menuStack.length]);7273 React.useEffect(() => {74 if (!open) {75 const timeout = setTimeout(() => {76 setMenuStack([initialMenu]);77 setDirection("forward");78 }, ANIMATION_DURATION * 1000);79 return () => clearTimeout(timeout);80 }81 }, [open, initialMenu]);8283 return (84 <NestedDrawerContext.Provider85 value={{86 menuStack,87 currentMenu,88 direction,89 navigateToMenu,90 navigateBack,91 canGoBack,92 open,93 setOpen,94 }}95 >96 {children}97 </NestedDrawerContext.Provider>98 );99}100101// … truncated
What it pulls in
npm packages
Files it writes
More from attn-ui
All 6 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Animated Avatar Stackanimated-avatar-stack | attn-ui | Components | Free | 2 deps · 2 files | |
| avataravatar | attn-ui | Components | Free | 1 dep | |
| buttonbutton | attn-ui | Components | Free | no deps | |
| Timezone Clocktimezone-clock | attn-ui | Components | Free | 1 dep · 2 files | |
| tooltiptooltip | attn-ui | Components | Free | 1 dep |
