Chuyển tới nội dung

Pro đang mở bán trước. Cài đặt mở từ tháng 1/2027. Xem Pro

Component

Sidebar

Điều hướng app shell cạnh trang: một cột section và item từ cạnh đầu, với trigger thu cột thành rail icon (mỗi icon được Tooltip đặt tên) hoặc giấu cột. Dưới breakpoint md, cùng nội dung đó mở trong một Sheet. Variant panel tùy chọn thêm header brand với nút gạt bên trong và các nhóm điều hướng lồng nhau. Khi đặt inset, cột nằm trên nền page và SidebarInset chứa nội dung trang trong một surface.

  • npm: 3 trực tiếp, 8 tổng
  • registry: 8 trực tiếp, 9 tổng

Xem trước

Không gian làm việc

Tổng quan

Nội dung của bạn xuất hiện ở đây.

Props

  • collapsed
  • defaultCollapsed
  • collapsible
  • side
  • label
  • active
  • asChild
  • href
  • count
  • disabled
  • variant
  • name
  • open
  • defaultOpen
  • value
  • defaultValue
  • inset
import { IconChartLine, IconHome, IconHomeFilled, IconSettings, IconUser } from "@tabler/icons-react"
import { Sidebar, SidebarBrand, SidebarContent, SidebarHeader, SidebarItem, SidebarProvider, SidebarSection } from "@/components/ui/sidebar"

<SidebarProvider side="left" collapsible="icon" defaultValue="overview">
  <div className="flex min-h-[32rem] w-full overflow-hidden rounded-container border border-border bg-background-surface">
    <Sidebar className="h-auto">
      <SidebarHeader className="border-b border-border">
        <SidebarBrand name="Không gian làm việc" />
      </SidebarHeader>
      <SidebarContent className="[&_ul]:gap-sm">
        <SidebarSection label="Không gian làm việc">
          <SidebarItem value="overview" leadingIcon={<IconHome size={20} />} leadingIconOn={<IconHomeFilled size={20} />}>Tổng quan</SidebarItem>
          <SidebarItem value="reports" leadingIcon={<IconChartLine size={20} />}>Báo cáo</SidebarItem>
          <SidebarItem value="settings" leadingIcon={<IconSettings size={20} />}>Cài đặt</SidebarItem>
        </SidebarSection>
        <SidebarSection label="Tài khoản">
          <SidebarItem value="profile" leadingIcon={<IconUser size={20} />}>Hồ sơ</SidebarItem>
        </SidebarSection>
      </SidebarContent>
    </Sidebar>
    <div className="flex min-w-0 flex-1 flex-col gap-lg p-lg">
      <div className="flex flex-col gap-xs">
        <p className="text-xs text-text-secondary">Không gian làm việc</p>
        <p className="text-heading-3 text-text-primary">Tổng quan</p>
      </div>
      <div className="flex flex-1 items-center justify-center rounded-container border border-border bg-background-surface p-md text-center text-sm text-text-secondary">Nội dung của bạn xuất hiện ở đây.</div>
    </div>
  </div>
</SidebarProvider>

Cách dùng

Khi nào dùng

  • Điều hướng cấp trên cùng, đứng cạnh trang xuyên suốt một sản phẩm.
  • Danh sách đích dài, gom thành các section có tên.

Khi nào không dùng

  • Chuyển giữa các view của cùng một nội dung. Dùng Tabs.
  • Danh sách hành động ngắn, neo vào một control. Dùng DropdownMenu.
  • Một section tùy chọn trên một trang. Dùng Accordion.

Biến thể

collapsible

Đặt trên SidebarProvider. icon giữ rail icon kèm Tooltip khi thu lại; offcanvas giấu hẳn sidebar trên desktop khi không có SidebarBrand, hoặc giữ nút gạt khôi phục bên trong khi có SidebarBrand; none giữ sidebar luôn mở.

  • Không gian làm việc

    Tổng quan

    Nội dung của bạn xuất hiện ở đây.

    iconmặc định

  • Không gian làm việc

    Tổng quan

    Nội dung của bạn xuất hiện ở đây.

    offcanvas

  • Không gian làm việc

    Tổng quan

    Nội dung của bạn xuất hiện ở đây.

    none

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

