shadcn/ui Sidebar içinde menü kurmak için SidebarContent içine bir ya da daha fazla SidebarGroup koyar, her grubun içinde SidebarMenu, SidebarMenuItem ve SidebarMenuButton parçalarını iç içe kullanırsınız. Ek düğme için SidebarMenuAction, alt menü için SidebarMenuSub, sayaç için SidebarMenuBadge, yükleme durumu için SidebarMenuSkeleton vardır. Grupları ve menüleri açılır kapanır yapmak için onları Collapsible ile sararsınız.

Bu yazı, Sidebar kurulumu ve yapısı yazısının devamıdır. Orada SidebarProvider, Sidebar özellikleri ve useSidebar kancası anlatıldı; burada kenar çubuğunun içini dolduran parçaları, veri çekme örneklerini, kontrollü kullanımı, tema değişkenlerini ve duruma göre stil verme ipuçlarını görüyorsunuz. Seri haritası için shadcn/ui öğrenme rehberi sayfasına bakabilirsiniz.

SidebarHeader, SidebarContent ve SidebarFooter

Belgeye göre SidebarHeader ve SidebarFooter kenar çubuğunun üstünde ve altında yapışık duran alanlardır; SidebarContent ise aradaki kaydırılabilir bölümdür ve grupları buraya eklersiniz. Kaynakta başlık ve alt bilgi, küçük bir iç boşlukla dikey sıralanan birer div olarak tanımlıdır. İçerik alanı kalan yüksekliği doldurur ve taşınca kaydırılır; kenar çubuğu simgelere daraldığında ise kaydırma gizlenir.

Başlıkta sık görülen kalıp, belgedeki "çalışma alanı seçici" örneğidir: SidebarHeader içine bir SidebarMenu, onun içine bir DropdownMenu konur ve tetikleyici olarak SidebarMenuButton kullanılır. Alt bilgide aynı kalıp kullanıcı menüsü için tekrarlanır; orada açılır içerik side="top" ile yukarı doğru açılır. Aşağıdaki örnek belgedeki alt bilgi örneğinin Türkçe etiketli hâlidir:

typescript
<SidebarFooter>
  <SidebarMenu>
    <SidebarMenuItem>
      <DropdownMenu>
        <DropdownMenuTrigger asChild>
          <SidebarMenuButton>
            <User2 /> Kullanıcı adı
            <ChevronUp className="ml-auto" />
          </SidebarMenuButton>
        </DropdownMenuTrigger>
        <DropdownMenuContent
          side="top"
          className="w-[--radix-popper-anchor-width]"
        >
          <DropdownMenuItem>
            <span>Hesap</span>
          </DropdownMenuItem>
          <DropdownMenuItem>
            <span>Faturalandırma</span>
          </DropdownMenuItem>
          <DropdownMenuItem>
            <span>Çıkış yap</span>
          </DropdownMenuItem>
        </DropdownMenuContent>
      </DropdownMenu>
    </SidebarMenuItem>
  </SidebarMenu>
</SidebarFooter>

Açılır menünün kendisi, yani öğeler, onay kutulu öğeler ve alt menüler DropdownMenu, ContextMenu ve Menubar yazısında anlatılıyor. Bölümler arasına çizgi koymak için kaynakta Separator üzerine kurulu SidebarSeparator vardır; belge onu başlıkla içerik arasında ve iki grup arasında kullanır.

SidebarGroup: etiket, eylem ve içerik

SidebarGroup, kenar çubuğu içinde bir bölüm oluşturur. Belgeye göre bir grubun SidebarGroupLabel, SidebarGroupContent ve isteğe bağlı bir SidebarGroupAction parçası olur. Eylem düğmesi grubun sağ üst köşesine yerleşir; içindeki simgenin yanına ekran okuyucular için sr-only sınıflı bir metin koymanız gerekir, çünkü düğmede görünen tek şey simgedir.

typescript
<SidebarGroup>
  <SidebarGroupLabel>Projeler</SidebarGroupLabel>
  <SidebarGroupAction title="Proje ekle">
    <Plus /> <span className="sr-only">Proje ekle</span>
  </SidebarGroupAction>
  <SidebarGroupContent />
</SidebarGroup>

