侧边栏
可组合、可主题化和可自定义的侧边栏组件。

可折叠为图标的侧边栏。
¥A sidebar that collapses to icons.
侧边栏是最复杂的组件之一。它们是任何应用的核心,通常包含许多活动部件。
¥Sidebars are one of the most complex components to build. They are central to any application and often contain a lot of moving parts.
我不喜欢构建侧边栏。所以我构建了 30 多个。各种配置。然后我将核心组件提取到 sidebar.tsx 中。
¥I don't like building sidebars. So I built 30+ of them. All kinds of
configurations. Then I extracted the core components into sidebar.tsx.
我们现在有一个坚实的基础可以在此基础上构建。可组合。可主题化。可定制。
¥We now have a solid foundation to build on top of. Composable. Themeable. Customizable.
浏览块库。
安装
¥Installation
Run the following command to install sidebar.tsx
pnpm dlx shadcn@latest add sidebar
Add the following colors to your CSS file
上面的命令应该会为你安装颜色。如果没有,请将以下内容复制并粘贴到你的 CSS 文件中。
¥The command above should install the colors for you. If not, copy and paste the following in your CSS file.
我们将在 主题部分 中稍后介绍颜色。
¥We'll go over the colors later in the theming section.
@layer base {
:root {
--sidebar-background: 0 0% 98%;
--sidebar-foreground: 240 5.3% 26.1%;
--sidebar-primary: 240 5.9% 10%;
--sidebar-primary-foreground: 0 0% 98%;
--sidebar-accent: 240 4.8% 95.9%;
--sidebar-accent-foreground: 240 5.9% 10%;
--sidebar-border: 220 13% 91%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
.dark {
--sidebar-background: 240 5.9% 10%;
--sidebar-foreground: 240 4.8% 95.9%;
--sidebar-primary: 224.3 76.3% 48%;
--sidebar-primary-foreground: 0 0% 100%;
--sidebar-accent: 240 3.7% 15.9%;
--sidebar-accent-foreground: 240 4.8% 95.9%;
--sidebar-border: 240 3.7% 15.9%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
}结构
¥Structure
Sidebar 组件由以下部分组成:
¥A Sidebar component is composed of the following parts:
-
SidebarProvider- 处理可折叠状态。¥
SidebarProvider- Handles collapsible state. -
Sidebar- 侧边栏容器。¥
Sidebar- The sidebar container. -
SidebarHeader和SidebarFooter- 粘贴在侧边栏的顶部和底部。¥
SidebarHeaderandSidebarFooter- Sticky at the top and bottom of the sidebar. -
SidebarContent- 可滚动内容。¥
SidebarContent- Scrollable content. -
SidebarGroup-SidebarContent内的部分。¥
SidebarGroup- Section within theSidebarContent. -
SidebarTrigger-Sidebar的触发器。¥
SidebarTrigger- Trigger for theSidebar.
用法
¥Usage
import { SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar"
import { AppSidebar } from "@/components/app-sidebar"
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<SidebarProvider>
<AppSidebar />
<main>
<SidebarTrigger />
{children}
</main>
</SidebarProvider>
)
}import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarGroup,
SidebarHeader,
} from "@/components/ui/sidebar"
export function AppSidebar() {
return (
<Sidebar>
<SidebarHeader />
<SidebarContent>
<SidebarGroup />
<SidebarGroup />
</SidebarContent>
<SidebarFooter />
</Sidebar>
)
}你的第一个侧边栏
¥Your First Sidebar
让我们从最基本的侧边栏开始。带有菜单的可折叠侧边栏。
¥Let's start with the most basic sidebar. A collapsible sidebar with a menu.
在应用的根目录下添加 SidebarProvider 和 SidebarTrigger。
¥Add a SidebarProvider and SidebarTrigger at the root of your application.
import { SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar"
import { AppSidebar } from "@/components/app-sidebar"
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<SidebarProvider>
<AppSidebar />
<main>
<SidebarTrigger />
{children}
</main>
</SidebarProvider>
)
}Create a new sidebar component at components/app-sidebar.tsx.
import { Sidebar, SidebarContent } from "@/components/ui/sidebar"
export function AppSidebar() {
return (
<Sidebar>
<SidebarContent />
</Sidebar>
)
}Now, let's add a SidebarMenu to the sidebar.
我们将在 SidebarGroup 中使用 SidebarMenu 组件。
¥We'll use the SidebarMenu component in a SidebarGroup.
import { Calendar, Home, Inbox, Search, Settings } from "lucide-react"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
} from "@/components/ui/sidebar"
// Menu items.
const items = [
{
title: "Home",
url: "#",
icon: Home,
},
{
title: "Inbox",
url: "#",
icon: Inbox,
},
{
title: "Calendar",
url: "#",
icon: Calendar,
},
{
title: "Search",
url: "#",
icon: Search,
},
{
title: "Settings",
url: "#",
icon: Settings,
},
]
export function AppSidebar() {
return (
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Application</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{items.map((item) => (
<SidebarMenuItem key={item.title}>
<SidebarMenuButton asChild>
<a href={item.url}>
<item.icon />
<span>{item.title}</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
)
}You've created your first sidebar.

你的第一个侧边栏。
¥Your first sidebar.
组件
¥Components
sidebar.tsx 中的组件是可组合的,即你可以通过将提供的组件放在一起来构建侧边栏。它们还可以与其他 shadcn/ui 组件(如 DropdownMenu、Collapsible 或 Dialog 等)很好地组合。
¥The components in sidebar.tsx are built to be composable i.e you build your sidebar by putting the provided components together. They also compose well with other shadcn/ui components such as DropdownMenu, Collapsible or Dialog etc.
如果你需要更改 sidebar.tsx 中的代码,我们鼓励你这样做。代码是你的。使用 sidebar.tsx 作为起点并构建你自己的。
¥If you need to change the code in sidebar.tsx, you are encouraged to do so. The code is yours. Use sidebar.tsx as a starting point and build your own.
在接下来的部分中,我们将介绍每个组件及其使用方法。
¥In the next sections, we'll go over each component and how to use them.
SidebarProvider
SidebarProvider 组件用于为 Sidebar 组件提供侧边栏上下文。你应该始终将你的应用封装在 SidebarProvider 组件中。
¥The SidebarProvider component is used to provide the sidebar context to the Sidebar component. You should always wrap your application in a SidebarProvider component.
属性
¥Props
| 名称 | 类型 | 描述 |
|---|---|---|
defaultOpen | boolean | 侧边栏的默认打开状态。 |
open | boolean | 侧边栏的打开状态(受控)。 |
onOpenChange | (open: boolean) => void | 设置侧边栏的打开状态(受控)。 |
宽度
¥Width
如果你的应用中只有一个侧边栏,则可以使用 sidebar.tsx 中的 SIDEBAR_WIDTH 和 SIDEBAR_WIDTH_MOBILE 变量来设置侧边栏的宽度。
¥If you have a single sidebar in your application, you can use the SIDEBAR_WIDTH and SIDEBAR_WIDTH_MOBILE variables in sidebar.tsx to set the width of the sidebar.
const SIDEBAR_WIDTH = "16rem"
const SIDEBAR_WIDTH_MOBILE = "18rem"对于应用中的多个侧边栏,你可以使用 style prop 来设置侧边栏的宽度。
¥For multiple sidebars in your application, you can use the style prop to set the width of the sidebar.
要设置侧边栏的宽度,你可以在 style 属性中使用 --sidebar-width 和 --sidebar-width-mobile CSS 变量。
¥To set the width of the sidebar, you can use the --sidebar-width and --sidebar-width-mobile CSS variables in the style prop.
<SidebarProvider
style={{
"--sidebar-width": "20rem",
"--sidebar-width-mobile": "20rem",
}}
>
<Sidebar />
</SidebarProvider>这将处理侧边栏的宽度以及布局间距。
¥This will handle the width of the sidebar but also the layout spacing.
键盘快捷方式
¥Keyboard Shortcut
SIDEBAR_KEYBOARD_SHORTCUT 变量用于设置用于打开和关闭侧边栏的键盘快捷键。
¥The SIDEBAR_KEYBOARD_SHORTCUT variable is used to set the keyboard shortcut used to open and close the sidebar.
要触发侧边栏,请在 Mac 上使用 cmd+b 键盘快捷键,在 Windows 上使用 ctrl+b。
¥To trigger the sidebar, you use the cmd+b keyboard shortcut on Mac and ctrl+b on Windows.
你可以通过更新 SIDEBAR_KEYBOARD_SHORTCUT 变量来更改键盘快捷键。
¥You can change the keyboard shortcut by updating the SIDEBAR_KEYBOARD_SHORTCUT variable.
const SIDEBAR_KEYBOARD_SHORTCUT = "b"持久状态
¥Persisted State
SidebarProvider 支持在页面重新加载和服务器端渲染时保持侧边栏状态。它使用 cookie 来存储侧边栏的当前状态。当侧边栏状态发生变化时,将使用当前打开/关闭状态设置一个名为 sidebar_state 的默认 cookie。然后在后续页面加载时读取此 cookie 以恢复侧边栏状态。
¥The SidebarProvider supports persisting the sidebar state across page reloads and server-side rendering. It uses cookies to store the current state of the sidebar. When the sidebar state changes, a default cookie named sidebar_state is set with the current open/closed state. This cookie is then read on subsequent page loads to restore the sidebar state.
要在 Next.js 中保留侧边栏状态,请在 app/layout.tsx 中像这样设置你的 SidebarProvider:
¥To persist sidebar state in Next.js, set up your SidebarProvider in app/layout.tsx like this:
import { cookies } from "next/headers"
import { SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar"
import { AppSidebar } from "@/components/app-sidebar"
export async function Layout({ children }: { children: React.ReactNode }) {
const cookieStore = await cookies()
const defaultOpen = cookieStore.get("sidebar_state")?.value === "true"
return (
<SidebarProvider defaultOpen={defaultOpen}>
<AppSidebar />
<main>
<SidebarTrigger />
{children}
</main>
</SidebarProvider>
)
}你可以通过更新 sidebar.tsx 中的 SIDEBAR_COOKIE_NAME 变量来更改 cookie 的名称。
¥You can change the name of the cookie by updating the SIDEBAR_COOKIE_NAME variable in sidebar.tsx.
const SIDEBAR_COOKIE_NAME = "sidebar_state"侧边栏
¥Sidebar
用于渲染可折叠侧边栏的主要 Sidebar 组件。
¥The main Sidebar component used to render a collapsible sidebar.
import { Sidebar } from "@/components/ui/sidebar"
export function AppSidebar() {
return <Sidebar />
}属性
¥Props
| 属性 | 类型 | 描述 |
|---|---|---|
side | left 或 right | 侧边栏的侧面。 |
variant | sidebar、floating 或 inset | 侧边栏的变体。 |
collapsible | offcanvas、icon 或 none | 侧边栏的可折叠状态。 |
side
使用 side 属性更改侧边栏的侧面。
¥Use the side prop to change the side of the sidebar.
可用选项为 left 和 right。
¥Available options are left and right.
import { Sidebar } from "@/components/ui/sidebar"
export function AppSidebar() {
return <Sidebar side="left | right" />
}variant
使用 variant 属性更改侧边栏的变体。
¥Use the variant prop to change the variant of the sidebar.
可用选项为 sidebar、floating 和 inset。
¥Available options are sidebar, floating and inset.
import { Sidebar } from "@/components/ui/sidebar"
export function AppSidebar() {
return <Sidebar variant="sidebar | floating | inset" />
}注意:如果你使用 inset 变体,请记住将你的主要内容封装在 SidebarInset 组件中。
¥Note: If you use the inset variant, remember to wrap your main content
in a SidebarInset component.
<SidebarProvider>
<Sidebar variant="inset" />
<SidebarInset>
<main>{children}</main>
</SidebarInset>
</SidebarProvider>collapsible
使用 collapsible 属性使侧边栏可折叠。
¥Use the collapsible prop to make the sidebar collapsible.
可用选项为 offcanvas、icon 和 none。
¥Available options are offcanvas, icon and none.
import { Sidebar } from "@/components/ui/sidebar"
export function AppSidebar() {
return <Sidebar collapsible="offcanvas | icon | none" />
}| Prop | 描述 |
|---|---|
offcanvas | 可从左侧或右侧滑入的可折叠侧边栏。 |
icon | 可折叠为图标的侧边栏。 |
none | 不可折叠侧边栏。 |
useSidebar
useSidebar 钩子用于控制侧边栏。
¥The useSidebar hook is used to control the sidebar.
import { useSidebar } from "@/components/ui/sidebar"
export function AppSidebar() {
const {
state,
open,
setOpen,
openMobile,
setOpenMobile,
isMobile,
toggleSidebar,
} = useSidebar()
}| 属性 | 类型 | 描述 |
|---|---|---|
state | expanded 或 collapsed | 侧边栏的当前状态。 |
open | boolean | 侧边栏是否打开。 |
setOpen | (open: boolean) => void | 设置侧边栏的打开状态。 |
openMobile | boolean | 侧边栏是否在移动设备上打开。 |
setOpenMobile | (open: boolean) => void | 设置移动设备上侧边栏的打开状态。 |
isMobile | boolean | 侧边栏是否在移动设备上。 |
toggleSidebar | () => void | 切换侧边栏。桌面和移动设备。 |
SidebarHeader
使用 SidebarHeader 组件向侧边栏添加粘性标题。
¥Use the SidebarHeader component to add a sticky header to the sidebar.
以下示例将 <DropdownMenu> 添加到 SidebarHeader。
¥The following example adds a <DropdownMenu> to the SidebarHeader.

带有下拉菜单的侧边栏标题。
¥A sidebar header with a dropdown menu.
<Sidebar>
<SidebarHeader>
<SidebarMenu>
<SidebarMenuItem>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<SidebarMenuButton>
Select Workspace
<ChevronDown className="ml-auto" />
</SidebarMenuButton>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-[--radix-popper-anchor-width]">
<DropdownMenuItem>
<span>Acme Inc</span>
</DropdownMenuItem>
<DropdownMenuItem>
<span>Acme Corp.</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
</SidebarMenu>
</SidebarHeader>
</Sidebar>SidebarFooter
使用 SidebarFooter 组件向侧边栏添加粘性页脚。
¥Use the SidebarFooter component to add a sticky footer to the sidebar.
以下示例将 <DropdownMenu> 添加到 SidebarFooter。
¥The following example adds a <DropdownMenu> to the SidebarFooter.

带有下拉菜单的侧边栏页脚。
¥A sidebar footer with a dropdown menu.
export function AppSidebar() {
return (
<SidebarProvider>
<Sidebar>
<SidebarHeader />
<SidebarContent />
<SidebarFooter>
<SidebarMenu>
<SidebarMenuItem>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<SidebarMenuButton>
<User2 /> Username
<ChevronUp className="ml-auto" />
</SidebarMenuButton>
</DropdownMenuTrigger>
<DropdownMenuContent
side="top"
className="w-[--radix-popper-anchor-width]"
>
<DropdownMenuItem>
<span>Account</span>
</DropdownMenuItem>
<DropdownMenuItem>
<span>Billing</span>
</DropdownMenuItem>
<DropdownMenuItem>
<span>Sign out</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
</SidebarMenu>
</SidebarFooter>
</Sidebar>
</SidebarProvider>
)
}SidebarContent
SidebarContent 组件用于封装侧边栏的内容。这是你添加 SidebarGroup 组件的地方。它是可滚动的。
¥The SidebarContent component is used to wrap the content of the sidebar. This is where you add your SidebarGroup components. It is scrollable.
import { Sidebar, SidebarContent } from "@/components/ui/sidebar"
export function AppSidebar() {
return (
<Sidebar>
<SidebarContent>
<SidebarGroup />
<SidebarGroup />
</SidebarContent>
</Sidebar>
)
}SidebarGroup
使用 SidebarGroup 组件在侧边栏内创建一个部分。
¥Use the SidebarGroup component to create a section within the sidebar.
SidebarGroup 有 SidebarGroupLabel、SidebarGroupContent 和可选的 SidebarGroupAction。
¥A SidebarGroup has a SidebarGroupLabel, a SidebarGroupContent and an optional SidebarGroupAction.

侧边栏组。
¥A sidebar group.
import { Sidebar, SidebarContent, SidebarGroup } from "@/components/ui/sidebar"
export function AppSidebar() {
return (
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Application</SidebarGroupLabel>
<SidebarGroupAction>
<Plus /> <span className="sr-only">Add Project</span>
</SidebarGroupAction>
<SidebarGroupContent></SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
)
}可折叠侧边栏组
¥Collapsible SidebarGroup
要使 SidebarGroup 可折叠,请将其封装在 Collapsible 中。
¥To make a SidebarGroup collapsible, wrap it in a Collapsible.

可折叠侧边栏组。
¥A collapsible sidebar group.
export function AppSidebar() {
return (
<Collapsible defaultOpen className="group/collapsible">
<SidebarGroup>
<SidebarGroupLabel asChild>
<CollapsibleTrigger>
Help
<ChevronDown className="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-180" />
</CollapsibleTrigger>
</SidebarGroupLabel>
<CollapsibleContent>
<SidebarGroupContent />
</CollapsibleContent>
</SidebarGroup>
</Collapsible>
)
}注意:我们将 CollapsibleTrigger 封装在 SidebarGroupLabel 中以渲染按钮。
¥Note: We wrap the CollapsibleTrigger in a SidebarGroupLabel to render
a button.
SidebarGroupAction
使用 SidebarGroupAction 组件向 SidebarGroup 添加操作按钮。
¥Use the SidebarGroupAction component to add an action button to the SidebarGroup.
export function AppSidebar() {
return (
<SidebarGroup>
<SidebarGroupLabel asChild>Projects</SidebarGroupLabel>
<SidebarGroupAction title="Add Project">
<Plus /> <span className="sr-only">Add Project</span>
</SidebarGroupAction>
<SidebarGroupContent />
</SidebarGroup>
)
}
带有操作按钮的侧边栏组。
¥A sidebar group with an action button.
SidebarMenu
SidebarMenu 组件用于在 SidebarGroup 中构建菜单。
¥The SidebarMenu component is used for building a menu within a SidebarGroup.
SidebarMenu 组件由 SidebarMenuItem、SidebarMenuButton、<SidebarMenuAction /> 和 <SidebarMenuSub /> 组件组成。
¥A SidebarMenu component is composed of SidebarMenuItem, SidebarMenuButton, <SidebarMenuAction /> and <SidebarMenuSub /> components.
以下是 SidebarMenu 组件渲染项目列表的示例。
¥Here's an example of a SidebarMenu component rendering a list of projects.

带有项目列表的侧边栏菜单。
¥A sidebar menu with a list of projects.
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Projects</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{projects.map((project) => (
<SidebarMenuItem key={project.name}>
<SidebarMenuButton asChild>
<a href={project.url}>
<project.icon />
<span>{project.name}</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>SidebarMenuButton
SidebarMenuButton 组件用于在 SidebarMenuItem 中渲染菜单按钮。
¥The SidebarMenuButton component is used to render a menu button within a SidebarMenuItem.
链接或锚点
¥Link or Anchor
默认情况下,SidebarMenuButton 渲染一个按钮,但你可以使用 asChild prop 来渲染不同的组件,例如 Link 或 a 标签。
¥By default, the SidebarMenuButton renders a button but you can use the asChild prop to render a different component such as a Link or an a tag.
<SidebarMenuButton asChild>
<a href="#">Home</a>
</SidebarMenuButton>图标和标签
¥Icon and Label
你可以在按钮内渲染图标和截断标签。请记住将标签封装在 <span> 中。
¥You can render an icon and a truncated label inside the button. Remember to wrap the label in a <span>.
<SidebarMenuButton asChild>
<a href="#">
<Home />
<span>Home</span>
</a>
</SidebarMenuButton>isActive
使用 isActive 属性将菜单项标记为活动。
¥Use the isActive prop to mark a menu item as active.
<SidebarMenuButton asChild isActive>
<a href="#">Home</a>
</SidebarMenuButton>SidebarMenuAction
SidebarMenuAction 组件用于在 SidebarMenuItem 中渲染菜单操作。
¥The SidebarMenuAction component is used to render a menu action within a SidebarMenuItem.
此按钮独立于 SidebarMenuButton 工作,即你可以将 <SidebarMenuButton /> 作为可点击链接,将 <SidebarMenuAction /> 作为按钮。
¥This button works independently of the SidebarMenuButton i.e you can have the <SidebarMenuButton /> as a clickable link and the <SidebarMenuAction /> as a button.
<SidebarMenuItem>
<SidebarMenuButton asChild>
<a href="#">
<Home />
<span>Home</span>
</a>
</SidebarMenuButton>
<SidebarMenuAction>
<Plus /> <span className="sr-only">Add Project</span>
</SidebarMenuAction>
</SidebarMenuItem>DropdownMenu
以下是 SidebarMenuAction 组件渲染 DropdownMenu 的示例。
¥Here's an example of a SidebarMenuAction component rendering a DropdownMenu.

带有下拉菜单的侧边栏菜单操作。
¥A sidebar menu action with a dropdown menu.
<SidebarMenuItem>
<SidebarMenuButton asChild>
<a href="#">
<Home />
<span>Home</span>
</a>
</SidebarMenuButton>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<SidebarMenuAction>
<MoreHorizontal />
</SidebarMenuAction>
</DropdownMenuTrigger>
<DropdownMenuContent side="right" align="start">
<DropdownMenuItem>
<span>Edit Project</span>
</DropdownMenuItem>
<DropdownMenuItem>
<span>Delete Project</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>SidebarMenuSub
SidebarMenuSub 组件用于在 SidebarMenu 中渲染子菜单。
¥The SidebarMenuSub component is used to render a submenu within a SidebarMenu.
使用 <SidebarMenuSubItem /> 和 <SidebarMenuSubButton /> 渲染子菜单项。
¥Use <SidebarMenuSubItem /> and <SidebarMenuSubButton /> to render a submenu item.

带有子菜单的侧边栏菜单。
¥A sidebar menu with a submenu.
<SidebarMenuItem>
<SidebarMenuButton />
<SidebarMenuSub>
<SidebarMenuSubItem>
<SidebarMenuSubButton />
</SidebarMenuSubItem>
<SidebarMenuSubItem>
<SidebarMenuSubButton />
</SidebarMenuSubItem>
</SidebarMenuSub>
</SidebarMenuItem>可折叠侧边栏菜单
¥Collapsible SidebarMenu
要使 SidebarMenu 组件可折叠,请将其和 SidebarMenuSub 组件封装在 Collapsible 中。
¥To make a SidebarMenu component collapsible, wrap it and the SidebarMenuSub components in a Collapsible.

可折叠侧边栏菜单。
¥A collapsible sidebar menu.
<SidebarMenu>
<Collapsible defaultOpen className="group/collapsible">
<SidebarMenuItem>
<CollapsibleTrigger asChild>
<SidebarMenuButton />
</CollapsibleTrigger>
<CollapsibleContent>
<SidebarMenuSub>
<SidebarMenuSubItem />
</SidebarMenuSub>
</CollapsibleContent>
</SidebarMenuItem>
</Collapsible>
</SidebarMenu>SidebarMenuBadge
SidebarMenuBadge 组件用于在 SidebarMenuItem 中渲染徽章。
¥The SidebarMenuBadge component is used to render a badge within a SidebarMenuItem.

带有徽章的侧边栏菜单。
¥A sidebar menu with a badge.
<SidebarMenuItem>
<SidebarMenuButton />
<SidebarMenuBadge>24</SidebarMenuBadge>
</SidebarMenuItem>SidebarMenuSkeleton
SidebarMenuSkeleton 组件用于为 SidebarMenu 渲染骨架。你可以使用它来在使用 React Server Components、SWR 或 react-query 时显示加载状态。
¥The SidebarMenuSkeleton component is used to render a skeleton for a SidebarMenu. You can use this to show a loading state when using React Server Components, SWR or react-query.
function NavProjectsSkeleton() {
return (
<SidebarMenu>
{Array.from({ length: 5 }).map((_, index) => (
<SidebarMenuItem key={index}>
<SidebarMenuSkeleton />
</SidebarMenuItem>
))}
</SidebarMenu>
)
}SidebarSeparator
SidebarSeparator 组件用于在 Sidebar 中渲染分隔符。
¥The SidebarSeparator component is used to render a separator within a Sidebar.
<Sidebar>
<SidebarHeader />
<SidebarSeparator />
<SidebarContent>
<SidebarGroup />
<SidebarSeparator />
<SidebarGroup />
</SidebarContent>
</Sidebar>SidebarTrigger
使用 SidebarTrigger 组件渲染切换侧边栏的按钮。
¥Use the SidebarTrigger component to render a button that toggles the sidebar.
SidebarTrigger 组件必须在 SidebarProvider 中使用。
¥The SidebarTrigger component must be used within a SidebarProvider.
<SidebarProvider>
<Sidebar />
<main>
<SidebarTrigger />
</main>
</SidebarProvider>自定义触发器
¥Custom Trigger
要创建自定义触发器,你可以使用 useSidebar 钩子。
¥To create a custom trigger, you can use the useSidebar hook.
import { useSidebar } from "@/components/ui/sidebar"
export function CustomTrigger() {
const { toggleSidebar } = useSidebar()
return <button onClick={toggleSidebar}>Toggle Sidebar</button>
}SidebarRail
SidebarRail 组件用于在 Sidebar 中渲染轨道。此轨道可用于切换侧边栏。
¥The SidebarRail component is used to render a rail within a Sidebar. This rail can be used to toggle the sidebar.
<Sidebar>
<SidebarHeader />
<SidebarContent>
<SidebarGroup />
</SidebarContent>
<SidebarFooter />
<SidebarRail />
</Sidebar>数据获取
¥Data Fetching
React 服务器组件
¥React Server Components
以下是使用 React Server Components 渲染项目列表的 SidebarMenu 组件的示例。
¥Here's an example of a SidebarMenu component rendering a list of projects using React Server Components.

使用 React Server Components 的侧边栏菜单。
¥A sidebar menu using React Server Components.
function NavProjectsSkeleton() {
return (
<SidebarMenu>
{Array.from({ length: 5 }).map((_, index) => (
<SidebarMenuItem key={index}>
<SidebarMenuSkeleton showIcon />
</SidebarMenuItem>
))}
</SidebarMenu>
)
}async function NavProjects() {
const projects = await fetchProjects()
return (
<SidebarMenu>
{projects.map((project) => (
<SidebarMenuItem key={project.name}>
<SidebarMenuButton asChild>
<a href={project.url}>
<project.icon />
<span>{project.name}</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
))}
</SidebarMenu>
)
}function AppSidebar() {
return (
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Projects</SidebarGroupLabel>
<SidebarGroupContent>
<React.Suspense fallback={<NavProjectsSkeleton />}>
<NavProjects />
</React.Suspense>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
)
}SWR 和 React 查询
¥SWR and React Query
你可以使用相同的方法对 SWR 或 react-query 进行操作。
¥You can use the same approach with SWR or react-query.
function NavProjects() {
const { data, isLoading } = useSWR("/api/projects", fetcher)
if (isLoading) {
return (
<SidebarMenu>
{Array.from({ length: 5 }).map((_, index) => (
<SidebarMenuItem key={index}>
<SidebarMenuSkeleton showIcon />
</SidebarMenuItem>
))}
</SidebarMenu>
)
}
if (!data) {
return ...
}
return (
<SidebarMenu>
{data.map((project) => (
<SidebarMenuItem key={project.name}>
<SidebarMenuButton asChild>
<a href={project.url}>
<project.icon />
<span>{project.name}</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
))}
</SidebarMenu>
)
}function NavProjects() {
const { data, isLoading } = useQuery()
if (isLoading) {
return (
<SidebarMenu>
{Array.from({ length: 5 }).map((_, index) => (
<SidebarMenuItem key={index}>
<SidebarMenuSkeleton showIcon />
</SidebarMenuItem>
))}
</SidebarMenu>
)
}
if (!data) {
return ...
}
return (
<SidebarMenu>
{data.map((project) => (
<SidebarMenuItem key={project.name}>
<SidebarMenuButton asChild>
<a href={project.url}>
<project.icon />
<span>{project.name}</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
))}
</SidebarMenu>
)
}受控侧边栏
¥Controlled Sidebar
使用 open 和 onOpenChange 属性来控制侧边栏。
¥Use the open and onOpenChange props to control the sidebar.

受控侧边栏。
¥A controlled sidebar.
export function AppSidebar() {
const [open, setOpen] = React.useState(false)
return (
<SidebarProvider open={open} onOpenChange={setOpen}>
<Sidebar />
</SidebarProvider>
)
}主题
¥Theming
我们使用以下 CSS 变量来设置侧边栏的主题。
¥We use the following CSS variables to theme the sidebar.
@layer base {
:root {
--sidebar-background: 0 0% 98%;
--sidebar-foreground: 240 5.3% 26.1%;
--sidebar-primary: 240 5.9% 10%;
--sidebar-primary-foreground: 0 0% 98%;
--sidebar-accent: 240 4.8% 95.9%;
--sidebar-accent-foreground: 240 5.9% 10%;
--sidebar-border: 220 13% 91%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
.dark {
--sidebar-background: 240 5.9% 10%;
--sidebar-foreground: 240 4.8% 95.9%;
--sidebar-primary: 0 0% 98%;
--sidebar-primary-foreground: 240 5.9% 10%;
--sidebar-accent: 240 3.7% 15.9%;
--sidebar-accent-foreground: 240 4.8% 95.9%;
--sidebar-border: 240 3.7% 15.9%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
}我们有意为侧边栏和应用的其余部分使用不同的变量,以便轻松拥有与应用其余部分不同样式的侧边栏。想象一下主应用中带有深色阴影的侧边栏。
¥We intentionally use different variables for the sidebar and the rest of the application to make it easy to have a sidebar that is styled differently from the rest of the application. Think a sidebar with a darker shade from the main application.
样式
¥Styling
以下是根据不同状态设置侧边栏样式的一些技巧。
¥Here are some tips for styling the sidebar based on different states.
-
根据侧边栏可折叠状态设置元素样式。当侧边栏处于
icon模式时,以下内容将隐藏SidebarGroup。¥Styling an element based on the sidebar collapsible state. The following will hide the
SidebarGroupwhen the sidebar is iniconmode.
<Sidebar collapsible="icon">
<SidebarContent>
<SidebarGroup className="group-data-[collapsible=icon]:hidden" />
</SidebarContent>
</Sidebar>-
根据菜单按钮活动状态设置菜单操作的样式。以下内容将强制菜单操作在菜单按钮处于活动状态时可见。
¥Styling a menu action based on the menu button active state. The following will force the menu action to be visible when the menu button is active.
<SidebarMenuItem>
<SidebarMenuButton />
<SidebarMenuAction className="peer-data-[active=true]/menu-button:opacity-100" />
</SidebarMenuItem>你可以在此 Twitter 线程 中找到有关使用状态进行样式设置的更多提示。
¥You can find more tips on using states for styling in this Twitter thread.
更新日志
¥Changelog
2024-10-30 setOpen 中的 Cookie 处理
¥2024-10-30 Cookie handling in setOpen
-
#5593 - 改进了
<SidebarProvider>中的 setOpen 回调逻辑。¥#5593 - Improved setOpen callback logic in
<SidebarProvider>.
更新 <SidebarProvider> 中的 setOpen 回调如下:
¥Update the setOpen callback in <SidebarProvider> as follows:
const setOpen = React.useCallback(
(value: boolean | ((value: boolean) => boolean)) => {
const openState = typeof value === "function" ? value(open) : value
if (setOpenProp) {
setOpenProp(openState)
} else {
_setOpen(openState)
}
// This sets the cookie to keep the sidebar state.
document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`
},
[setOpenProp, open]
)2024-10-21 修复 text-sidebar-foreground
¥2024-10-21 Fixed text-sidebar-foreground
-
#5491 - 将
text-sidebar-foreground从<SidebarProvider>移动到<Sidebar>组件。¥#5491 - Moved
text-sidebar-foregroundfrom<SidebarProvider>to<Sidebar>component.
2024-10-20 useSidebar 钩子中的拼写错误。
¥2024-10-20 Typo in useSidebar hook.
修复了 useSidebar 钩子中的拼写错误。
¥Fixed typo in useSidebar hook.
- throw new Error("useSidebar must be used within a Sidebar.")
+ throw new Error("useSidebar must be used within a SidebarProvider.")












