HextaUI

Sidebar

Simgelere ya da ekran dışına daralan, header'ınızın altında sabit kalan ve telefonlarda kaydırılabilir bir sayfaya dönüşen bir uygulama kenar çubuğu.

import {
  IconBook,
  IconChartBar,
  IconChevronRight,
  IconDots,
  IconFolder,
  IconHome,
  IconInbox,
  IconLayoutDashboard,
  IconLogout,
  IconSelector,
  IconSettings,
  IconShare,
  IconTrash,
} from "@tabler/icons-react"

import {
  Breadcrumb,
  BreadcrumbItem,
  BreadcrumbLink,
  BreadcrumbList,
  BreadcrumbPage,
  BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
import {
  Collapsible,
  CollapsibleContent,
  CollapsibleTrigger,
} from "@/components/ui/collapsible"
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import {
  Sidebar,
  SidebarContent,
  SidebarFooter,
  SidebarGroup,
  SidebarGroupContent,
  SidebarGroupLabel,
  SidebarHeader,
  SidebarInset,
  SidebarMenu,
  SidebarMenuAction,
  SidebarMenuBadge,
  SidebarMenuButton,
  SidebarMenuItem,
  SidebarMenuSub,
  SidebarMenuSubButton,
  SidebarMenuSubItem,
  SidebarProvider,
  SidebarRail,
  SidebarTrigger,
} from "@/components/ui/sidebar"

const projects = [
  { name: "Design engineering", icon: IconFolder },
  { name: "Sales & marketing", icon: IconChartBar },
  { name: "Travel", icon: IconBook },
]

export function SidebarDemo() {
  return (
    <SidebarProvider className="h-128 min-h-0">
      <Sidebar collapsible="icon">
        <SidebarHeader>
          <SidebarMenu>
            <SidebarMenuItem>
              <DropdownMenu>
                <DropdownMenuTrigger render={<SidebarMenuButton size="lg" />}>
                  <div className="flex size-8 shrink-0 items-center justify-center rounded-md bg-sidebar-primary text-sm font-semibold text-sidebar-primary-foreground">
                    A
                  </div>
                  <div className="grid min-w-0 flex-1 leading-tight">
                    <span className="truncate font-medium">Acme Inc</span>
                    <span className="truncate text-xs text-muted-foreground">
                      Enterprise
                    </span>
                  </div>
                  <IconSelector className="ms-auto" />
                </DropdownMenuTrigger>
                <DropdownMenuContent align="start" className="w-56">
                  <DropdownMenuItem>Acme Inc</DropdownMenuItem>
                  <DropdownMenuItem>Acme Corp.</DropdownMenuItem>
                  <DropdownMenuItem>Evil Corp.</DropdownMenuItem>
                </DropdownMenuContent>
              </DropdownMenu>
            </SidebarMenuItem>
          </SidebarMenu>
        </SidebarHeader>
        <SidebarContent>
          <SidebarGroup>
            <SidebarGroupLabel>Platform</SidebarGroupLabel>
            <SidebarGroupContent>
              <SidebarMenu>
                <SidebarMenuItem>
                  <SidebarMenuButton
                    render={<a href="#" />}
                    isActive
                    tooltip="Home"
                  >
                    <IconHome />
                    <span>Home</span>
                  </SidebarMenuButton>
                </SidebarMenuItem>
                <SidebarMenuItem>
                  <SidebarMenuButton render={<a href="#" />} tooltip="Inbox">
                    <IconInbox />
                    <span>Inbox</span>
                  </SidebarMenuButton>
                  <SidebarMenuBadge>24</SidebarMenuBadge>
                </SidebarMenuItem>
                <Collapsible
                  defaultOpen
                  render={<SidebarMenuItem />}
                  className="group/collapsible"
                >
                  <CollapsibleTrigger
                    render={<SidebarMenuButton tooltip="Dashboards" />}
                  >
                    <IconLayoutDashboard />
                    <span>Dashboards</span>
                    <IconChevronRight className="ms-auto duration-200 group-data-open/collapsible:rotate-90 motion-safe:transition-transform rtl:-scale-x-100" />
                  </CollapsibleTrigger>
                  <CollapsibleContent>
                    <SidebarMenuSub>
                      <SidebarMenuSubItem>
                        <SidebarMenuSubButton href="#">
                          <span>Overview</span>
                        </SidebarMenuSubButton>
                      </SidebarMenuSubItem>
                      <SidebarMenuSubItem>
                        <SidebarMenuSubButton href="#">
                          <span>Revenue</span>
                        </SidebarMenuSubButton>
                      </SidebarMenuSubItem>
                    </SidebarMenuSub>
                  </CollapsibleContent>
                </Collapsible>
                <SidebarMenuItem>
                  <SidebarMenuButton render={<a href="#" />} tooltip="Settings">
                    <IconSettings />
                    <span>Settings</span>
                  </SidebarMenuButton>
                </SidebarMenuItem>
              </SidebarMenu>
            </SidebarGroupContent>
          </SidebarGroup>
          <SidebarGroup>
            <SidebarGroupLabel>Projects</SidebarGroupLabel>
            <SidebarGroupContent>
              <SidebarMenu>
                {projects.map((project) => (
                  <SidebarMenuItem key={project.name}>
                    <SidebarMenuButton
                      render={<a href="#" />}
                      tooltip={project.name}
                    >
                      <project.icon />
                      <span>{project.name}</span>
                    </SidebarMenuButton>
                    <DropdownMenu>
                      <DropdownMenuTrigger
                        render={<SidebarMenuAction showOnHover />}
                      >
                        <IconDots />
                        <span className="sr-only">More</span>
                      </DropdownMenuTrigger>
                      <DropdownMenuContent side="right" align="start">
                        <DropdownMenuItem>
                          <IconShare />
                          Share
                        </DropdownMenuItem>
                        <DropdownMenuSeparator />
                        <DropdownMenuItem variant="destructive">
                          <IconTrash />
                          Delete
                        </DropdownMenuItem>
                      </DropdownMenuContent>
                    </DropdownMenu>
                  </SidebarMenuItem>
                ))}
              </SidebarMenu>
            </SidebarGroupContent>
          </SidebarGroup>
        </SidebarContent>
        <SidebarFooter>
          <SidebarMenu>
            <SidebarMenuItem>
              <DropdownMenu>
                <DropdownMenuTrigger render={<SidebarMenuButton size="lg" />}>
                  <div className="flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-xs font-medium">
                    OM
                  </div>
                  <div className="grid min-w-0 flex-1 leading-tight">
                    <span className="truncate font-medium">Olivia Martin</span>
                    <span className="truncate text-xs text-muted-foreground">
                      [email protected]
                    </span>
                  </div>
                  <IconSelector className="ms-auto" />
                </DropdownMenuTrigger>
                <DropdownMenuContent side="top" align="start" className="w-56">
                  <DropdownMenuItem>
                    <IconSettings />
                    Account
                  </DropdownMenuItem>
                  <DropdownMenuItem>
                    <IconLogout />
                    Log out
                  </DropdownMenuItem>
                </DropdownMenuContent>
              </DropdownMenu>
            </SidebarMenuItem>
          </SidebarMenu>
        </SidebarFooter>
        <SidebarRail />
      </Sidebar>
      <SidebarInset>
        <header className="flex h-14 shrink-0 items-center gap-2 border-b px-4">
          <SidebarTrigger className="-ms-1" />
          <Breadcrumb>
            <BreadcrumbList>
              <BreadcrumbItem>
                <BreadcrumbLink href="#">Platform</BreadcrumbLink>
              </BreadcrumbItem>
              <BreadcrumbSeparator />
              <BreadcrumbItem>
                <BreadcrumbPage>Home</BreadcrumbPage>
              </BreadcrumbItem>
            </BreadcrumbList>
          </Breadcrumb>
        </header>
        <div className="flex flex-1 flex-col gap-4 p-4">
          <div className="grid gap-4 sm:grid-cols-3">
            <div className="aspect-video rounded-xl bg-muted" />
            <div className="aspect-video rounded-xl bg-muted" />
            <div className="aspect-video rounded-xl bg-muted" />
          </div>
          <div className="min-h-32 flex-1 rounded-xl bg-muted" />
        </div>
      </SidebarInset>
    </SidebarProvider>
  )
}
pnpm dlx shadcn@latest add https://hextaui.com/r/sidebar.json

Bileşeni, HextaUI tema token'larını ve bileşenin bağımlı olduğu tüm HextaUI bileşenlerini ekler.

import {
  Sidebar,
  SidebarContent,
  SidebarFooter,
  SidebarGroup,
  SidebarGroupContent,
  SidebarGroupLabel,
  SidebarHeader,
  SidebarInset,
  SidebarMenu,
  SidebarMenuButton,
  SidebarMenuItem,
  SidebarProvider,
  SidebarTrigger,
} from "@/components/ui/sidebar"

Düzeninizi <SidebarProvider /> ile sarın ve sayfayı kenar çubuğundan sonra <SidebarInset /> içine koyun.

export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    <SidebarProvider>
      <AppSidebar />
      <SidebarInset>
        <SidebarTrigger />
        {children}
      </SidebarInset>
    </SidebarProvider>
  )
}
export function AppSidebar() {
  return (
    <Sidebar>
      <SidebarHeader />
      <SidebarContent>
        <SidebarGroup>
          <SidebarGroupLabel>Application</SidebarGroupLabel>
          <SidebarGroupContent>
            <SidebarMenu>
              <SidebarMenuItem>
                <SidebarMenuButton render={<a href="/" />} isActive>
                  <IconHome />
                  <span>Home</span>
                </SidebarMenuButton>
              </SidebarMenuItem>
            </SidebarMenu>
          </SidebarGroupContent>
        </SidebarGroup>
      </SidebarContent>
      <SidebarFooter />
    </Sidebar>
  )
}
SidebarProvider
├── Sidebar
│   ├── SidebarHeader
│   ├── SidebarContent
│   │   └── SidebarGroup
│   │       ├── SidebarGroupLabel
│   │       ├── SidebarGroupAction
│   │       └── SidebarGroupContent
│   │           └── SidebarMenu
│   │               └── SidebarMenuItem
│   │                   ├── SidebarMenuButton
│   │                   ├── SidebarMenuAction
│   │                   ├── SidebarMenuBadge
│   │                   └── SidebarMenuSub
│   │                       └── SidebarMenuSubItem
│   │                           └── SidebarMenuSubButton
│   ├── SidebarFooter
│   └── SidebarRail
└── SidebarInset
    └── SidebarTrigger
  • SidebarProvider açık durumu, klavye kısayolunu ve genişlikleri tutar.
  • Sidebar, sayfa kayarken sabit kalan bir sütundur. 768px'in altında bir sheet'e dönüşür.
  • SidebarHeader ve SidebarFooter yerinde kalır. SidebarContent ikisinin arasında kayar.
  • SidebarGroup isteğe bağlı bir etiketi ve eylemi olan bir bölümdür. SidebarMenu bağlantıları tutar.
  • SidebarInset kenar çubuğunun yanındaki sayfadır.

