Chuyển tới nội dung
Component

Sidebar

App shell navigation beside the page: a column of sections and items from the start edge, with a trigger that collapses it to a rail of icons (each named by a Tooltip) or hides it. Below the md breakpoint the same content opens in a Sheet.

Xem trước

Props

  • collapsed
  • defaultCollapsed
  • collapsible
  • side
  • label
  • active
  • asChild
  • href
  • count
  • disabled
import { IconChartLine, IconHome, IconSettings, IconUser } from "@tabler/icons-react"
import { Sidebar, SidebarContent, SidebarItem, SidebarProvider, SidebarSection, SidebarTrigger } from "@/components/ui/sidebar"

<SidebarProvider>
  <SidebarTrigger label="Toggle navigation" />
  <Sidebar>
    <SidebarContent>
      <SidebarSection label="Workspace">
        <SidebarItem href="#" leadingIcon={<IconHome size={20} weight="regular" />}>Overview</SidebarItem>
        <SidebarItem href="#" leadingIcon={<IconChartLine size={20} weight="regular" />}>Reports</SidebarItem>
        <SidebarItem href="#" leadingIcon={<IconSettings size={20} weight="regular" />}>Settings</SidebarItem>
      </SidebarSection>
      <SidebarSection label="Account">
        <SidebarItem href="#" leadingIcon={<IconUser size={20} weight="regular" />}>Profile</SidebarItem>
      </SidebarSection>
    </SidebarContent>
  </Sidebar>
</SidebarProvider>

Cách dùng

Khi nào dùng

  • Top-level navigation that stays beside the page across a whole product.
  • A long list of destinations grouped into named sections.

Khi nào không dùng

  • Switching between views of the same content. Use Tabs.
  • A short list of actions anchored to a control. Use DropdownMenu.
  • One optional section on a page. Use Accordion.

Biến thể

collapsible

Set on SidebarProvider. icon keeps a rail of icons with Tooltips when collapsed; offcanvas hides the sidebar on desktop entirely; none fixes it open.

import { IconChartLine, IconHome, IconSettings, IconUser } from "@tabler/icons-react"
import { Sidebar, SidebarContent, SidebarItem, SidebarProvider, SidebarSection, SidebarTrigger } from "@/components/ui/sidebar"

<SidebarProvider>
  <SidebarTrigger label="Toggle navigation" />
  <Sidebar>
    <SidebarContent>
      <SidebarSection label="Workspace">
        <SidebarItem href="#" leadingIcon={<IconHome size={20} weight="regular" />}>Overview</SidebarItem>
        <SidebarItem href="#" leadingIcon={<IconChartLine size={20} weight="regular" />}>Reports</SidebarItem>
        <SidebarItem href="#" leadingIcon={<IconSettings size={20} weight="regular" />}>Settings</SidebarItem>
      </SidebarSection>
      <SidebarSection label="Account">
        <SidebarItem href="#" leadingIcon={<IconUser size={20} weight="regular" />}>Profile</SidebarItem>
      </SidebarSection>
    </SidebarContent>
  </Sidebar>
</SidebarProvider>
<SidebarProvider collapsible="offcanvas">
  <SidebarTrigger label="Toggle navigation" />
  <Sidebar>
    <SidebarContent>
      <SidebarSection label="Workspace">
        <SidebarItem href="#" leadingIcon={<IconHome size={20} weight="regular" />}>Overview</SidebarItem>
        <SidebarItem href="#" leadingIcon={<IconChartLine size={20} weight="regular" />}>Reports</SidebarItem>
        <SidebarItem href="#" leadingIcon={<IconSettings size={20} weight="regular" />}>Settings</SidebarItem>
      </SidebarSection>
      <SidebarSection label="Account">
        <SidebarItem href="#" leadingIcon={<IconUser size={20} weight="regular" />}>Profile</SidebarItem>
      </SidebarSection>
    </SidebarContent>
  </Sidebar>
</SidebarProvider>
<SidebarProvider collapsible="none">
  <SidebarTrigger label="Toggle navigation" />
  <Sidebar>
    <SidebarContent>
      <SidebarSection label="Workspace">
        <SidebarItem href="#" leadingIcon={<IconHome size={20} weight="regular" />}>Overview</SidebarItem>
        <SidebarItem href="#" leadingIcon={<IconChartLine size={20} weight="regular" />}>Reports</SidebarItem>
        <SidebarItem href="#" leadingIcon={<IconSettings size={20} weight="regular" />}>Settings</SidebarItem>
      </SidebarSection>
      <SidebarSection label="Account">
        <SidebarItem href="#" leadingIcon={<IconUser size={20} weight="regular" />}>Profile</SidebarItem>
      </SidebarSection>
    </SidebarContent>
  </Sidebar>