<SidebarProvider side="left" collapsible="icon" defaultValue="overview">
  <div className="flex min-h-[32rem] w-full overflow-hidden rounded-container border border-border bg-background-surface">
    <Sidebar className="h-auto">
      <SidebarHeader className="border-b border-border">
        <SidebarBrand name="Không gian làm việc" />
      </SidebarHeader>
      <SidebarContent className="[&_ul]:gap-sm">
        <SidebarSection label="Không gian làm việc">
          <SidebarItem value="overview" leadingIcon={<IconHome size={20} />} leadingIconOn={<IconHomeFilled size={20} />}>Tổng quan</SidebarItem>
          <SidebarItem value="reports" leadingIcon={<IconChartLine size={20} />}>Báo cáo</SidebarItem>
          <SidebarItem value="settings" leadingIcon={<IconSettings size={20} />}>Cài đặt</SidebarItem>
        </SidebarSection>
        <SidebarSection label="Tài khoản">
          <SidebarItem value="profile" leadingIcon={<IconUser size={20} />}>Hồ sơ</SidebarItem>
        </SidebarSection>
      </SidebarContent>
    </Sidebar>
    <div className="flex min-w-0 flex-1 flex-col gap-lg p-lg">
      <div className="flex flex-col gap-xs">
        <p className="text-xs text-text-secondary">Không gian làm việc</p>
        <p className="text-heading-3 text-text-primary">Tổng quan</p>
      </div>
      <div className="flex flex-1 items-center justify-center rounded-container border border-border bg-background-surface p-md text-center text-sm text-text-secondary">Nội dung của bạn xuất hiện ở đây.</div>
    </div>
  </div>
</SidebarProvider>
<SidebarProvider side="left" collapsible="offcanvas" defaultValue="overview">
  <div className="flex min-h-[32rem] w-full overflow-hidden rounded-container border border-border bg-background-surface">
    <Sidebar className="h-auto">
      <SidebarHeader className="border-b border-border">
        <SidebarBrand name="Không gian làm việc" />
      </SidebarHeader>
      <SidebarContent className="[&_ul]:gap-sm">
        <SidebarSection label="Không gian làm việc">
          <SidebarItem value="overview" leadingIcon={<IconHome size={20} />} leadingIconOn={<IconHomeFilled size={20} />}>Tổng quan</SidebarItem>
          <SidebarItem value="reports" leadingIcon={<IconChartLine size={20} />}>Báo cáo</SidebarItem>
          <SidebarItem value="settings" leadingIcon={<IconSettings size={20} />}>Cài đặt</SidebarItem>
        </SidebarSection>
        <SidebarSection label="Tài khoản">
          <SidebarItem value="profile" leadingIcon={<IconUser size={20} />}>Hồ sơ</SidebarItem>
        </SidebarSection>
      </SidebarContent>
    </Sidebar>
    <div className="flex min-w-0 flex-1 flex-col gap-lg p-lg">
      <div className="flex flex-col gap-xs">
        <p className="text-xs text-text-secondary">Không gian làm việc</p>
        <p className="text-heading-3 text-text-primary">Tổng quan</p>
      </div>
      <div className="flex flex-1 items-center justify-center rounded-container border border-border bg-background-surface p-md text-center text-sm text-text-secondary">Nội dung của bạn xuất hiện ở đây.</div>
    </div>
  </div>
</SidebarProvider>
<SidebarProvider side="left" collapsible="none" defaultValue="overview">
  <div className="flex min-h-[32rem] w-full overflow-hidden rounded-container border border-border bg-background-surface">
    <Sidebar className="h-auto">
      <SidebarHeader className="border-b border-border">
        <SidebarBrand name="Không gian làm việc" />
      </SidebarHeader>
      <SidebarContent className="[&_ul]:gap-sm">
        <SidebarSection label="Không gian làm việc">
          <SidebarItem value="overview" leadingIcon={<IconHome size={20} />} leadingIconOn={<IconHomeFilled size={20} />}>Tổng quan</SidebarItem>
          <SidebarItem value="reports" leadingIcon={<IconChartLine size={20} />}>Báo cáo</SidebarItem>
          <SidebarItem value="settings" leadingIcon={<IconSettings size={20} />}>Cài đặt</SidebarItem>
        </SidebarSection>
        <SidebarSection label="Tài khoản">
          <SidebarItem value="profile" leadingIcon={<IconUser size={20} />}>Hồ sơ</SidebarItem>
        </SidebarSection>
      </SidebarContent>
    </Sidebar>
    <div className="flex min-w-0 flex-1 flex-col gap-lg p-lg">
      <div className="flex flex-col gap-xs">
        <p className="text-xs text-text-secondary">Không gian làm việc</p>
        <p className="text-heading-3 text-text-primary">Tổng quan</p>
      </div>
      <div className="flex flex-1 items-center justify-center rounded-container border border-border bg-background-surface p-md text-center text-sm text-text-secondary">Nội dung của bạn xuất hiện ở đây.</div>
    </div>
  </div>