Varyantlar

variant görünümü belirler: tam yükseklikte bir sidebar, bir floating panel ya da sayfanın kenar çubuğu renginde bir karta dönüştüğü inset. Düzenin animasyonunu görmek için aralarında geçiş yapın.

"use client"

import * as React from "react"
import {
  IconHome,
  IconInbox,
  IconSearch,
  IconSettings,
} from "@tabler/icons-react"

import {
  Sidebar,
  SidebarContent,
  SidebarGroup,
  SidebarGroupContent,
  SidebarGroupLabel,
  SidebarInset,
  SidebarMenu,
  SidebarMenuButton,
  SidebarMenuItem,
  SidebarProvider,
  SidebarTrigger,
} from "@/components/ui/sidebar"
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"

type Variant = "sidebar" | "floating" | "inset"

const items = [
  { title: "Home", icon: IconHome },
  { title: "Inbox", icon: IconInbox },
  { title: "Search", icon: IconSearch },
  { title: "Settings", icon: IconSettings },
]

export function SidebarVariants() {
  const [variant, setVariant] = React.useState<Variant>("inset")
  const [active, setActive] = React.useState("Home")

  return (
    <SidebarProvider className="h-112 min-h-0">
      <Sidebar variant={variant}>
        <SidebarContent>
          <SidebarGroup>
            <SidebarGroupLabel>Application</SidebarGroupLabel>
            <SidebarGroupContent>
              <SidebarMenu>
                {items.map((item) => (
                  <SidebarMenuItem key={item.title}>
                    <SidebarMenuButton
                      isActive={active === item.title}
                      onClick={() => setActive(item.title)}
                    >
                      <item.icon />
                      <span>{item.title}</span>
                    </SidebarMenuButton>
                  </SidebarMenuItem>
                ))}
              </SidebarMenu>
            </SidebarGroupContent>
          </SidebarGroup>
        </SidebarContent>
      </Sidebar>
      <SidebarInset>
        <header className="flex h-14 items-center gap-2 px-4">
          <SidebarTrigger className="-ms-1" />
          <ToggleGroup
            aria-label="Variant"
            value={[variant]}
            onValueChange={(value) => {
              if (value[0]) {
                setVariant(value[0] as Variant)
              }
            }}
          >
            <ToggleGroupItem value="sidebar">Sidebar</ToggleGroupItem>
            <ToggleGroupItem value="floating">Floating</ToggleGroupItem>
            <ToggleGroupItem value="inset">Inset</ToggleGroupItem>
          </ToggleGroup>
        </header>
      </SidebarInset>
    </SidebarProvider>
  )
}