Kaynakta SidebarGroupLabel ve SidebarGroupAction için asChild desteği bulunur. Kenar çubuğu collapsible="icon" ile daraldığında etiket yukarı kayıp saydamlaşır, eylem düğmesi de tamamen gizlenir. Eylem düğmesinin mobilde tıklama alanı, görünmez bir sözde öğe ile büyütülür; bu ayrıntı kaynak koddaki bir yorumla açıklanır.

Açılır kapanır grup

Bir grubu daraltılabilir yapmak için onu Collapsible ile sararsınız. Belgedeki örnekte etiket asChild ile bir CollapsibleTrigger hâline getirilir; belgenin notuna göre bunun amacı tetikleyicinin bir düğme olarak render edilmesidir. Ok simgesi, group/collapsible adlı grup sınıfı ve data-state=open özniteliği sayesinde açıkken döner.

typescript
<Collapsible defaultOpen className="group/collapsible">
  <SidebarGroup>
    <SidebarGroupLabel asChild>
      <CollapsibleTrigger>
        Yardım
        <ChevronDown className="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-180" />
      </CollapsibleTrigger>
    </SidebarGroupLabel>
    <CollapsibleContent>
      <SidebarGroupContent />
    </CollapsibleContent>
  </SidebarGroup>
</Collapsible>

Collapsible bileşeninin kendisi Tabs, Accordion ve Collapsible yazısında ayrıca anlatılıyor.

SidebarMenu, SidebarMenuItem ve SidebarMenuButton

SidebarMenu, SidebarMenuItem ve SidebarMenuButton: variant, variant, size, size

SidebarMenu, bir grup içinde menü kurmak için kullanılır ve SidebarMenuItem, SidebarMenuButton, SidebarMenuAction ile SidebarMenuSub parçalarından oluşur. Kaynakta menü bir ul, öğe bir li olarak render edilir. SidebarMenuButton belgede üç başlıkla anlatılır: asChild ile bağlantıya dönüşmesi, simge ve etiket birlikte kullanımı, isActive ile etkin öğenin işaretlenmesi.

typescript
<SidebarMenuButton asChild isActive>
  <a href="#">
    <Home />
    <span>Ana sayfa</span>
  </a>
</SidebarMenuButton>

Belge etiketi bir span içine koymanızı hatırlatır; kaynaktaki stil son span öğesini kısaltarak uzun metinlerin taşmasını önler, simgeleri de sabit boyuta getirir. isActive verildiğinde düğme data-active="true" özniteliği alır ve vurgu rengiyle kalın yazılır. Kaynak ayrıca belgede tablo hâlinde verilmeyen iki cva varyantı tanımlar:

ÖzellikDeğerKaynaktaki etkisi
variantdefaultÜzerine gelince vurgu arka planı
variantoutlineArka plan rengi ve ince çerçeve gölgesi
sizedefaulth-8, text-sm
sizesmh-7, text-xs
sizelgh-12, text-sm; simge modunda iç boşluk sıfırlanır
isActivetrue / falsedata-active özniteliği ve vurgu stili
tooltipmetin veya TooltipContent özellikleriYalnızca kenar çubuğu daralmışken gösterilen ipucu

tooltip özelliği özellikle collapsible="icon" ile önemlidir. Kaynakta ipucu sağa doğru açılır ve kenar çubuğu daralmış değilse ya da mobildeyseniz gizlenir; yani yalnızca simgeler görünürken etiketi hatırlatır. Resmî sidebar-07 bloğu menü düğmelerine tooltip={item.title} vererek bu davranışı kullanır. Varyant mantığını kendi düğmelerinize uygulamak için cva ile bileşen özelleştirme yazısına bakabilirsiniz.

SidebarMenuAction: menü öğesine ikinci düğme

SidebarMenuAction: menü öğesine ikinci düğme

SidebarMenuAction, menü öğesinin içinde SidebarMenuButton düğmesinden bağımsız çalışan ikinci bir düğmedir. Belgenin vurguladığı nokta şu: ana düğme bir bağlantı olabilir, eylem düğmesi ise ayrı bir düğme olarak kalır; tıklamaları birbirine karışmaz. Tipik kullanım, belgedeki gibi üç nokta simgeli bir DropdownMenu açmaktır:

typescript
<SidebarMenuItem>
  <SidebarMenuButton asChild>
    <a href="#">
      <Home />
      <span>Ana sayfa</span>
    </a>
  </SidebarMenuButton>
  <DropdownMenu>
    <DropdownMenuTrigger asChild>
      <SidebarMenuAction>
        <MoreHorizontal />
      </SidebarMenuAction>
    </DropdownMenuTrigger>
    <DropdownMenuContent side="right" align="start">
      <DropdownMenuItem>
        <span>Projeyi düzenle</span>
      </DropdownMenuItem>
      <DropdownMenuItem>
        <span>Projeyi sil</span>
      </DropdownMenuItem>
    </DropdownMenuContent>
  </DropdownMenu>
</SidebarMenuItem>

Kaynakta SidebarMenuAction bileşeninin belgede anlatılmayan bir showOnHover özelliği de vardır. Bu özellik açıkken düğme orta ve büyük ekranlarda saydam başlar; öğenin üzerine gelindiğinde, öğe içinde odak olduğunda ya da açılır menü açıkken görünür olur. Eylem düğmesinin dikey konumu, yanındaki menü düğmesinin size değerine göre otomatik ayarlanır; menü düğmesi de öğede bir eylem düğmesi varsa sağ tarafta yer açar.

SidebarMenuSub ve açılır kapanır menü

Alt menü için SidebarMenuSub kullanılır; içindeki öğeler SidebarMenuSubItem ve SidebarMenuSubButton ile yazılır. Kaynakta dikkat çeken bir fark var: SidebarMenuSubButton varsayılan olarak button değil, a etiketi üretir. Boyut için sm ve md (varsayılan) değerlerini, etkin öğe için yine isActive özelliğini alır. Kenar çubuğu simgelere daraldığında alt menü tamamen gizlenir.

Menüyü açılır kapanır yapmak için belge, menü öğesini ve alt menüyü birlikte bir Collapsible ile sarmanızı söyler. Resmî sidebar-07 bloğundaki nav-main.tsx dosyası bu kalıbın tam hâlidir; aşağıda aynı yapıyı görüyorsunuz:

typescript
<SidebarMenu>
  {items.map((item) => (
    <Collapsible
      key={item.title}
      asChild
      defaultOpen={item.isActive}
      className="group/collapsible"
    >
      <SidebarMenuItem>
        <CollapsibleTrigger asChild>
          <SidebarMenuButton tooltip={item.title}>
            {item.icon && <item.icon />}
            <span>{item.title}</span>
            <ChevronRight className="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" />
          </SidebarMenuButton>
        </CollapsibleTrigger>
        <CollapsibleContent>
          <SidebarMenuSub>
            {item.items?.map((subItem) => (
              <SidebarMenuSubItem key={subItem.title}>
                <SidebarMenuSubButton asChild>
                  <a href={subItem.url}>
                    <span>{subItem.title}</span>
                  </a>
                </SidebarMenuSubButton>
              </SidebarMenuSubItem>
            ))}
          </SidebarMenuSub>
        </CollapsibleContent>
      </SidebarMenuItem>
    </Collapsible>
  ))}
</SidebarMenu>

Bu örnekte Collapsible bileşenine asChild verildiği için ekstra bir sarmalayıcı oluşmaz; li öğesi doğrudan açılır kapanır kök olur. defaultOpen={item.isActive} ise etkin bölümün sayfa açıldığında açık gelmesini sağlar. items dizisinin her elemanı blokta başlık, adres, isteğe bağlı simge, isActive ve alt öğeler listesi taşır.

Bloğun dosya düzeni de kendi projeniz için iyi bir örnektir. sidebar-07 klasöründe kenar çubuğu tek bir dosyada değil, parçalara bölünmüş hâlde durur: başlıktaki ekip seçici team-switcher.tsx, ana menü nav-main.tsx, proje listesi nav-projects.tsx, alt bilgideki kullanıcı menüsü nav-user.tsx dosyasındadır ve app-sidebar.tsx bunları SidebarHeader, SidebarContent ve SidebarFooter içine yerleştirip sona bir SidebarRail ekler. Her parça verisini özellik olarak alır; böylece menü içeriğini değiştirmek için yalnızca veri nesnesini güncellersiniz.

SidebarMenuBadge ve SidebarMenuSkeleton

SidebarMenuBadge, menü öğesinin sağında küçük bir sayaç ya da etiket gösterir. Kaynakta rozet tıklamaları yakalamaz, rakamları eşit genişlikte yazar ve simge modunda gizlenir. Kullanımı, düğmenin kardeşi olarak öğeye eklemekten ibarettir: SidebarMenuItem içinde önce SidebarMenuButton, sonra SidebarMenuBadge gelir.