</SidebarProvider>

side

Đặt trên SidebarProvider. Cạnh mà sidebar ngồi; Sheet mở từ cùng cạnh đó.

  • Không gian làm việc

    Tổng quan

    Nội dung của bạn xuất hiện ở đây.

    leftmặc định

  • Không gian làm việc

    Tổng quan

    Nội dung của bạn xuất hiện ở đây.

    right

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

<SidebarProvider side="left" collapsible="icon" defaultValue="overview">
  <div className="flex min-h-[32rem] w-full overflow-hidden rounded-container border border-border bg-background-surface">
    <Sidebar className="h-auto">
      <SidebarHeader className="border-b border-border">
        <SidebarBrand name="Không gian làm việc" />
      </SidebarHeader>
      <SidebarContent className="[&_ul]:gap-sm">
        <SidebarSection label="Không gian làm việc">
          <SidebarItem value="overview" leadingIcon={<IconHome size={20} />} leadingIconOn={<IconHomeFilled size={20} />}>Tổng quan</SidebarItem>
          <SidebarItem value="reports" leadingIcon={<IconChartLine size={20} />}>Báo cáo</SidebarItem>
          <SidebarItem value="settings" leadingIcon={<IconSettings size={20} />}>Cài đặt</SidebarItem>
        </SidebarSection>
        <SidebarSection label="Tài khoản">
          <SidebarItem value="profile" leadingIcon={<IconUser size={20} />}>Hồ sơ</SidebarItem>
        </SidebarSection>
      </SidebarContent>
    </Sidebar>
    <div className="flex min-w-0 flex-1 flex-col gap-lg p-lg">
      <div className="flex flex-col gap-xs">
        <p className="text-xs text-text-secondary">Không gian làm việc</p>
        <p className="text-heading-3 text-text-primary">Tổng quan</p>
      </div>
      <div className="flex flex-1 items-center justify-center rounded-container border border-border bg-background-surface p-md text-center text-sm text-text-secondary">Nội dung của bạn xuất hiện ở đây.</div>
    </div>
  </div>
</SidebarProvider>
<SidebarProvider side="right" collapsible="icon" defaultValue="overview">
  <div className="flex min-h-[32rem] w-full overflow-hidden rounded-container border border-border bg-background-surface">
    <Sidebar className="order-2 h-auto">
      <SidebarHeader className="border-b border-border">
        <SidebarBrand name="Không gian làm việc" />
      </SidebarHeader>
      <SidebarContent className="[&_ul]:gap-sm">
        <SidebarSection label="Không gian làm việc">
          <SidebarItem value="overview" leadingIcon={<IconHome size={20} />} leadingIconOn={<IconHomeFilled size={20} />}>Tổng quan</SidebarItem>
          <SidebarItem value="reports" leadingIcon={<IconChartLine size={20} />}>Báo cáo</SidebarItem>
          <SidebarItem value="settings" leadingIcon={<IconSettings size={20} />}>Cài đặt</SidebarItem>
        </SidebarSection>
        <SidebarSection label="Tài khoản">
          <SidebarItem value="profile" leadingIcon={<IconUser size={20} />}>Hồ sơ</SidebarItem>
        </SidebarSection>
      </SidebarContent>
    </Sidebar>
    <div className="flex min-w-0 flex-1 flex-col gap-lg p-lg">
      <div className="flex flex-col gap-xs">
        <p className="text-xs text-text-secondary">Không gian làm việc</p>
        <p className="text-heading-3 text-text-primary">Tổng quan</p>
      </div>
      <div className="flex flex-1 items-center justify-center rounded-container border border-border bg-background-surface p-md text-center text-sm text-text-secondary">Nội dung của bạn xuất hiện ở đây.</div>
    </div>
  </div>
</SidebarProvider>

variant

Đặt trên Sidebar. default giữ ví dụ điều hướng phẳng; panel thêm các nhóm lồng nhau. Khi có SidebarBrand, cả hai variant giữ nút gạt trong header, thay logo trên rail đã thu hoặc rail mobile.

  • Không gian làm việc

    Tổng quan

    Nội dung của bạn xuất hiện ở đây.

    defaultMặc địnhmặc định

  • Không gian làm việc

    Tổng quan

    Nội dung của bạn xuất hiện ở đây.

    panelPanel có logo