Collapsible

offcanvas kenar çubuğunu görünümden kaydırır, icon onu simgelerine küçültür ve her etiketi bir tooltip'te gösterir, none ise açık tutar. Üzerinde çalıştığınız kenar çubuğunu açıp kapatmak için ⌘B veya Ctrl+B tuşlarına basın.

"use client"

import * as React from "react"
import {
  IconHome,
  IconInbox,
  IconSearch,
  IconSettings,
} from "@tabler/icons-react"

import {
  Sidebar,
  SidebarContent,
  SidebarGroup,
  SidebarGroupContent,
  SidebarGroupLabel,
  SidebarInset,
  SidebarMenu,
  SidebarMenuButton,
  SidebarMenuItem,
  SidebarProvider,
  SidebarTrigger,
} from "@/components/ui/sidebar"
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"

type CollapsibleMode = "offcanvas" | "icon" | "none"

const items = [
  { title: "Home", icon: IconHome },
  { title: "Inbox", icon: IconInbox },
  { title: "Search", icon: IconSearch },
  { title: "Settings", icon: IconSettings },
]

export function SidebarCollapsible() {
  const [collapsible, setCollapsible] = React.useState<CollapsibleMode>("icon")
  const [active, setActive] = React.useState("Home")

  return (
    <SidebarProvider className="h-112 min-h-0">
      <Sidebar collapsible={collapsible}>
        <SidebarContent>
          <SidebarGroup>
            <SidebarGroupLabel>Application</SidebarGroupLabel>
            <SidebarGroupContent>
              <SidebarMenu>
                {items.map((item) => (
                  <SidebarMenuItem key={item.title}>
                    <SidebarMenuButton
                      isActive={active === item.title}
                      onClick={() => setActive(item.title)}
                      tooltip={item.title}
                    >
                      <item.icon />
                      <span>{item.title}</span>
                    </SidebarMenuButton>
                  </SidebarMenuItem>
                ))}
              </SidebarMenu>
            </SidebarGroupContent>
          </SidebarGroup>
        </SidebarContent>
      </Sidebar>
      <SidebarInset>
        <header className="flex h-14 items-center gap-2 px-4">
          <SidebarTrigger className="-ms-1" />
          <ToggleGroup
            aria-label="Collapsible"
            value={[collapsible]}
            onValueChange={(value) => {
              if (value[0]) {
                setCollapsible(value[0] as CollapsibleMode)
              }
            }}
          >
            <ToggleGroupItem value="offcanvas">Offcanvas</ToggleGroupItem>
            <ToggleGroupItem value="icon">Icon</ToggleGroupItem>
            <ToggleGroupItem value="none">None</ToggleGroupItem>
          </ToggleGroup>
        </header>
      </SidebarInset>
    </SidebarProvider>
  )
}