</SidebarProvider>

side

Set on SidebarProvider. The edge the sidebar sits on; the Sheet opens from the same edge.

import { IconChartLine, IconHome, IconSettings, IconUser } from "@tabler/icons-react"
import { Sidebar, SidebarContent, SidebarItem, SidebarProvider, SidebarSection, SidebarTrigger } from "@/components/ui/sidebar"

<SidebarProvider>
  <SidebarTrigger label="Toggle navigation" />
  <Sidebar>
    <SidebarContent>
      <SidebarSection label="Workspace">
        <SidebarItem href="#" leadingIcon={<IconHome size={20} weight="regular" />}>Overview</SidebarItem>
        <SidebarItem href="#" leadingIcon={<IconChartLine size={20} weight="regular" />}>Reports</SidebarItem>
        <SidebarItem href="#" leadingIcon={<IconSettings size={20} weight="regular" />}>Settings</SidebarItem>
      </SidebarSection>
      <SidebarSection label="Account">
        <SidebarItem href="#" leadingIcon={<IconUser size={20} weight="regular" />}>Profile</SidebarItem>
      </SidebarSection>
    </SidebarContent>
  </Sidebar>
</SidebarProvider>
<SidebarProvider side="right">
  <SidebarTrigger label="Toggle navigation" />
  <Sidebar>
    <SidebarContent>
      <SidebarSection label="Workspace">
        <SidebarItem href="#" leadingIcon={<IconHome size={20} weight="regular" />}>Overview</SidebarItem>
        <SidebarItem href="#" leadingIcon={<IconChartLine size={20} weight="regular" />}>Reports</SidebarItem>
        <SidebarItem href="#" leadingIcon={<IconSettings size={20} weight="regular" />}>Settings</SidebarItem>
      </SidebarSection>
      <SidebarSection label="Account">
        <SidebarItem href="#" leadingIcon={<IconUser size={20} weight="regular" />}>Profile</SidebarItem>
      </SidebarSection>
    </SidebarContent>
  </Sidebar>
</SidebarProvider>

Ví dụ

App navigation

import { IconChartLine, IconHome, IconSettings } from "@tabler/icons-react"
import { Button } from "@/components/ui/button"
import { Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarItem, SidebarProvider, SidebarSection, SidebarTrigger } from "@/components/ui/sidebar"

<SidebarProvider>
  <SidebarTrigger label="Toggle navigation" />
  <Sidebar>
    <SidebarHeader>
      <p className="px-sm font-sans text-md font-medium text-text-primary">Acme</p>
    </SidebarHeader>
    <SidebarContent>
      <SidebarSection label="Workspace">
        <SidebarItem active leadingIcon={<IconHome size={20} />} href="#">Overview</SidebarItem>
        <SidebarItem leadingIcon={<IconChartLine size={20} />} href="#">Reports</SidebarItem>
      </SidebarSection>
      <SidebarSection label="Account">
        <SidebarItem leadingIcon={<IconSettings size={20} />} count={2} href="#">Settings</SidebarItem>
      </SidebarSection>
    </SidebarContent>
    <SidebarFooter>
      <Button variant="secondary" className="w-full">Invite people</Button>
    </SidebarFooter>
  </Sidebar>
</SidebarProvider>

Offcanvas with a trigger

collapsible offcanvas hides the sidebar on desktop; the trigger toggles it and opens the Sheet on a small screen.

import { IconLayoutGrid, IconLayoutGridFilled } from "@tabler/icons-react"
import { Sidebar, SidebarContent, SidebarItem, SidebarProvider, SidebarSection, SidebarTrigger } from "@/components/ui/sidebar"

<SidebarProvider collapsible="offcanvas" defaultCollapsed>
  <SidebarTrigger label="Toggle navigation" />
  <Sidebar>
    <SidebarContent>
      <SidebarSection label="Menu">
        <SidebarItem leadingIcon={<IconLayoutGrid size={20} />} leadingIconOn={<IconLayoutGridFilled size={20} />} active>Projects</SidebarItem>
      </SidebarSection>
    </SidebarContent>
  </Sidebar>
</SidebarProvider>

Nên và không nên

Nên

  • Give every section a label; it names the nav and orients the reader.
  • Mark exactly one item active, the page the user is on.
  • Keep the footer for identity and account actions, not navigation.

Không nên

  • Don't switch between views of the same content; use Tabs.
  • Don't put controls other than items inside the content; put them in the header or footer.
  • Don't nest a sidebar inside a sidebar.