import { IconChartLine, IconHome, IconHomeFilled, IconLayoutGrid, IconList, IconSettings, IconTag, IconUser } from "@tabler/icons-react"
import { Sidebar, SidebarBrand, SidebarContent, SidebarFooter, SidebarGroup, SidebarHeader, SidebarItem, SidebarProvider, SidebarSection } from "@/components/ui/sidebar"

<SidebarProvider side="left" collapsible="icon" defaultValue="overview">
  <div className="flex min-h-[32rem] w-full overflow-hidden rounded-container border border-border bg-background-surface">
    <Sidebar className="h-auto">
      <SidebarHeader className="border-b border-border">
        <SidebarBrand name="Không gian làm việc" />
      </SidebarHeader>
      <SidebarContent className="[&_ul]:gap-sm">
        <SidebarSection label="Không gian làm việc">
          <SidebarItem value="overview" leadingIcon={<IconHome size={20} />} leadingIconOn={<IconHomeFilled size={20} />}>Tổng quan</SidebarItem>
          <SidebarItem value="reports" leadingIcon={<IconChartLine size={20} />}>Báo cáo</SidebarItem>
          <SidebarItem value="settings" leadingIcon={<IconSettings size={20} />}>Cài đặt</SidebarItem>
        </SidebarSection>
        <SidebarSection label="Tài khoản">
          <SidebarItem value="profile" leadingIcon={<IconUser size={20} />}>Hồ sơ</SidebarItem>
        </SidebarSection>
      </SidebarContent>
    </Sidebar>
    <div className="flex min-w-0 flex-1 flex-col gap-lg p-lg">
      <div className="flex flex-col gap-xs">
        <p className="text-xs text-text-secondary">Không gian làm việc</p>
        <p className="text-heading-3 text-text-primary">Tổng quan</p>
      </div>
      <div className="flex flex-1 items-center justify-center rounded-container border border-border bg-background-surface p-md text-center text-sm text-text-secondary">Nội dung của bạn xuất hiện ở đây.</div>
    </div>
  </div>
</SidebarProvider>
<SidebarProvider side="left" defaultValue="overview">
  <div className="flex min-h-[32rem] w-full overflow-hidden rounded-container border border-border bg-background-surface">
    <Sidebar variant="panel" className="h-auto">
      <SidebarHeader className="border-b border-border">
        <SidebarBrand name="Không gian làm việc" />
      </SidebarHeader>
      <SidebarContent className="[&_ul]:gap-sm">
        <SidebarSection>
          <SidebarItem value="overview" leadingIcon={<IconHome size={20} />} leadingIconOn={<IconHomeFilled size={20} />}>Tổng quan</SidebarItem>
          <SidebarItem value="activity" leadingIcon={<IconChartLine size={20} />}>Hoạt động</SidebarItem>
        </SidebarSection>
        <SidebarSection label="Không gian làm việc">
          <SidebarGroup label="Dự án" leadingIcon={<IconLayoutGrid size={20} />} defaultOpen>
            <SidebarItem value="all-projects">Tất cả dự án</SidebarItem>
            <SidebarItem value="recent-projects">Dự án gần đây</SidebarItem>
            <SidebarItem value="archived-projects">Dự án đã lưu trữ</SidebarItem>
          </SidebarGroup>
          <SidebarGroup label="Thư viện" leadingIcon={<IconList size={20} />}>
            <SidebarItem value="documents">Tài liệu</SidebarItem>
            <SidebarItem value="assets">Tài nguyên</SidebarItem>
          </SidebarGroup>
          <SidebarItem value="labels" leadingIcon={<IconTag size={20} />}>Nhãn</SidebarItem>
        </SidebarSection>
      </SidebarContent>
      <SidebarFooter>
        <SidebarItem value="settings" leadingIcon={<IconSettings size={20} />}>Cài đặt</SidebarItem>
        <SidebarItem value="your-account" leadingIcon={<IconUser size={20} />}>Tài khoản của bạn</SidebarItem>
      </SidebarFooter>
    </Sidebar>
    <div className="flex min-w-0 flex-1 flex-col gap-lg p-lg">
      <div className="flex flex-col gap-xs">
        <p className="text-xs text-text-secondary">Không gian làm việc</p>
        <p className="text-heading-3 text-text-primary">Tổng quan</p>
      </div>
      <div className="flex flex-1 items-center justify-center rounded-container border border-border bg-background-surface p-md text-center text-sm text-text-secondary">Nội dung của bạn xuất hiện ở đây.</div>
    </div>
  </div>
