Sidebar
A responsive navigation sidebar with collapsible support and organized sections.
Dashboard
Home
Messages
Profile
Content
Documents
Projects
Settings
Settings
Calendar
© 2025 My App
Installation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import * as React from "react"
import { cn } from "@/lib/utils"
interface SidebarProps extends React.HTMLAttributes<HTMLDivElement> {
collapsed?: boolean
}
const Sidebar = React.forwardRef<HTMLDivElement, SidebarProps>(
({ collapsed, className, children, ...props }, ref) => (
<div
ref={ref}
className={cn(
"flex flex-col h-screen bg-background border-r transition-all duration-300",
collapsed ? "w-16" : "w-64",
className
)}
{...props}
>
{children}
</div>
)
)
Sidebar.displayName = "Sidebar"
interface SidebarHeaderProps extends React.HTMLAttributes<HTMLDivElement> {
collapsed?: boolean
}
const SidebarHeader = React.forwardRef<HTMLDivElement, SidebarHeaderProps>(
({ collapsed, className, children, ...props }, ref) => (
<div
ref={ref}
className={cn(
"flex items-center h-14 px-4 border-b",
collapsed ? "justify-center" : "justify-between",
className
)}
{...props}
>
{children}
</div>
)
)
SidebarHeader.displayName = "SidebarHeader"
const SidebarContent = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, children, ...props }, ref) => (
<div
ref={ref}
className={cn("flex-1 overflow-auto py-2", className)}
{...props}
>
{children}
</div>
))
SidebarContent.displayName = "SidebarContent"
const SidebarFooter = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, children, ...props }, ref) => (
<div
ref={ref}
className={cn("p-4 border-t mt-auto", className)}
{...props}
>
{children}
</div>
))
SidebarFooter.displayName = "SidebarFooter"
interface SidebarItemProps extends React.HTMLAttributes<HTMLDivElement> {
icon?: React.ReactNode
collapsed?: boolean
active?: boolean
}
const SidebarItem = React.forwardRef<HTMLDivElement, SidebarItemProps>(
({ icon, collapsed, active, className, children, ...props }, ref) => (
<div
ref={ref}
className={cn(
"flex items-center py-2 px-4 cursor-pointer transition-colors rounded-md",
active
? "bg-muted text-foreground"
: "hover:bg-muted/50 text-muted-foreground hover:text-foreground",
collapsed ? "justify-center" : "",
className
)}
{...props}
>
{icon && <div className={collapsed ? "" : "mr-2"}>{icon}</div>}
{!collapsed && <div>{children}</div>}
</div>
)
)
SidebarItem.displayName = "SidebarItem"
interface SidebarSectionProps extends React.HTMLAttributes<HTMLDivElement> {
collapsed?: boolean
title?: string
}
const SidebarSection = React.forwardRef<HTMLDivElement, SidebarSectionProps>(
({ collapsed, title, className, children, ...props }, ref) => (
<div
ref={ref}
className={cn("py-2", className)}
{...props}
>
{title && !collapsed && (
<div className="text-xs font-semibold text-muted-foreground px-4 mb-1">
{title}
</div>
)}
{title && collapsed && (
<div className="mx-2 border-t my-2"></div>
)}
{children}
</div>
)
)
SidebarSection.displayName = "SidebarSection"
export {
Sidebar,
SidebarHeader,
SidebarContent,
SidebarFooter,
SidebarItem,
SidebarSection
}Note: The Sidebar component is a custom component and not part of the Radix UI primitives. It needs to be created manually.
Usage
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import {
Sidebar,
SidebarHeader,
SidebarContent,
SidebarFooter,
SidebarItem,
SidebarSection
} from "@/components/ui/sidebar"
import { Home, Settings, User, Mail } from "lucide-react"
import { Button } from "@/components/ui/button"
export function SidebarDemo() {
const [collapsed, setCollapsed] = React.useState(false)
return (
<Sidebar collapsed={collapsed}>
<SidebarHeader collapsed={collapsed}>
{!collapsed && <span className="text-lg font-semibold">Dashboard</span>}
<Button
variant="ghost"
size="icon"
onClick={() => setCollapsed(!collapsed)}
>
{collapsed ? "→" : "←"}
</Button>
</SidebarHeader>
<SidebarContent>
<SidebarSection>
<SidebarItem icon={<Home size={20} />} active collapsed={collapsed}>
Home
</SidebarItem>
<SidebarItem icon={<Mail size={20} />} collapsed={collapsed}>
Messages
</SidebarItem>
<SidebarItem icon={<User size={20} />} collapsed={collapsed}>
Profile
</SidebarItem>
</SidebarSection>
<SidebarSection title="Settings" collapsed={collapsed}>
<SidebarItem icon={<Settings size={20} />} collapsed={collapsed}>
Settings
</SidebarItem>
</SidebarSection>
</SidebarContent>
<SidebarFooter>
{!collapsed && (
<div className="text-xs text-muted-foreground">
© 2025 My App
</div>
)}
</SidebarFooter>
</Sidebar>
)
}Examples
Collapsible Sidebar
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// Collapsible sidebar example
import { useState } from "react"
function CollapsibleSidebar() {
const [collapsed, setCollapsed] = useState(false)
return (
<Sidebar collapsed={collapsed}>
<SidebarHeader collapsed={collapsed}>
{!collapsed && <span className="text-lg font-semibold">Dashboard</span>}
<Button
variant="ghost"
size="icon"
onClick={() => setCollapsed(!collapsed)}
>
{collapsed ? "→" : "←"}
</Button>
</SidebarHeader>
<SidebarContent>
<SidebarSection collapsed={collapsed}>
<SidebarItem icon={<Home size={20} />} active collapsed={collapsed}>
Home
</SidebarItem>
<SidebarItem icon={<Mail size={20} />} collapsed={collapsed}>
Messages
</SidebarItem>
<SidebarItem icon={<User size={20} />} collapsed={collapsed}>
Profile
</SidebarItem>
</SidebarSection>
<SidebarSection title="Settings" collapsed={collapsed}>
<SidebarItem icon={<Settings size={20} />} collapsed={collapsed}>
Settings
</SidebarItem>
</SidebarSection>
</SidebarContent>
<SidebarFooter>
{!collapsed && (
<div className="text-xs text-muted-foreground">
© 2025 My App
</div>
)}
</SidebarFooter>
</Sidebar>
)
}With Multiple Sections
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// With additional items and sections
<Sidebar>
<SidebarHeader>
<span className="text-lg font-semibold">Dashboard</span>
<Button variant="ghost" size="icon">
<Menu size={20} />
</Button>
</SidebarHeader>
<SidebarContent>
<SidebarSection>
<SidebarItem icon={<Home size={20} />} active>
Home
</SidebarItem>
<SidebarItem icon={<Mail size={20} />}>
Messages
</SidebarItem>
<SidebarItem icon={<User size={20} />}>
Profile
</SidebarItem>
</SidebarSection>
<SidebarSection title="Content">
<SidebarItem icon={<FileText size={20} />}>
Documents
</SidebarItem>
<SidebarItem icon={<Image size={20} />}>
Media
</SidebarItem>
</SidebarSection>
<SidebarSection title="Organization">
<SidebarItem icon={<Users size={20} />}>
Team
</SidebarItem>
<SidebarItem icon={<Calendar size={20} />}>
Calendar
</SidebarItem>
</SidebarSection>
<SidebarSection title="Configuration">
<SidebarItem icon={<Settings size={20} />}>
Settings
</SidebarItem>
<SidebarItem icon={<HelpCircle size={20} />}>
Help
</SidebarItem>
</SidebarSection>
</SidebarContent>
<SidebarFooter>
<div className="text-xs text-muted-foreground">
© 2025 My App
</div>
</SidebarFooter>
</Sidebar>Props
| Component | Props | Description |
|---|---|---|
| Sidebar | React.HTMLAttributes & { collapsed?: boolean } | The root container for the sidebar. The collapsed prop controls the expanded/collapsed state. |
| SidebarHeader | React.HTMLAttributes & { collapsed?: boolean } | The header section of the sidebar, typically containing the logo or title. |
| SidebarContent | React.HTMLAttributes | The main content area of the sidebar, containing navigation items. |
| SidebarFooter | React.HTMLAttributes | The footer section of the sidebar, typically containing copyright info or user controls. |
| SidebarItem | React.HTMLAttributes & { icon?: React.ReactNode collapsed?: boolean active?: boolean } | A navigation item within the sidebar. Can have an icon and active state. |
| SidebarSection | React.HTMLAttributes & { collapsed?: boolean title?: string } | A grouping of related sidebar items with an optional title. |