Daraltılabilir gruplar ve alt menüler

Bir SidebarGroup veya SidebarMenuItem'ı bir Collapsible ile sarın, etiketi veya düğmeyi tetikleyici olarak işleyin ve içine bir SidebarMenuSub yerleştirin.

import {
  IconChevronDown,
  IconChevronRight,
  IconFile,
  IconFolder,
} from "@tabler/icons-react"

import {
  Collapsible,
  CollapsibleContent,
  CollapsibleTrigger,
} from "@/components/ui/collapsible"
import {
  Sidebar,
  SidebarContent,
  SidebarGroup,
  SidebarGroupContent,
  SidebarGroupLabel,
  SidebarInset,
  SidebarMenu,
  SidebarMenuButton,
  SidebarMenuItem,
  SidebarMenuSub,
  SidebarMenuSubButton,
  SidebarMenuSubItem,
  SidebarProvider,
  SidebarTrigger,
} from "@/components/ui/sidebar"

const sections = [
  {
    title: "Getting started",
    items: ["Installation", "Project structure", "Deploying"],
  },
  {
    title: "Building your app",
    items: ["Routing", "Data fetching", "Rendering", "Caching", "Styling"],
  },
  {
    title: "API reference",
    items: ["Components", "File conventions", "Functions"],
  },
]

export function SidebarSubmenus() {
  return (
    <SidebarProvider className="h-128 min-h-0">
      <Sidebar>
        <SidebarContent>
          <Collapsible defaultOpen className="group/collapsible">
            <SidebarGroup>
              <SidebarGroupLabel render={<CollapsibleTrigger />}>
                Documentation
                <IconChevronDown className="ms-auto duration-200 group-data-open/collapsible:rotate-180 motion-safe:transition-transform" />
              </SidebarGroupLabel>
              <CollapsibleContent>
                <SidebarGroupContent>
                  <SidebarMenu>
                    {sections.map((section, index) => (
                      <Collapsible
                        key={section.title}
                        defaultOpen={index === 1}
                        render={<SidebarMenuItem />}
                        className="group/section"
                      >
                        <CollapsibleTrigger render={<SidebarMenuButton />}>
                          <IconFolder />
                          <span>{section.title}</span>
                          <IconChevronRight className="ms-auto duration-200 group-data-open/section:rotate-90 motion-safe:transition-transform rtl:-scale-x-100" />
                        </CollapsibleTrigger>
                        <CollapsibleContent>
                          <SidebarMenuSub>
                            {section.items.map((item) => (
                              <SidebarMenuSubItem key={item}>
                                <SidebarMenuSubButton
                                  href="#"
                                  isActive={item === "Data fetching"}
                                >
                                  <IconFile />
                                  <span>{item}</span>
                                </SidebarMenuSubButton>
                              </SidebarMenuSubItem>
                            ))}
                          </SidebarMenuSub>
                        </CollapsibleContent>
                      </Collapsible>
                    ))}
                  </SidebarMenu>
                </SidebarGroupContent>
              </CollapsibleContent>
            </SidebarGroup>
          </Collapsible>
        </SidebarContent>
      </Sidebar>
      <SidebarInset>
        <header className="flex h-14 items-center px-4">
          <SidebarTrigger className="-ms-1" />
        </header>
      </SidebarInset>
    </SidebarProvider>
  )
}