</SidebarProvider>

Ví dụ

Điều hướng app

Nội dung của bạn xuất hiện ở đây.
import { IconChartLine, IconHome, IconHomeFilled, IconSettings } from "@tabler/icons-react"
import { Button } from "@/components/ui/button"
import { Sidebar, SidebarBrand, SidebarContent, SidebarFooter, SidebarHeader, SidebarItem, SidebarProvider, SidebarSection } from "@/components/ui/sidebar"

<SidebarProvider defaultValue="overview">
  <div className="flex min-h-[32rem] w-full rounded-container border border-border">
    <Sidebar className="h-auto">
      <SidebarHeader>
        <SidebarBrand name="Không gian làm việc" />
      </SidebarHeader>
      <SidebarContent>
        <SidebarSection label="Không gian làm việc">
          <SidebarItem value="overview" leadingIcon={<IconHome size={20} />} leadingIconOn={<IconHomeFilled size={20} />}>Overview</SidebarItem>
          <SidebarItem value="reports" leadingIcon={<IconChartLine size={20} />}>Reports</SidebarItem>
        </SidebarSection>
        <SidebarSection label="Tài khoản">
          <SidebarItem value="settings" leadingIcon={<IconSettings size={20} />} count={2}>Settings</SidebarItem>
        </SidebarSection>
      </SidebarContent>
      <SidebarFooter>
        <Button variant="secondary" className="w-full">Mời mọi người</Button>
      </SidebarFooter>
    </Sidebar>
    <div className="flex min-w-0 flex-1 items-center justify-center p-md text-center text-sm text-text-secondary">Nội dung của bạn xuất hiện ở đây.</div>
  </div>
</SidebarProvider>

Offcanvas với trigger

collapsible offcanvas giấu sidebar trên desktop; trigger bật tắt sidebar và mở Sheet trên màn hình nhỏ.

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

<SidebarProvider defaultValue="projects" collapsible="offcanvas" defaultCollapsed>
  <SidebarTrigger label="Bật tắt điều hướng" />
  <Sidebar>
    <SidebarContent>
      <SidebarSection label="Trình đơn">
        <SidebarItem value="projects" leadingIcon={<IconLayoutGrid size={20} />} leadingIconOn={<IconLayoutGridFilled size={20} />} active>Projects</SidebarItem>
      </SidebarSection>
    </SidebarContent>
  </Sidebar>
</SidebarProvider>

Panel với header brand

Nút gạt trong header đứng cạnh logo placeholder. Nhóm lồng nhau mở tại chỗ; rail gọn và sheet mobile giữ điều hướng tới được.

import { IconHome, IconHomeFilled, IconLayoutGrid, IconSettings } from "@tabler/icons-react"
import { Sidebar, SidebarBrand, SidebarContent, SidebarFooter, SidebarGroup, SidebarHeader, SidebarItem, SidebarProvider, SidebarSection } from "@/components/ui/sidebar"

<SidebarProvider defaultValue="overview">
  <Sidebar variant="panel">
    <SidebarHeader>
      <SidebarBrand name="Không gian làm việc" />
    </SidebarHeader>
    <SidebarContent>
      <SidebarSection label="Không gian làm việc">
        <SidebarItem value="overview" leadingIcon={<IconHome size={20} />} leadingIconOn={<IconHomeFilled size={20} />}>Overview</SidebarItem>
        <SidebarGroup label="Dự án" leadingIcon={<IconLayoutGrid size={20} />} defaultOpen>
          <SidebarItem value="all-projects">Tất cả dự án</SidebarItem>
          <SidebarItem value="recent-projects">Dự án gần đây</SidebarItem>
        </SidebarGroup>
      </SidebarSection>
    </SidebarContent>
    <SidebarFooter>
      <SidebarItem value="settings" leadingIcon={<IconSettings size={20} />}>Settings</SidebarItem>
    </SidebarFooter>
  </Sidebar>
</SidebarProvider>

Bố cục inset

Bố cục app: Sidebar trên nền page và nội dung trang trong một surface inset với đệm 32px.

Tổng quan

Doanh thu

Last 30 days

import { IconChartLine, IconHome, IconHomeFilled, IconSettings } from "@tabler/icons-react"
import { Card, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Sidebar, SidebarBrand, SidebarContent, SidebarHeader, SidebarInset, SidebarItem, SidebarProvider, SidebarSection } from "@/components/ui/sidebar"

