Collapsible Sidebar Menu
This is a sidebar navigation that can be used on dashboards, etc., and can be collapsed to an icon-only state.
ReactTailwind CSSlucide-react
A sidebar navigation that allows you to switch between a full-size display with text and a compact display with only icons, often seen on management screens and dashboards. Ideal if you want to maximize the display area of the content area.
Preview
Dashboard Overview
Welcome back, Jane. Here is what’s happening today.
Total Revenue
$45,231
Active Users
2,410
New Orders
142
Recent Activity
Use Cases & Features
- Dashboard & Admin Screen: Designed to allow users to focus on the main content (graphs, data tables, etc.) by collapsing the navigation as needed.
- Completion with tooltips: Even when it is in a compact state with only icons, accessibility and ease of use are ensured by displaying tooltips on hover.
- Smooth animation: By combining width, transparency (
opacity), andmax-width, we achieve natural movement in which text disappears and appears smoothly.
Key points of design and UX (Design & UX)
- Text overflow prevention: Combining
max-w-0andoverflow-hiddenprevents the text from breaking into new lines and breaking the layout when folded. - Visually highlighting the active state: The currently selected menu item has a blue background and text color to intuitively convey the current position.
- Guiding the eye: The toggle button for opening and closing is placed on the border of the sidebar to increase the affordance of “press here to move.”
How to customize (Customization Guide)
- Change the width of the sidebar: You can adjust it to your desired size by changing
w-64(when expanded) orw-20(when collapsed) on the implementation code side. - Changing theme colors: By replacing the
bg-blue-600andtext-blue-700utility classes all at once, you can apply them to designs that match your brand colors.
Implementation code (Implementation)
<div className="flex h-screen bg-slate-50 font-sans overflow-hidden">
{/* Sidebar */}
<aside
className={`bg-white border-r border-slate-200 flex flex-col transition-all duration-300 ease-in-out relative z-10 ${
isCollapsed ? 'w-20' : 'w-64'
}`}
>
{/* Header */}
<div className="h-16 flex items-center px-4 border-b border-slate-100 shrink-0">
<div className="flex items-center gap-3 overflow-hidden whitespace-nowrap">
<div className="w-10 h-10 rounded-xl bg-blue-600 flex items-center justify-center shrink-0 shadow-sm shadow-blue-200">
<Hexagon className="w-6 h-6 text-white" />
</div>
<span
className={`font-bold text-slate-800 text-xl transition-all duration-300 overflow-hidden ${
isCollapsed ? 'max-w-0 opacity-0' : 'max-w-[200px] opacity-100'
}`}
>
DashUI
</span>
</div>
</div>
{/* Navigation */}
<nav className="flex-1 py-6 px-3 space-y-2 overflow-y-auto overflow-x-hidden">
{navItems.map((item, index) => (
<a
key={index}
href="#"
className={`flex items-center gap-3 px-3 py-3 rounded-xl transition-colors group relative ${
item.active
? 'text-blue-700 bg-blue-50 hover:bg-blue-100'
: 'text-slate-500 hover:bg-slate-100 hover:text-slate-900'
}`}
>
<item.icon className="w-6 h-6 shrink-0" />
<span
className={`font-semibold whitespace-nowrap transition-all duration-300 flex-1 text-sm overflow-hidden ${
isCollapsed ? 'max-w-0 opacity-0' : 'max-w-[200px] opacity-100'
}`}
>
{item.label}
</span>
{/* Badge display (only when expanded) */}
{!isCollapsed && item.badge && (
<span className="bg-blue-100 text-blue-700 py-0.5 px-2 rounded-full text-xs font-bold whitespace-nowrap">
{item.badge}
</span>
)}
{/* Tooltip (displayed on hover only when collapsed) */}
{isCollapsed && (
<div className="absolute left-14 hidden group-hover:block bg-slate-800 text-white text-xs px-2.5 py-1.5 rounded-md shadow-lg z-20 whitespace-nowrap pointer-events-none opacity-0 transition-opacity duration-200 group-hover:opacity-100">
{item.label}
</div>
)}
</a>
))}
</nav>
{/* Footer Profile */}
<div className="p-4 border-t border-slate-100 shrink-0">
<a href="#" className="flex items-center gap-3 hover:bg-slate-50 p-2 -m-2 rounded-xl transition-colors">
<img
src="https://i.pravatar.cc/150?u=a042581f4e29026704d"
alt="User Avatar"
className="w-10 h-10 rounded-full shrink-0 border border-slate-200 object-cover"
/>
<div
className={`flex-1 min-w-0 transition-all duration-300 overflow-hidden ${
isCollapsed ? 'max-w-0 opacity-0' : 'max-w-[200px] opacity-100'
}`}
>
<p className="text-sm font-semibold text-slate-900 truncate">Jane Doe</p>
<p className="text-xs text-slate-500 truncate">Admin</p>
</div>
</a>
</div>
</aside>
{/* Toggle Button */}
<button
onClick={() => setIsCollapsed(!isCollapsed)}
className={`absolute top-6 z-20 cursor-pointer bg-white border border-slate-200 text-slate-500 hover:text-blue-600 hover:bg-blue-50 rounded-full p-1.5 shadow-sm transition-all duration-300 ${
isCollapsed ? 'left-[4.2rem]' : 'left-[15rem]'
}`}
aria-label={isCollapsed ? "Expand sidebar" : "Collapse sidebar"}
>
<ChevronLeft className={`w-4 h-4 transition-transform duration-300 ${isCollapsed ? 'rotate-180' : ''}`} />
</button>
{/* Main Content Area (Example) */}
<main className="flex-1 p-8 overflow-y-auto">
<h1 className="text-2xl font-bold text-slate-900">Dashboard</h1>
<p className="text-slate-500 mt-1">Select an item from the sidebar.</p>
</main>
</div>
);
} Browser Support
- Works well with the latest versions of modern browsers (Chrome, Firefox, Safari, Edge).
transition-allandmax-w-0animations also render smoothly in all modern browsers.