Sağ taraf

side="right" ayarlayın ve kenar çubuğunu SidebarInset'ten sonra yerleştirin. Rail ve mobil sheet tarafı izler.

import { IconAt, IconBell, IconMessage, IconUsers } from "@tabler/icons-react"

import {
  Sidebar,
  SidebarContent,
  SidebarGroup,
  SidebarGroupContent,
  SidebarGroupLabel,
  SidebarInset,
  SidebarMenu,
  SidebarMenuBadge,
  SidebarMenuButton,
  SidebarMenuItem,
  SidebarProvider,
  SidebarRail,
  SidebarTrigger,
} from "@/components/ui/sidebar"

const items = [
  { title: "Mentions", icon: IconAt, count: 3 },
  { title: "Comments", icon: IconMessage, count: 12 },
  { title: "Reminders", icon: IconBell, count: 0 },
  { title: "Followers", icon: IconUsers, count: 128 },
]

export function SidebarRight() {
  return (
    <SidebarProvider className="h-112 min-h-0">
      <SidebarInset>
        <header className="flex h-14 items-center justify-end px-4">
          <SidebarTrigger className="-me-1" />
        </header>
      </SidebarInset>
      <Sidebar side="right">
        <SidebarContent>
          <SidebarGroup>
            <SidebarGroupLabel>Activity</SidebarGroupLabel>
            <SidebarGroupContent>
              <SidebarMenu>
                {items.map((item) => (
                  <SidebarMenuItem key={item.title}>
                    <SidebarMenuButton>
                      <item.icon />
                      <span>{item.title}</span>
                    </SidebarMenuButton>
                    {item.count > 0 && (
                      <SidebarMenuBadge>{item.count}</SidebarMenuBadge>
                    )}
                  </SidebarMenuItem>
                ))}
              </SidebarMenu>
            </SidebarGroupContent>
          </SidebarGroup>
        </SidebarContent>
        <SidebarRail />
      </Sidebar>
    </SidebarProvider>
  )
}

Bir başlığın altında

Kenar çubuğu sticky'dir, bu yüzden üstündeki her şeyin altından başlar. Sticky bir başlıkla --sidebar-top değerini onun yüksekliğine ayarlayın; kenar çubuğu onun altına sabitlenir ve ekranın kalanına sığar.

import { IconHome, IconInbox, IconSettings } from "@tabler/icons-react"

import {
  Sidebar,
  SidebarContent,
  SidebarFooter,
  SidebarGroup,
  SidebarGroupContent,
  SidebarInset,
  SidebarMenu,
  SidebarMenuButton,
  SidebarMenuItem,
  SidebarProvider,
  SidebarTrigger,
} from "@/components/ui/sidebar"

const items = [
  { title: "Home", icon: IconHome },
  { title: "Inbox", icon: IconInbox },
  { title: "Settings", icon: IconSettings },
]

export function SidebarHeaderLayout() {
  return (
    <SidebarProvider className="h-112 min-h-0 flex-col [--sidebar-top:3.5rem]">
      <header className="sticky top-0 z-20 flex h-14 shrink-0 items-center gap-2 border-b bg-background px-4">
        <SidebarTrigger className="-ms-1" />
        <span className="text-sm font-medium">Acme</span>
      </header>
      <div className="flex min-h-0 flex-1">
        <Sidebar>
          <SidebarContent>
            <SidebarGroup>
              <SidebarGroupContent>
                <SidebarMenu>
                  {items.map((item) => (
                    <SidebarMenuItem key={item.title}>
                      <SidebarMenuButton>
                        <item.icon />
                        <span>{item.title}</span>
                      </SidebarMenuButton>
                    </SidebarMenuItem>
                  ))}
                </SidebarMenu>
              </SidebarGroupContent>
            </SidebarGroup>
          </SidebarContent>
          <SidebarFooter>
            <p className="px-2 text-xs text-muted-foreground">v2.4.0</p>
          </SidebarFooter>
        </Sidebar>
        <SidebarInset>
          <div className="flex flex-1 flex-col gap-4 p-4">
            <div className="min-h-32 flex-1 rounded-xl bg-muted" />
          </div>
        </SidebarInset>
      </div>
    </SidebarProvider>
  )
}

Kontrollü

open ve onOpenChange verin. Tetikleyici, rail ve kısayolun hepsi onOpenChange üzerinden geçer.

"use client"

import * as React from "react"
import { IconHome, IconInbox, IconSettings } from "@tabler/icons-react"

import {
  Sidebar,
  SidebarContent,
  SidebarGroup,
  SidebarGroupContent,
  SidebarInset,
  SidebarMenu,
  SidebarMenuButton,
  SidebarMenuItem,
  SidebarProvider,
} from "@/components/ui/sidebar"
import { Switch } from "@/components/ui/switch"