<SidebarProvider defaultValue="overview">
  <div className="flex h-[32rem] w-full overflow-hidden rounded-container border border-border bg-background-page">
    <Sidebar inset className="h-auto">
      <SidebarHeader>
        <SidebarBrand name="Không gian làm việc" />
      </SidebarHeader>
      <SidebarContent>
        <SidebarSection label="Không gian làm việc">
          <SidebarItem value="overview" leadingIcon={<IconHome size={20} />} leadingIconOn={<IconHomeFilled size={20} />}>Overview</SidebarItem>
          <SidebarItem value="reports" leadingIcon={<IconChartLine size={20} />}>Reports</SidebarItem>
          <SidebarItem value="settings" leadingIcon={<IconSettings size={20} />}>Settings</SidebarItem>
        </SidebarSection>
      </SidebarContent>
    </Sidebar>
    <SidebarInset className="gap-2xl">
      <h1 className="text-heading-2">Tổng quan</h1>
      <Card>
        <CardHeader>
          <CardTitle>Doanh thu</CardTitle>
          <CardDescription>Last 30 days</CardDescription>
        </CardHeader>
      </Card>
    </SidebarInset>
  </div>
</SidebarProvider>

Nên và không nên

Nên

  • Cho mỗi section một label; label đặt tên nav và giúp người đọc định hướng.
  • Đánh dấu đúng một item active, trang người dùng đang ở.
  • Giữ footer cho danh tính và hành động tài khoản, không cho điều hướng.
  • Dùng SidebarBrand trong SidebarHeader ở cả hai variant để nút gạt vẫn nằm trong sidebar.
  • Cho mỗi SidebarGroup một label và icon dẫn đầu. Dùng các link SidebarItem lồng nhau cho các đích.
  • Dùng value của item với defaultValue của SidebarProvider cho đích dạng button, chọn view mà không cần link. Dùng value và onValueChange khi ứng dụng kiểm soát lựa chọn.
  • Giữ các đích submenu trong SidebarGroup để rail của panel đưa chúng ra trong flyout bên.
  • Trong một app, đặt inset trên Sidebar và để nội dung trang trong SidebarInset. Đệm của nó là đệm trang: đừng đệm nội dung lần nữa, và tách các section bằng gap-2xl.

Không nên

  • Đừng chuyển giữa các view của cùng một nội dung; dùng Tabs.
  • Đừng đặt control khác ngoài item bên trong content; đặt chúng ở header hoặc footer.
  • Đừng lồng một sidebar vào một sidebar.
  • Đừng dùng offcanvas khi không có SidebarBrand, trừ khi một nút mở bên ngoài vẫn tới được.
  • Đừng bọc cả trang bằng một Card bên trong SidebarInset; nó đã là surface.

Props

