Guide
How to build a collapsible animated sidebar in Next.js
An application sidebar has more moving parts than it looks: desktop and mobile states, a collapsed icon rail, a toggle that works from anywhere, and focus handling when it becomes a sheet on small screens. This guide walks through each part using the beUI Animated Sidebar, which follows the same provider and composition model as the shadcn sidebar and adds Framer Motion transitions.
Icon rail vs offcanvas: choosing a collapse mode
The collapsible prop on AnimatedSidebar decides what closing does on desktop. With icon, the default, the panel springs down to a narrow rail: labels fade out, icons stay, and each button gets the label as its accessible name and title. With offcanvas, the panel slides fully out of view and the inset content takes the whole width. With none, the sidebar stays open.
Widths come from CSS variables on the provider: --sidebar-width (16rem), --sidebar-width-icon (4.25rem) and --sidebar-width-mobile (18rem). Override them through the provider's style prop. AnimatedSidebar also takes side (left or right) and variant (sidebar, floating or inset).
- Pass open, defaultOpen and onOpenChange to the provider to control or persist the desktop state, for example in a cookie.
- Use AnimatedSidebarMenuSub with AnimatedSidebarMenuSubItem and AnimatedSidebarMenuSubButton for nested items. Selecting a group from the icon rail expands the panel so its children are reachable.
- AnimatedSidebarRail adds a thin edge you can click to toggle the panel.
<AnimatedSidebarMenuItem>
<AnimatedSidebarMenuButton
icon={<Target className="size-4" />}
ariaExpanded={open}
onSelect={() => setOpen((value) => !value)}
>
Opportunities
</AnimatedSidebarMenuButton>
<AnimatedSidebarMenuSub open={open}>
<AnimatedSidebarMenuSubItem>
<AnimatedSidebarMenuSubButton href="/pipeline" isActive={pathname === "/pipeline"}>
Pipeline
</AnimatedSidebarMenuSubButton>
</AnimatedSidebarMenuSubItem>
</AnimatedSidebarMenuSub>
</AnimatedSidebarMenuItem>Mobile sheet and keyboard shortcut
Below 768px the same AnimatedSidebar renders as a sheet in a portal on document.body: a dialog with aria-modal that slides in over a dimmed backdrop. Opening it locks page scroll and moves focus to the first focusable item; Tab and Shift+Tab stay inside the sheet, Escape or the backdrop closes it, and focus returns to the trigger. Selecting a regular menu item closes the sheet, while items with ariaExpanded keep it open so the submenu can unfold.
Cmd+B on macOS or Ctrl+B elsewhere calls toggleSidebar, which toggles the desktop panel or the mobile sheet depending on the viewport. Use AnimatedSidebarClose inside the panel for an explicit close button on mobile.
Components in this guide
Animated Sidebar
A composable application sidebar with morphing nested navigation that folds into an animated icon rail on desktop and becomes a focus-managed sheet on mobile.
Bounce Sidebar
A vertical sidebar whose active dot jumps between destinations on a curved, spring-loaded path.
AI Sidebar
A collapsible AI workspace sidebar for folders, projects, files, and bookmarks with keyboard navigation, optimistic moves, inline rename, and overflow-aware labels.
Dock
macOS-style dock with grouped actions and a gliding active pill.
FAQ
- How do I make a collapsible sidebar in Next.js?
- Wrap your app layout in a client component that renders AnimatedSidebarProvider, AnimatedSidebar and AnimatedSidebarInset, add an AnimatedSidebarTrigger in your header, and pick collapsible="icon" or "offcanvas".
- Is the beUI Animated Sidebar compatible with shadcn/ui?
- It installs through the shadcn CLI and follows the same composition model as the shadcn sidebar, with a provider, a panel, an inset and menu parts. It is its own component, so the part names start with AnimatedSidebar.
- What keyboard shortcut toggles the sidebar?
- Cmd+B on macOS and Ctrl+B on other platforms. It toggles the desktop panel, or the mobile sheet on small screens.
- How do I remember whether the sidebar was collapsed?
- Control the provider with open and onOpenChange, save the value in a cookie or local storage, and read it back as the initial value. Reading a cookie on the server avoids a flash of the wrong state.
- Can the sidebar sit on the right side?
- Yes. Pass side="right" to AnimatedSidebar. The mobile sheet then slides in from the right as well.
Updated