Sidebar
A composable, themeable and customizable sidebar component.
The Sidebar component provides a flexible navigation structure with sections, menus, and collapsible items. It supports collapsed/expanded states, icons, badges, and nested submenus. Built from scratch using React and native HTML elements. No dependencies on any UI library.
Code
TypeScript: Copy this code into components/ui/sidebar.tsx:
tsx
"use client"
import * as React from "react"
import Link from "next/link"
import { cn } from "@/lib/utils"
interface SidebarContextValue {
collapsed: boolean
setCollapsed: (collapsed: boolean) => void
}
const SidebarContext = React.createContext<SidebarContextValue | undefined>(undefined)
const useSidebar = () => {
const context = React.useContext(SidebarContext)
if (!context) {
throw new Error("Sidebar components must be used within Sidebar")
}
return context
}
interface SidebarProps extends React.HTMLAttributes<HTMLDivElement> {
defaultCollapsed?: boolean
collapsed?: boolean
onCollapsedChange?: (collapsed: boolean) => void
}
const Sidebar = React.forwardRef<HTMLDivElement, SidebarProps>(
({ className, defaultCollapsed = false, collapsed: controlledCollapsed, onCollapsedChange, children, ...props }, ref) => {
const [uncontrolledCollapsed, setUncontrolledCollapsed] = React.useState(defaultCollapsed)
const isControlled = controlledCollapsed !== undefined
const collapsed = isControlled ? controlledCollapsed : uncontrolledCollapsed
const handleCollapsedChange = React.useCallback((newCollapsed: boolean) => {
if (!isControlled) {
setUncontrolledCollapsed(newCollapsed)
}
onCollapsedChange?.(newCollapsed)
}, [isControlled, onCollapsedChange])
return (
<SidebarContext.Provider value={{ collapsed, setCollapsed: handleCollapsedChange }}>
<aside
ref={ref}
className={cn(
"flex flex-col border-r-2 border-foreground bg-background transition-all duration-300",
collapsed ? "w-16" : "w-64",
className
)}
{...props}
>
{children}
</aside>
</SidebarContext.Provider>
)
}
)
Sidebar.displayName = "Sidebar"
const SidebarHeader = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex items-center border-b-2 border-foreground p-4", className)}
{...props}
/>
))
SidebarHeader.displayName = "SidebarHeader"
interface SidebarBrandProps extends React.HTMLAttributes<HTMLDivElement> {
icon?: React.ReactNode
title: string
subtitle?: string
}
const SidebarBrand = React.forwardRef<HTMLDivElement, SidebarBrandProps>(
({ className, icon, title, subtitle, children, ...props }, ref) => {
const { collapsed } = useSidebar()
return (
<div
ref={ref}
className={cn("flex items-center gap-3", className)}
{...props}
>
{icon && (
<div className={cn("flex-shrink-0", collapsed && "mx-auto")}>
{icon}
</div>
)}
{!collapsed && (
<div className="flex-1 min-w-0">
<div className="font-bold text-sm truncate">{title}</div>
{subtitle && (
<div className="text-xs text-muted-foreground truncate">{subtitle}</div>
)}
</div>
)}
{children}
</div>
)
}
)
SidebarBrand.displayName = "SidebarBrand"
const SidebarContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex-1 overflow-y-auto p-4", className)}
{...props}
/>
)
)
SidebarContent.displayName = "SidebarContent"
interface SidebarSectionProps extends React.HTMLAttributes<HTMLDivElement> {
label?: string
}
const SidebarSection = React.forwardRef<HTMLDivElement, SidebarSectionProps>(
({ className, label, children, ...props }, ref) => {
const { collapsed } = useSidebar()
return (
<div
ref={ref}
className={cn("space-y-2 mb-6", className)}
{...props}
>
{label && !collapsed && (
<div className="px-2 text-xs font-bold uppercase text-muted-foreground">
{label}
</div>
)}
{children}
</div>
)
}
)
SidebarSection.displayName = "SidebarSection"
const SidebarMenu = React.forwardRef<HTMLUListElement, React.HTMLAttributes<HTMLUListElement>>(
({ className, ...props }, ref) => (
<ul
ref={ref}
className={cn("space-y-1", className)}
{...props}
/>
)
)
SidebarMenu.displayName = "SidebarMenu"
const SidebarMenuItem = React.forwardRef<HTMLLIElement, React.LiHTMLAttributes<HTMLLIElement>>(
({ className, ...props }, ref) => (
<li
ref={ref}
className={cn("", className)}
{...props}
/>
)
)
SidebarMenuItem.displayName = "SidebarMenuItem"
interface SidebarMenuButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
asChild?: boolean
isActive?: boolean
icon?: React.ReactNode
badge?: React.ReactNode
rightIcon?: React.ReactNode
}
const SidebarMenuButton = React.forwardRef<HTMLButtonElement, SidebarMenuButtonProps>(
({ className, asChild, isActive, icon, badge, rightIcon, children, ...props }, ref) => {
const { collapsed } = useSidebar()
const buttonClassName = cn(
"flex w-full items-center gap-3 rounded-md px-3 py-2 text-sm font-bold transition-colors",
"hover:bg-accent hover:text-accent-foreground",
isActive && "bg-accent text-accent-foreground",
collapsed && "justify-center px-2",
className
)
if (asChild && React.isValidElement(children)) {
return React.cloneElement(children, {
className: cn(buttonClassName, children.props.className),
ref,
...props,
} as any)
}
return (
<button
ref={ref}
className={buttonClassName}
{...props}
>
{icon && (
<span className={cn("flex-shrink-0", collapsed && "mx-auto")}>
{icon}
</span>
)}
{!collapsed && (
<>
<span className="flex-1 text-left">{children}</span>
{badge && <span className="ml-auto">{badge}</span>}
{rightIcon && <span className="ml-auto">{rightIcon}</span>}
</>
)}
</button>
)
}
)
SidebarMenuButton.displayName = "SidebarMenuButton"
const SidebarMenuSub = ({ children }: { children: React.ReactNode }) => {
return <>{children}</>
}
interface SidebarMenuSubItemProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
icon?: React.ReactNode
isActive?: boolean
}
const SidebarMenuSubItem = React.forwardRef<HTMLButtonElement, SidebarMenuSubItemProps>(
({ className, icon, isActive, children, ...props }, ref) => {
const { collapsed } = useSidebar()
if (collapsed) return null
return (
<button
ref={ref}
className={cn(
"flex w-full items-center gap-3 rounded-md px-3 py-2 pl-8 text-sm font-bold transition-colors",
"hover:bg-accent hover:text-accent-foreground",
isActive && "bg-accent text-accent-foreground",
className
)}
{...props}
>
{icon && <span className="flex-shrink-0">{icon}</span>}
<span className="flex-1 text-left">{children}</span>
</button>
)
}
)
SidebarMenuSubItem.displayName = "SidebarMenuSubItem"
const SidebarMenuSeparator = React.forwardRef<
HTMLHRElement,
React.HTMLAttributes<HTMLHRElement>
>(({ className, ...props }, ref) => (
<hr
ref={ref}
className={cn("my-2 border-t-2 border-foreground", className)}
{...props}
/>
))
SidebarMenuSeparator.displayName = "SidebarMenuSeparator"
const SidebarFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("border-t-2 border-foreground p-4", className)}
{...props}
/>
)
)
SidebarFooter.displayName = "SidebarFooter"
const SidebarTrigger = React.forwardRef<
HTMLButtonElement,
React.ButtonHTMLAttributes<HTMLButtonElement>
>(({ className, ...props }, ref) => {
const { collapsed, setCollapsed } = useSidebar()
return (
<button
ref={ref}
onClick={() => setCollapsed(!collapsed)}
className={cn(
"flex h-8 w-8 items-center justify-center rounded-md border-2 border-foreground bg-background transition-colors hover:bg-accent hover:text-accent-foreground neobrutalism-shadow-sm active:translate-x-[1px] active:translate-y-[1px] active:shadow-none",
className
)}
{...props}
>
<svg
className="h-4 w-4"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M4 6h16M4 12h16M4 18h16"
/>
</svg>
<span className="sr-only">Toggle sidebar</span>
</button>
)
})
SidebarTrigger.displayName = "SidebarTrigger"
export {
Sidebar,
SidebarHeader,
SidebarBrand,
SidebarContent,
SidebarSection,
SidebarMenu,
SidebarMenuItem,
SidebarMenuButton,
SidebarMenuSub,
SidebarMenuSubItem,
SidebarMenuSeparator,
SidebarFooter,
SidebarTrigger,
}JavaScript: Copy this code into components/ui/sidebar.jsx:
jsx
"use client"
import * as React from "react"
import Link from "next/link"
import { cn } from "@/lib/utils"
const SidebarContext = React.createContext(undefined)
const useSidebar = () => {
const context = React.useContext(SidebarContext)
if (!context) {
throw new Error("Sidebar components must be used within Sidebar")
}
return context
}
const Sidebar = React.forwardRef(
({ className, defaultCollapsed = false, collapsed: controlledCollapsed, onCollapsedChange, children, ...props }, ref) => {
const [uncontrolledCollapsed, setUncontrolledCollapsed] = React.useState(defaultCollapsed)
const isControlled = controlledCollapsed !== undefined
const collapsed = isControlled ? controlledCollapsed : uncontrolledCollapsed
const handleCollapsedChange = React.useCallback((newCollapsed) => {
if (!isControlled) {
setUncontrolledCollapsed(newCollapsed)
}
onCollapsedChange?.(newCollapsed)
}, [isControlled, onCollapsedChange])
return (
<SidebarContext.Provider value={{ collapsed, setCollapsed: handleCollapsedChange }}>
<aside
ref={ref}
className={cn(
"flex flex-col border-r-2 border-foreground bg-background transition-all duration-300",
collapsed ? "w-16" : "w-64",
className
)}
{...props}
>
{children}
</aside>
</SidebarContext.Provider>
)
}
)
Sidebar.displayName = "Sidebar"
const SidebarHeader = React.forwardRef(
({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex items-center border-b-2 border-foreground p-4", className)}
{...props}
/>
)
)
SidebarHeader.displayName = "SidebarHeader"
const SidebarBrand = React.forwardRef(
({ className, icon, title, subtitle, children, ...props }, ref) => {
const { collapsed } = useSidebar()
return (
<div
ref={ref}
className={cn("flex items-center gap-3", className)}
{...props}
>
{icon && (
<div className={cn("flex-shrink-0", collapsed && "mx-auto")}>
{icon}
</div>
)}
{!collapsed && (
<div className="flex-1 min-w-0">
<div className="font-bold text-sm truncate">{title}</div>
{subtitle && (
<div className="text-xs text-muted-foreground truncate">{subtitle}</div>
)}
</div>
)}
{children}
</div>
)
}
)
SidebarBrand.displayName = "SidebarBrand"
const SidebarContent = React.forwardRef(
({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex-1 overflow-y-auto p-4", className)}
{...props}
/>
)
)
SidebarContent.displayName = "SidebarContent"
const SidebarSection = React.forwardRef(
({ className, label, children, ...props }, ref) => {
const { collapsed } = useSidebar()
return (
<div
ref={ref}
className={cn("space-y-2 mb-6", className)}
{...props}
>
{label && !collapsed && (
<div className="px-2 text-xs font-bold uppercase text-muted-foreground">
{label}
</div>
)}
{children}
</div>
)
}
)
SidebarSection.displayName = "SidebarSection"
const SidebarMenu = React.forwardRef(
({ className, ...props }, ref) => (
<ul
ref={ref}
className={cn("space-y-1", className)}
{...props}
/>
)
)
SidebarMenu.displayName = "SidebarMenu"
const SidebarMenuItem = React.forwardRef(
({ className, ...props }, ref) => (
<li
ref={ref}
className={cn("", className)}
{...props}
/>
)
)
SidebarMenuItem.displayName = "SidebarMenuItem"
const SidebarMenuButton = React.forwardRef(
({ className, asChild, isActive, icon, badge, rightIcon, children, ...props }, ref) => {
const { collapsed } = useSidebar()
const buttonClassName = cn(
"flex w-full items-center gap-3 rounded-md px-3 py-2 text-sm font-bold transition-colors",
"hover:bg-accent hover:text-accent-foreground",
isActive && "bg-accent text-accent-foreground",
collapsed && "justify-center px-2",
className
)
if (asChild && React.isValidElement(children)) {
return React.cloneElement(children, {
className: cn(buttonClassName, children.props.className),
ref,
...props,
})
}
return (
<button
ref={ref}
className={buttonClassName}
{...props}
>
{icon && (
<span className={cn("flex-shrink-0", collapsed && "mx-auto")}>
{icon}
</span>
)}
{!collapsed && (
<>
<span className="flex-1 text-left">{children}</span>
{badge && <span className="ml-auto">{badge}</span>}
{rightIcon && <span className="ml-auto">{rightIcon}</span>}
</>
)}
</button>
)
}
)
SidebarMenuButton.displayName = "SidebarMenuButton"
const SidebarMenuSub = ({ children }) => {
return <>{children}</>
}
const SidebarMenuSubItem = React.forwardRef(
({ className, icon, isActive, children, ...props }, ref) => {
const { collapsed } = useSidebar()
if (collapsed) return null
return (
<button
ref={ref}
className={cn(
"flex w-full items-center gap-3 rounded-md px-3 py-2 pl-8 text-sm font-bold transition-colors",
"hover:bg-accent hover:text-accent-foreground",
isActive && "bg-accent text-accent-foreground",
className
)}
{...props}
>
{icon && <span className="flex-shrink-0">{icon}</span>}
<span className="flex-1 text-left">{children}</span>
</button>
)
}
)
SidebarMenuSubItem.displayName = "SidebarMenuSubItem"
const SidebarMenuSeparator = React.forwardRef(
({ className, ...props }, ref) => (
<hr
ref={ref}
className={cn("my-2 border-t-2 border-foreground", className)}
{...props}
/>
)
)
SidebarMenuSeparator.displayName = "SidebarMenuSeparator"
const SidebarFooter = React.forwardRef(
({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("border-t-2 border-foreground p-4", className)}
{...props}
/>
)
)
SidebarFooter.displayName = "SidebarFooter"
const SidebarTrigger = React.forwardRef(
({ className, ...props }, ref) => {
const { collapsed, setCollapsed } = useSidebar()
return (
<button
ref={ref}
onClick={() => setCollapsed(!collapsed)}
className={cn(
"flex h-8 w-8 items-center justify-center rounded-md border-2 border-foreground bg-background transition-colors hover:bg-accent hover:text-accent-foreground neobrutalism-shadow-sm active:translate-x-[1px] active:translate-y-[1px] active:shadow-none",
className
)}
{...props}
>
<svg
className="h-4 w-4"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M4 6h16M4 12h16M4 18h16"
/>
</svg>
<span className="sr-only">Toggle sidebar</span>
</button>
)
}
)
SidebarTrigger.displayName = "SidebarTrigger"
export {
Sidebar,
SidebarHeader,
SidebarBrand,
SidebarContent,
SidebarSection,
SidebarMenu,
SidebarMenuItem,
SidebarMenuButton,
SidebarMenuSub,
SidebarMenuSubItem,
SidebarMenuSeparator,
SidebarFooter,
SidebarTrigger,
}Usage
TypeScript:
tsx
import {
Sidebar,
SidebarHeader,
SidebarBrand,
SidebarContent,
SidebarSection,
SidebarMenu,
SidebarMenuItem,
SidebarMenuButton,
SidebarMenuSub,
SidebarMenuSubItem,
SidebarMenuSeparator,
SidebarFooter,
SidebarTrigger,
} from "@/components/ui/sidebar"
import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from "@/components/ui/select"
function MyComponent() {
return (
<Sidebar>
<SidebarHeader>
<SidebarBrand
icon={
<svg className="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
}
title="Acme Inc"
subtitle="Enterprise"
>
<button className="ml-auto">
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 15l7-7 7 7" />
</svg>
</button>
</SidebarBrand>
</SidebarHeader>
<SidebarContent>
<SidebarSection label="Platform">
<Select value="playground" onValueChange={(value) => console.log(value)}>
<SelectTrigger className="w-full mb-2">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="playground">Playground</SelectItem>
<SelectItem value="production">Production</SelectItem>
</SelectContent>
</Select>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton>History</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton>Starred</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton>Settings</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarSection>
<SidebarSection>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton
icon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2" />
</svg>
}
rightIcon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
}
>
Models
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton
icon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" />
</svg>
}
rightIcon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
}
>
Documentation
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton
icon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
}
rightIcon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
}
>
Settings
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarSection>
<SidebarSection label="Projects">
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton
icon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M7 20l4-16m2 16l4-16M6 9h14M4 15h14" />
</svg>
}
rightIcon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z" />
</svg>
}
>
Design Engineering
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton
icon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
}
rightIcon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z" />
</svg>
}
>
Sales & Marketing
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton
icon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4m0 0L9 7" />
</svg>
}
rightIcon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z" />
</svg>
}
>
Travel
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton>
More
<svg className="h-4 w-4 ml-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z" />
</svg>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarSection>
</SidebarContent>
<SidebarFooter>
<SidebarTrigger />
</SidebarFooter>
</Sidebar>
)
}JavaScript:
jsx
import {
Sidebar,
SidebarHeader,
SidebarBrand,
SidebarContent,
SidebarSection,
SidebarMenu,
SidebarMenuItem,
SidebarMenuButton,
SidebarMenuSub,
SidebarMenuSubItem,
SidebarMenuSeparator,
SidebarFooter,
SidebarTrigger,
} from "@/components/ui/sidebar"
import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from "@/components/ui/select"
function MyComponent() {
return (
<Sidebar>
<SidebarHeader>
<SidebarBrand
icon={
<svg className="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
}
title="Acme Inc"
subtitle="Enterprise"
>
<button className="ml-auto">
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 15l7-7 7 7" />
</svg>
</button>
</SidebarBrand>
</SidebarHeader>
<SidebarContent>
<SidebarSection label="Platform">
<Select value="playground" onValueChange={(value) => console.log(value)}>
<SelectTrigger className="w-full mb-2">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="playground">Playground</SelectItem>
<SelectItem value="production">Production</SelectItem>
</SelectContent>
</Select>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton>History</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton>Starred</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton>Settings</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarSection>
<SidebarSection>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton
icon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2" />
</svg>
}
rightIcon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
}
>
Models
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton
icon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" />
</svg>
}
rightIcon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
}
>
Documentation
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton
icon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
}
rightIcon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
}
>
Settings
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarSection>
<SidebarSection label="Projects">
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton
icon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M7 20l4-16m2 16l4-16M6 9h14M4 15h14" />
</svg>
}
rightIcon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z" />
</svg>
}
>
Design Engineering
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton
icon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
}
rightIcon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z" />
</svg>
}
>
Sales & Marketing
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton
icon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4m0 0L9 7" />
</svg>
}
rightIcon={
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z" />
</svg>
}
>
Travel
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton>
More
<svg className="h-4 w-4 ml-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z" />
</svg>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarSection>
</SidebarContent>
<SidebarFooter>
<SidebarTrigger />
</SidebarFooter>
</Sidebar>
)
}Make sure you also have the lib/utils.ts file with the cn helper function.
Examples
Default Sidebar
Main content area