TênKiểuGiá trịMặc địnhMô tả
collapsedboolean--Đặt trên SidebarProvider. Trạng thái đã thu, khi bạn kiểm soát nó. Đi cùng onCollapsedChange.
defaultCollapsedboolean-falseĐặt trên SidebarProvider. Thu lại ở lần render đầu.
onCollapsedChangefunction--Đặt trên SidebarProvider. Được gọi với trạng thái thu kế tiếp.
collapsibleenumicon | offcanvas | noneiconĐặt trên SidebarProvider. icon giữ rail icon kèm Tooltip khi thu lại; offcanvas giấu hẳn sidebar trên desktop khi không có SidebarBrand, hoặc giữ nút gạt khôi phục bên trong khi có SidebarBrand; none giữ sidebar luôn mở.
sideenumleft | rightleftĐặt trên SidebarProvider. Cạnh mà sidebar ngồi; Sheet mở từ cùng cạnh đó.
labelstring-MainĐặt trên SidebarContent thì là tên landmark điều hướng; đặt trên SidebarSection thì là heading và tên của nhóm (giấu trên rail icon).
activeboolean-falseĐặt trên SidebarItem. Trang mà item này trỏ tới: aria-current="page", nền accent muted với chữ strong của nó, và icon ở weight fill. Khi bỏ qua trên item có value, lựa chọn lấy từ SidebarProvider. Prop active truyền tường minh thì ghi đè trạng thái selected của item đó.
asChildboolean-falseĐặt trên SidebarItem. Render item thành đúng một phần tử con, thường là link của router.
hrefstring--Đặt trên SidebarItem. Có href thì item là link; không có thì là button.
countnumber--Đặt trên SidebarItem. Một số sau label, nằm trong Badge; trên rail thì số chuyển vào Tooltip.
leadingIconnode--Đặt trên SidebarItem. Icon Tabler đứng trước label, 20px.
leadingIconOnnode--Đặt trên SidebarItem. Icon biến thể filled (Tabler *Filled, ví dụ IconHomeFilled) hiện trên item active thay cho leadingIcon.
disabledboolean-falseĐặt trên SidebarItem. Item không kích hoạt được và bị mờ, kể cả link và link router được slot. Item disabled rời thứ tự Tab; trên rail icon, Tooltip của chúng vẫn mở khi hover.
variantenumdefault | paneldefaultĐặt trên Sidebar. default giữ ví dụ điều hướng phẳng; panel thêm các nhóm lồng nhau. Khi có SidebarBrand, cả hai variant giữ nút gạt trong header, thay logo trên rail đã thu hoặc rail mobile.
name bắt buộcstring--Đặt trên SidebarBrand. Tên workspace bắt buộc, giấu khỏi mắt trên rail.
logonode--Đặt trên SidebarBrand. Một node logo tùy chỉnh; nếu bỏ qua thì hiện placeholder neutral.
openboolean--Đặt trên SidebarGroup. Điều khiển disclosure nội tuyến của sidebar đang mở; đi cùng onOpenChange. Flyout hover tạm của panel đã thu có trạng thái riêng.
defaultOpenboolean-falseĐặt trên SidebarGroup. Cho disclosure nội tuyến bắt đầu ở trạng thái mở. Không mở flyout của panel đã thu.
onOpenChangefunction--Đặt trên SidebarGroup. Được gọi với trạng thái disclosure nội tuyến được yêu cầu. Đổi flyout tạm của panel thì không gọi prop này.
valuestring--Đặt trên SidebarProvider cho lựa chọn controlled, đi cùng onValueChange. Đặt trên SidebarItem để nhận diện đích đó. Kích hoạt item enabled thì cập nhật lựa chọn; href vẫn không bắt buộc.
defaultValuestring--Đặt trên SidebarProvider. Value của item được chọn lúc đầu khi lựa chọn uncontrolled.
onValueChangefunction--Đặt trên SidebarProvider. Được gọi một lần khi item enabled yêu cầu một value selected khác.
insetboolean-falseĐặt trên Sidebar. Đặt cột lên nền page, không có cạnh nhìn thấy, cho bố cục app trong đó SidebarInset chứa nội dung trang. Độc lập với variant.

Slot

TênBắt buộcMô tả
headerkhôngSidebarHeader phía trên nội dung cuộn.
contentcóSidebarContent với một hoặc nhiều SidebarSection gồm các SidebarItem.
footerkhôngSidebarFooter ghim ở cuối.
insetkhôngSidebarInset cạnh Sidebar, chứa nội dung trang.

Cấu tạo

PhầnMô tả
rootSidebar: cột trên desktop, ẩn dưới md, rộng 256px, chỉ có viền ở cạnh hướng vào nội dung. Trên rail icon, rộng bằng một item md vuông cộng spacing-sm mỗi bên (49px kể cả viền với chuột, 53px với cảm ứng), và header, content cùng footer đệm bằng spacing-sm. Khi có SidebarBrand, cả hai variant dùng bề rộng của một control md trên rail và giữ một rail gọn vẫn hiện dưới md để nút gạt bên trong vẫn tới được.
headerSidebarHeader: khối phía trên nội dung cuộn, như tên workspace.
contentSidebarContent: nhóm các section cuộn được, một nav được label đặt tên (mặc định "Main").
footerSidebarFooter: khối ghim ở cuối, có một Separator phía trên.
sectionSidebarSection: một nhóm item liên quan, được label đặt tên, các item nằm trong một list.
labelHeading của section: chữ secondary medium 12px, giấu trên rail icon.
itemSidebarItem: một đích, là link khi có href, là button khi không có, hoặc phần tử bất kỳ với asChild. Cao ít nhất bằng control md, chữ medium 14px, một Badge sau label khi có count. Trên rail icon, item có icon là ô vuông bằng chiều cao control md.
currentItem active, trang người dùng đang ở: nền accent muted với chữ strong của nó.
currentIconIcon của item active, màu icon accent, ở weight fill.
iconIcon Tabler dẫn đầu của item, 20px; leadingIconOn (biến thể *Filled) thay nó trên item active.
triggerSidebarTrigger: một icon button ghost, thu sidebar từ md trở lên và mở Sheet dưới md, được label đặt tên. Với collapsible none thì chỉ hiện dưới md.
brandSidebarBrand: placeholder hoặc logo được đưa vào, và tên workspace cạnh SidebarTrigger khi đang mở. Trên rail, logo bị gỡ và nút gạt chiếm chỗ đó, thẳng hàng với các icon điều hướng. Logo trở lại khi mở rộng, kể cả trong Sheet mobile.
groupSidebarGroup: button disclosure có tên, với icon dẫn đầu và caret, rồi đến list các đích lồng nhau. Phần con bị giấu trên rail; kích hoạt thì mở rộng sidebar, hoặc mở sheet mobile. Trên panel desktop đã thu, hover hoặc kích hoạt icon để mở các đích trong flyout bên hướng vào trang, mà không mở rộng sidebar. Flyout dùng lại cách định vị, xử lý va chạm và chuyển động của Popover.
insetSidebarInset: nội dung trang cạnh một Sidebar inset, một landmark main tự cuộn. Từ md trở lên là một surface có bo góc page và viền, cách mép canvas spacing-sm, đệm spacing-2xl (32px). Dưới md Sidebar là một Sheet, nên nó tràn viền với đệm spacing-lg cộng safe area dưới. Sidebar inset dùng nền page và cạnh trong suốt.