SidebarMenuSkeleton, menü verisi gelirken gösterilecek yükleme iskeletidir. Belge bunu React Server Components, SWR ya da react-query ile veri çekerken kullanmanızı önerir. Kaynağa göre her iskelet satırının metin genişliği yüzde 50 ile 90 arasında rastgele seçilir, böylece satırlar birbirinin aynısı görünmez; showIcon verirseniz başına küçük bir simge kutusu da eklenir. Genel Skeleton bileşeni Alert, Badge, Progress, Skeleton ve Spinner yazısında.

Veri çekme: Server Components ve Suspense

Belgenin veri çekme bölümü üç parçalı bir örnek verir: iskeleti gösteren bir bileşen, veriyi await ile çeken bir sunucu bileşeni ve ikisini React.Suspense ile birleştiren kenar çubuğu. fetchProjects belgede de bir yer tutucudur; kendi veri katmanınızla değiştirirsiniz.

typescript
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>Projeler</SidebarGroupLabel>
          <SidebarGroupContent>
            <React.Suspense fallback={<NavProjectsSkeleton />}>
              <NavProjects />
            </React.Suspense>
          </SidebarGroupContent>
        </SidebarGroup>
      </SidebarContent>
    </Sidebar>
  )
}

Aynı yaklaşımı SWR ya da react-query ile de kurabilirsiniz. Belgedeki istemci tarafı örneklerinde kanca data ve isLoading döndürür; isLoading doğruyken aynı iskelet listesi, veri gelince menü render edilir. Sunucu bileşenleri ve Suspense kavramları için Next.js App Router ve React ile modern web uygulaması yazılarına bakabilirsiniz.

SidebarTrigger, SidebarRail ve kontrollü sidebar

SidebarTrigger kenar çubuğunu açıp kapatan hazır düğmedir ve belgeye göre SidebarProvider içinde kullanılmalıdır. SidebarRail ise kenar çubuğunun kenarına yerleşen ince bir şerittir ve tıklanınca kenar çubuğunu açıp kapatır. Kaynakta şerit aria-label="Toggle Sidebar" taşır ama tabIndex={-1} ile klavye sırasından çıkarılmıştır; yani klavye kullanıcıları için asıl yol SidebarTrigger ya da kısayoldur. Belgede şerit, Sidebar içinde SidebarFooter bileşeninden sonra eklenir.

Durumu tamamen kendiniz yönetmek istiyorsanız SidebarProvider bileşenine open ve onOpenChange verirsiniz. Belgedeki kontrollü örnek şöyledir:

typescript
export function AppSidebar() {
  const [open, setOpen] = React.useState(false)

  return (
    <SidebarProvider open={open} onOpenChange={setOpen}>
      <Sidebar />
    </SidebarProvider>
  )
}

Kaynak kodda setOpen hem kontrollü hem kontrolsüz kullanımda sidebar_state çerezini yazar; yani durumu dışarıdan yönetseniz de çerez güncellenmeye devam eder. Bu davranış belgenin değişiklik geçmişinde 30 Ekim 2024 tarihli "Cookie handling in setOpen" kaydıyla gelmiştir ve kayıt, eski dosyası olanların setOpen geri çağırmasını yeni hâliyle güncellemesini ister. Kontrollü kullanımın yalnızca masaüstü open durumunu kapsadığını unutmayın; mobildeki openMobile ayrı tutulur.

Tema değişkenleri ve duruma göre stil

Belge kenar çubuğu için uygulamanın geri kalanından bilinçli olarak ayrı CSS değişkenleri kullandığını söyler; amaç, örneğin ana sayfadan daha koyu tonda bir kenar çubuğunu kolayca yapabilmektir. Değişkenler arka plan, ön plan, birincil renk, vurgu rengi, kenarlık ve odak halkası için açık ve koyu temada ayrı ayrı tanımlanır. Belgenin Theming bölümündeki örnek hâlâ eski HSL biçimini ve --sidebar-background adını gösterir; kurulum adımı ve genel tema sayfası ise oklch değerleri ve --sidebar adını kullanır. Yeni bir projede kurulum adımındaki listeyi izlemek daha tutarlıdır.