const items = [
  { title: "Home", icon: IconHome },
  { title: "Inbox", icon: IconInbox },
  { title: "Settings", icon: IconSettings },
]

export function SidebarControlled() {
  const [open, setOpen] = React.useState(true)

  return (
    <SidebarProvider
      open={open}
      onOpenChange={setOpen}
      className="h-96 min-h-0"
    >
      <Sidebar collapsible="icon">
        <SidebarContent>
          <SidebarGroup>
            <SidebarGroupContent>
              <SidebarMenu>
                {items.map((item) => (
                  <SidebarMenuItem key={item.title}>
                    <SidebarMenuButton tooltip={item.title}>
                      <item.icon />
                      <span>{item.title}</span>
                    </SidebarMenuButton>
                  </SidebarMenuItem>
                ))}
              </SidebarMenu>
            </SidebarGroupContent>
          </SidebarGroup>
        </SidebarContent>
      </Sidebar>
      <SidebarInset>
        <div className="flex items-center gap-3 p-4">
          <Switch
            id="sidebar-controlled-open"
            checked={open}
            onCheckedChange={setOpen}
          />
          <label htmlFor="sidebar-controlled-open" className="text-sm">
            Sidebar {open ? "expanded" : "collapsed"}
          </label>
        </div>
      </SidebarInset>
    </SidebarProvider>
  )
}

Yükleniyor

SidebarMenuSkeleton yüklenirken bir menüyü doldurur. Genişlikler satıra göre değişir ve sunucu ile istemci arasında eşleşir.

import {
  Sidebar,
  SidebarContent,
  SidebarGroup,
  SidebarGroupContent,
  SidebarGroupLabel,
  SidebarInset,
  SidebarMenu,
  SidebarMenuItem,
  SidebarMenuSkeleton,
  SidebarProvider,
  SidebarTrigger,
} from "@/components/ui/sidebar"

export function SidebarSkeleton() {
  return (
    <SidebarProvider className="h-96 min-h-0">
      <Sidebar>
        <SidebarContent>
          <SidebarGroup>
            <SidebarGroupLabel>Projects</SidebarGroupLabel>
            <SidebarGroupContent>
              <SidebarMenu>
                {Array.from({ length: 6 }).map((_, index) => (
                  <SidebarMenuItem key={index}>
                    <SidebarMenuSkeleton showIcon />
                  </SidebarMenuItem>
                ))}
              </SidebarMenu>
            </SidebarGroupContent>
          </SidebarGroup>
        </SidebarContent>
      </Sidebar>
      <SidebarInset>
        <header className="flex h-14 items-center px-4">
          <SidebarTrigger className="-ms-1" />
        </header>
      </SidebarInset>
    </SidebarProvider>
  )
}

Sağdan sola

dir="rtl" ve side="right" ayarlayın. Boşluk, alt menü çizgileri, tooltip'ler ve tetikleyici simgesi yansıtılır.

import { IconHome, IconInbox, IconSettings } from "@tabler/icons-react"

import {
  Sidebar,
  SidebarContent,
  SidebarGroup,
  SidebarGroupContent,
  SidebarGroupLabel,
  SidebarInset,
  SidebarMenu,
  SidebarMenuBadge,
  SidebarMenuButton,
  SidebarMenuItem,
  SidebarProvider,
  SidebarRail,
  SidebarTrigger,
} from "@/components/ui/sidebar"

const items = [
  { title: "الرئيسية", icon: IconHome },
  { title: "البريد الوارد", icon: IconInbox, badge: "٢٤" },
  { title: "الإعدادات", icon: IconSettings },
]

export function SidebarRtl() {
  return (
    <SidebarProvider dir="rtl" className="h-96 min-h-0">
      <Sidebar side="right" collapsible="icon" dir="rtl">
        <SidebarContent>
          <SidebarGroup>
            <SidebarGroupLabel>التطبيق</SidebarGroupLabel>
            <SidebarGroupContent>
              <SidebarMenu>
                {items.map((item, index) => (
                  <SidebarMenuItem key={item.title}>
                    <SidebarMenuButton
                      isActive={index === 0}
                      tooltip={item.title}
                    >
                      <item.icon />
                      <span>{item.title}</span>
                    </SidebarMenuButton>
                    {item.badge && (
                      <SidebarMenuBadge>{item.badge}</SidebarMenuBadge>
                    )}
                  </SidebarMenuItem>
                ))}
              </SidebarMenu>
            </SidebarGroupContent>
          </SidebarGroup>
        </SidebarContent>
        <SidebarRail />
      </Sidebar>
      <SidebarInset>
        <header className="flex h-14 items-center px-4">
          <SidebarTrigger className="-ms-1" />
        </header>
      </SidebarInset>
    </SidebarProvider>
  )
}