Khả năng truy cập

Role: complementary

PhímHành động
TabĐi từ item này sang item khác; item là link hoặc button theo thứ tự trên trang.
Enter, SpaceItem button thì kích hoạt; item link thì đi theo href.
EscapeĐóng Sheet mà sidebar biến thành trên màn hình nhỏ.
  • Root là aside (complementary). SidebarContent bên trong là landmark điều hướng duy nhất, được label đặt tên (mặc định "Main").
  • Mỗi SidebarSection là một group được label nhìn thấy đặt tên (aria-labelledby), hoặc bằng aria-label trên rail icon nơi label bị giấu. Các item của nó là một list.
  • Item của trang hiện tại đặt aria-current="page" và icon chuyển sang weight fill; trạng thái không bao giờ chỉ dựa vào màu.
  • Trên rail, item có icon chuyển label vào một Tooltip và một span sr-only. Item không có icon giữ chữ nhìn thấy. Item disabled đứng ngoài thứ tự Tab, và Tooltip của nó vẫn mở khi hover. Sheet mobile luôn hiện đủ label.
  • Sheet tự đặt tên bằng title sr-only; button trigger mang cùng tên đó trong aria-label.
  • Các phần của Sidebar phải nằm trong một SidebarProvider; không có thì chúng throw.
  • SidebarBrand đặt tên trigger bên trong theo hành động: Thu gọn sidebar, Mở rộng sidebar hoặc Đóng sidebar. Rail mobile của panel mở Sheet; header của Sheet đóng Sheet và trả focus về nút mở ban đầu.
  • SidebarGroup đưa ra aria-expanded và aria-controls. Nhóm đang đóng và nhóm trên rail gỡ các đích lồng nhau khỏi điều hướng bàn phím. Trạng thái mở của nhóm vẫn còn khi sidebar thu lại.
  • Khi có header brand, offcanvas giấu điều hướng nhưng giữ button khôi phục bên trong trên rail, logo thì bị giấu. Khi không có header brand, hành vi offcanvas hiện có giấu cả cột và cần một nút mở bên ngoài.
  • Trên rail đã thu, SidebarBrand gỡ logo trang trí và giữ nút gạt ở chỗ đó. Nút gạt vẫn mounted để focus bàn phím còn sau khi thu và khi mở.
  • Đích dạng button có value dùng chung một lựa chọn qua SidebarProvider; lựa chọn controlled chỉ đổi khi value được truyền vào đổi. Item disabled không yêu cầu lựa chọn được. Lựa chọn còn giữa rail desktop và Sheet mobile.
  • Flyout nhóm của panel đã thu mở khi hover mà không chuyển focus. Click hoặc kích hoạt bằng bàn phím thì đưa focus vào flyout; Escape đóng flyout. Chọn một đích thì đóng flyout và giữ rail đã thu. Nhóm rail mặc định và nhóm mobile giữ hành vi mở rộng hiện có.

Cài đặt

npx werewolf-ui add sidebar

Chạy npx werewolf-ui init một lần trong app trước khi thêm component. Init cài token, thêm CSS import và luật cho agent. Add cài component này cùng các dependency và giữ nguyên theme của bạn. Xem Cài đặt để biết yêu cầu và cách cài qua registry.