Props

TênKiểuGiá trịMặc địnhMô tả
collapsedboolean--Set on SidebarProvider. The collapsed state, when you control it. Pair it with onCollapsedChange.
defaultCollapsedboolean-falseSet on SidebarProvider. Collapsed on first render.
onCollapsedChangefunction--Set on SidebarProvider. Called with the next collapsed state.
collapsibleenumicon | offcanvas | noneiconSet on SidebarProvider. icon keeps a rail of icons with Tooltips when collapsed; offcanvas hides the sidebar on desktop entirely; none fixes it open.
sideenumleft | rightleftSet on SidebarProvider. The edge the sidebar sits on; the Sheet opens from the same edge.
labelstring-MainSet on SidebarContent, the name of its navigation landmark; set on SidebarSection, the group's heading and name (hidden on the icon rail).
activeboolean-falseSet on SidebarItem. The page this item points to: aria-current="page", the muted accent fill with its strong text, and the fill icon weight.
asChildboolean-falseSet on SidebarItem. Renders the item as the single child element, typically a router link.
hrefstring--Set on SidebarItem. With it the item is a link; without it a button.
countnumber--Set on SidebarItem. A number after the label in a Badge; on the rail it moves into the Tooltip.
leadingIconnode--Set on SidebarItem. The Tabler icon before the label, 20px.
leadingIconOnnode--Set on SidebarItem. The filled-variant icon (Tabler *Filled, e.g. IconHomeFilled) shown on the active item instead of leadingIcon.
disabledboolean-falseSet on SidebarItem. The item cannot activate and dims, including links and slotted router links. Disabled items leave the tab order; on the icon rail their Tooltip still opens on hover.

Slot

TênBắt buộcMô tả
headerkhôngSidebarHeader above the scrolling content.
contentcóSidebarContent with one or more SidebarSection of SidebarItem.
footerkhôngSidebarFooter pinned at the end.

Cấu tạo

PhầnMô tả
rootSidebar: the desktop column, hidden below md, 256px wide, bordered only on the edge that faces the content. On the icon rail it is one square md item wide plus spacing-sm on each side (49px with the border on mouse, 53px on touch), and the header, content and footer pad with spacing-sm.
headerSidebarHeader: the block above the scrolling content, such as the workspace name.
contentSidebarContent: the scrolling group of sections, a nav named by its label (default "Main").
footerSidebarFooter: the block pinned at the end, with a Separator above it.
sectionSidebarSection: a group of related items, named by its label, with the items in a list.
labelThe section heading: 12px medium secondary text, hidden on the icon rail.
itemSidebarItem: one destination, a link with href, a button without one, or any element with asChild. At least the md control height, 14px medium text, a Badge after the label with count. On the icon rail an item with an icon is a square of the md control height.
currentThe active item, the page the user is on: the muted accent fill with its strong text.
currentIconThe active item's icon in the accent icon color, at the fill weight.
iconThe item's leading Tabler icon at 20px; leadingIconOn (the *Filled variant) replaces it on the active item.
triggerSidebarTrigger: one ghost icon button that collapses the sidebar on md and up and opens the Sheet below it, named by its label. With collapsible none it shows only below md.

Khả năng truy cập

Role: complementary

PhímHành động
TabMoves from item to item; items are links or buttons in the page order.
Enter, SpaceA button item activates; a link item follows its href.
EscapeCloses the Sheet the sidebar becomes on a small screen.
  • The root is an aside (complementary). SidebarContent inside it is the one navigation landmark, named by its label (default "Main").
  • Each SidebarSection is a group named by its visible label (aria-labelledby), or by aria-label on the icon rail where the label is hidden. Its items are a list.
  • The current page's item sets aria-current="page" and its icon switches to the fill weight; the state never relies on color alone.
  • On the rail an item with an icon moves its label into a Tooltip and an sr-only span. Items without icons keep visible text. A disabled item stays out of the tab order, and its Tooltip still opens on hover. Mobile sheets always show full labels.
  • The Sheet names itself with an sr-only title; the trigger button carries the same name in aria-label.
  • Sidebar parts must sit inside a SidebarProvider; without it they throw.

Cài đặt

npx shadcn add https://werewolf-ui.vercel.app/r/sidebar.json

Lệnh này thêm luôn styles/werewolf.css, bộ token mà mọi component dùng, và các component khác mà nó cần. Import file đó một lần trong CSS gốc, ngay sau @import "tailwindcss", với đường dẫn tính từ file CSS đó (từ app/globals.css là @import "../styles/werewolf.css").