Kenar çubuğu 16rem genişliğindedir; telefonlarda 18rem, simgelere daraltıldığında 3rem. Sağlayıcıda --sidebar-width, --sidebar-width-mobile ve --sidebar-width-icon değerlerini geçersiz kılın.

<SidebarProvider
  style={
    {
      "--sidebar-width": "20rem",
      "--sidebar-width-mobile": "20rem",
    } as React.CSSProperties
  }
>

Kenar çubuğunun yan etkisi yoktur. Açık olup olmadığını hatırlamak için onOpenChange içinde kaydedin ve sunucuda işlerken defaultOpen olarak geri okuyun.

"use client"

export function Providers({
  defaultOpen,
  children,
}: {
  defaultOpen: boolean
  children: React.ReactNode
}) {
  return (
    <SidebarProvider
      defaultOpen={defaultOpen}
      onOpenChange={(open) => {
        document.cookie = `sidebar_state=${open}; path=/; max-age=604800`
      }}
    >
      {children}
    </SidebarProvider>
  )
}
TuşAction
⌘ + BCtrl + BKenar çubuğunu açıp kapatır. Sayfada birden fazla kenar çubuğu varsa odağı tutan, yoksa ilki yanıt verir. Zengin metin düzenleyicide yazarken yok sayılır.
TabShift + TabBağlantılar arasında gezinir. Daraltılmış tuval dışı kenar çubuğu atlanır.
EnterSpaceOdaktaki bağlantıyı, düğmeyi veya tetikleyiciyi etkinleştirir.
EscTelefonlarda kenar çubuğunu kapatır.
  • SidebarTrigger “Toggle Sidebar” olarak etiketlenir ve aria-expanded ile aria-controls sunar.
  • isActive aria-current="page" ayarlar.
  • Tuval dışına daraltmak içeriği klavyeden ve ekran okuyuculardan gizler. Odak içerideyse tetikleyiciye taşınır.
  • Simgelere daraltıldığında etiketler her bağlantının erişilebilir adında kalır ve hover ile klavye odağında tooltip olarak görünür. Grup etiketleri, eylemler ve rozetler gizlenir.
  • Telefonlarda kenar çubuğu modal bir sheet'tir: odak hapsedilir, kaydırmak veya Esc kapatır, bir bağlantıyı izlemek de kapatır. Yeni sekmede açan bağlantılar, indirmeler ve değiştirici tuşlu tıklamalar onu açık tutar.
  • Azaltılmış hareket açıkken daralma anlıktır.
PropTürVarsayılan
defaultOpen
booleantrue
open
boolean–
onOpenChange
(open: boolean) => void–
keyboardShortcutmod, Apple platformlarında ⌘, diğerlerinde Ctrl'dür. null kapatır.
string | null"mod+b"
ÖznitelikAçıklama
data-slot="sidebar-wrapper"Düzen sarmalayıcısı.
--sidebar-widthGenişletilmiş genişlik. Varsayılan 16rem.
--sidebar-width-mobileTelefon sheet'inin genişliği. Varsayılan 18rem.
--sidebar-width-iconSimgelere daraltıldığındaki genişlik. Varsayılan 3rem.
--sidebar-topKaydırırken kenar çubuğunun sabitlendiği yer; örneğin sticky bir başlığın altı. Varsayılan 0px.

className ve diğer prop'lar kenar çubuğu kapsayıcısına gider.

PropTürVarsayılan
side
"left" | "right""left"
variantplain; sayfanın üzerinde duran bir kenar çubuğu için yüzeyi, kenar çizgisini, kaydırma çubuğunu ve menü öğeleri arasındaki boşluğu kaldırır.
"sidebar" | "floating" | "inset" | "plain""sidebar"
collapsible
"offcanvas" | "icon" | "none""offcanvas"
mobileTelefonlarda nasıl açıldığı: yandan bir sheet veya sohbet uygulamaları gibi ekranı doldurarak kayma.
"sheet" | "fullscreen""sheet"
dirTelefon sheet'inin yönünü de belirler.
"ltr" | "rtl"–
ÖznitelikAçıklama
data-slot="sidebar"Kenar çubuğu veya telefonlarda sheet.
data-state"expanded" veya "collapsed".
data-collapsibleDaraltılmışken daraltılabilir mod, aksi halde "". Alt öğeleri group-data-[collapsible=icon]: ile biçimlendirin.
data-variantVaryant.
data-sideTaraf.
data-mobileTelefon sheet'inde bulunur.
data-slot="sidebar-container"Kayan ve yeniden boyutlanan panel.
data-slot="sidebar-inner"İçeriği tutan yüzey.

toggleSidebar çağıran, ghost simgeli bir Button. Durdurmak için onClick içinde event.preventDefault() çağırın. Simgeyi değiştirmek için alt öğe verin.

ÖznitelikAçıklama
data-slot="sidebar-trigger"Tetikleyici.
aria-expandedKenar çubuğunun açık olup olmadığı.