Duruma göre stil vermek için belge iki ipucu verir. İlki, kenar çubuğu simge modundayken bir grubu gizlemektir: group-data-[collapsible=icon]:hidden sınıfı, sarmalayıcıdaki data-collapsible özniteliğine bakar. İkincisi, menü düğmesi etkinken eylem düğmesini görünür kılmaktır; burada peer-data-[active=true]/menu-button:opacity-100 sınıfı düğmenin data-active özniteliğini okur.

typescript
<Sidebar collapsible="icon">
  <SidebarContent>
    <SidebarGroup className="group-data-[collapsible=icon]:hidden" />
  </SidebarContent>
</Sidebar>

<SidebarMenuItem>
  <SidebarMenuButton />
  <SidebarMenuAction className="peer-data-[active=true]/menu-button:opacity-100" />
</SidebarMenuItem>

Bu sınıfların Tailwind tarafındaki genel sözdizimi (grup ve kardeş varyantları) Tailwind'in konusudur; Tailwind CSS rehberinde temelleri bulabilirsiniz. Kaynakta belgede ayrı bölümü olmayan bir SidebarInput bileşeni de dışa aktarılır; kenar çubuğu içinde arama kutusu gibi kullanılmak üzere Input bileşenini küçük bir yükseklikle sarar.

Sık yapılan hatalar

Sık yapılan hatalar: Etiketi span'a koymamak, Simge modunda kaybolan öğelere şaşırmak, Simge düğmesinde erişilebilir ad bırakmamak, Alt menü düğmesini button sanmak
  • Etiketi span'a koymamak: Metni doğrudan a içine yazarsanız kısaltma stili çalışmaz ve uzun adlar taşar.
  • Simge modunda kaybolan öğelere şaşırmak: Kaynakta grup etiketi, grup eylemi, menü eylemi, rozet ve alt menü collapsible="icon" daralmasında gizlenir. Daralmış hâlde bilgi vermek için menü düğmesine tooltip verin.
  • Simge düğmesinde erişilebilir ad bırakmamak: SidebarGroupAction ve SidebarMenuAction yalnızca simge gösterir; belgedeki gibi sr-only metin ekleyin. Erişilebilir adlar için ARIA yazısına bakın.
  • Alt menü düğmesini button sanmak: SidebarMenuSubButton varsayılan olarak a üretir; bir işlem çalıştıracaksanız asChild ile kendi button öğenizi verin.
  • Kontrollü modda mobili unutmak: open yalnızca masaüstü durumudur; mobil paneli useSidebar içindeki setOpenMobile ile yönetirsiniz.
  • Collapsible için grup adını vermemek: Ok simgesinin dönmesi group/collapsible sınıfına bağlıdır; sınıfı Collapsible üzerine eklemeyi unutursanız group-data-[state=open]/collapsible hiçbir şey yapmaz.

Sık Sorulan Sorular

Etkin menü öğesini nasıl işaretlerim?

SidebarMenuButton bileşenine isActive verin. Hangi öğenin etkin olduğunu belirlemek, yani geçerli adresle karşılaştırmak sizin yönlendirme kodunuzun işidir; bileşen yalnızca data-active özniteliğini ve stili uygular.

Next.js Link ile kullanabilir miyim?

Evet. asChild sayesinde SidebarMenuButton stilini içine koyduğunuz bileşene aktarır; belge bunun bir Link ya da a etiketi olabileceğini söyler.

Menü verisini sunucudan çekerken ne göstermeliyim?

Belgedeki gibi SidebarMenuSkeleton satırlarından oluşan bir iskelet bileşeni yazıp React.Suspense için fallback olarak verin ya da istemci tarafı kancanın isLoading değerine göre gösterin.

Rozet ile eylem düğmesini aynı öğede kullanabilir miyim?

Kaynakta ikisi de öğenin sağ tarafına mutlak konumla yerleşir. Belge ikisini birlikte gösteren bir örnek vermez; birlikte kullanacaksanız konumlarını kendi sınıflarınızla ayarlamanız gerekir.

Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.

İlgili içerikler: shadcn/ui öğrenme rehberi · Sidebar kurulumu ve yapısı · DropdownMenu ve ContextMenu · Tabs, Accordion ve Collapsible · Skeleton ve diğer geri bildirim bileşenleri · Tema ve CSS değişkenleri