Kenar çubuğunun kenarında, tıklayınca onu açıp kapatan ince bir tıklama alanı. Tetikleyici ve kısayol klavye kullanıcılarını kapsadığı için sekme sırasının dışında bırakılır. Kenar çubuğu tuvalin dışındayken rail ekran kenarında kalır.

ÖznitelikAçıklama
data-slot="sidebar-rail"Rail.

Kalan genişliği alan bir <main>. Bir inset kenar çubuğunun yanında yuvarlak köşeli bir karta dönüşür.

PropTürVarsayılan
renderFarklı bir öğe işler. Sayfada zaten bir <main> landmark'ı varsa <div /> verin.
React.ReactElement | (props) => React.ReactElement–
ÖznitelikAçıklama
data-slot="sidebar-inset"Sayfa alanı.

Düz <div> öğeleri. İçerik ince bir kaydırma çubuğu ve yumuşak kenar solmalarıyla kayar.

ÖznitelikAçıklama
data-slot="sidebar-header"Üst bölüm.
data-slot="sidebar-content"Kayan orta bölüm.
data-slot="sidebar-footer"Alt bölüm.
ÖznitelikAçıklama
data-slot="sidebar-group"Kenar çubuğunun bir bölümü.
data-slot="sidebar-group-content"Grubun içeriği.
PropTürVarsayılan
render
ReactElement | (props, state) => ReactElement<div>
ÖznitelikAçıklama
data-slot="sidebar-group-label"Simgelere daraltıldığında yukarı kayar ve solar.
PropTürVarsayılan
render
ReactElement | (props, state) => ReactElement<button>
ÖznitelikAçıklama
data-slot="sidebar-group-action"Erişilebilir bir etiket gerekir.

Bir <ul> ve <li> öğeleri. Satırların bitişik durduğu sohbet geçmişi gibi yoğun listeler için gap="none" ayarlayın.

PropTürVarsayılan
gapÖğeler arası boşluk. SidebarMenuSub üzerinde de.
"default" | "none""default"
ÖznitelikAçıklama
data-slot="sidebar-menu"Liste.
data-slot="sidebar-menu-item"Bir öğe. Hover stilleri için group/menu-item.
PropTürVarsayılan
isActiveVurgular ve aria-current="page" ayarlar.
booleanfalse
variant
"default" | "outline""default"
size
"default" | "sm" | "lg""default"
tooltipSimgelere daraltıldığında gösterilir. Menüde ilerledikçe içerik öğeler arasında kayar.
ReactNode | TooltipContentProps–
render
ReactElement | (props, state) => ReactElement<button>
ÖznitelikAçıklama
data-slot="sidebar-menu-button"Kardeş stilleri için peer/menu-button.
data-activeisActive iken bulunur.
data-sizeBoyut.
PropTürVarsayılan
showOnHoverYalnızca öğe hover veya odaktayken ya da menüsü açıkken gösterir. Dokunmatik ekranlarda her zaman görünür.
booleanfalse
render
ReactElement | (props, state) => ReactElement<button>
ÖznitelikAçıklama
data-slot="sidebar-menu-action"Erişilebilir bir etiket gerekir.
ÖznitelikAçıklama
data-slot="sidebar-menu-badge"Öğenin sonunda bir sayı.
PropTürVarsayılan
showIcon
booleanfalse
ÖznitelikAçıklama
data-slot="sidebar-menu-skeleton"Yardımcı teknolojilerden gizlidir.

Ön kenarında çizgi bulunan iç içe bir liste. Kenar çubuğu simgelere daraldığında katlanır.

PropTürVarsayılan
isActiveSidebarMenuSubButton üzerinde.
booleanfalse
sizeSidebarMenuSubButton üzerinde.
"sm" | "md""md"
renderSidebarMenuSubButton üzerinde.
ReactElement | (props, state) => ReactElement<a>
ÖznitelikAçıklama
data-slot="sidebar-menu-sub"İç içe liste.
data-slot="sidebar-menu-sub-button"İç içe bir bağlantı.
data-activeisActive iken bulunur.

Sayfa arka planı üzerinde küçük bir Input ve ince bir ayırıcı.

ÖznitelikAçıklama
data-slot="sidebar-input"Girdi.
data-slot="sidebar-separator"Ayırıcı.

En yakın kenar çubuğunu okur ve denetler. SidebarProvider dışında hata fırlatır.

const {
  state,
  open,
  setOpen,
  openMobile,
  setOpenMobile,
  isMobile,
  toggleSidebar,
} = useSidebar()
PropTürVarsayılan
state
"expanded" | "collapsed"–
open
boolean–
setOpen
(open: boolean) => void–
openMobile
boolean–
setOpenMobile
(open: boolean) => void–
isMobile
boolean–
toggleSidebarTelefonlarda sheet'i, aksi halde kenar çubuğunu açıp kapatır.
() => void–

Kullanıldığı bloklar

Sidebar üzerine kurulan bloklar.