shadcn/ui gezinme için üç ayrı bileşen sunar: üst menüde açılır panelli bağlantılar için NavigationMenu, kullanıcının sitede nerede olduğunu gösteren yol için Breadcrumb ve uzun listeleri sayfalara bölen Pagination. Üçü de npx shadcn@latest add ile ayrı ayrı eklenir, bağlantı bileşeninizi (next/link gibi) içlerine asChild ya da küçük bir kod değişikliğiyle bağlarsınız. Navigation Menu Radix UI üzerine kuruludur; Breadcrumb ve Pagination ise düz HTML ve shadcn'in kendi stilleriyle yazılmıştır.

Bu yazıda her bileşeni ayrı başlık altında, belgedeki örnekler ve kaynak koddaki erişilebilirlik öznitelikleriyle birlikte görüyorsunuz. Uygulama içi yan menü için Sidebar, tablo verisini sayfalamak için Data Table sıralama, filtreleme ve sayfalama yazısına bakın. Serinin tamamı shadcn/ui öğrenme rehberi sayfasında.

Pagination: sayfa numaraları, önceki ve sonraki

Pagination, sayfa gezinmesini önceki ve sonraki bağlantılarıyla birlikte sunar. Sürüm geçmişine göre Aralık 2023'te eklendi ve çerçevenizin Link bileşeniyle çalışacak şekilde basit tutuldu. CLI komutu npx shadcn@latest add pagination şeklindedir; kaynakta görsel stil için button bileşeninin buttonVariants işlevi kullanılır.

typescript
<Pagination>
  <PaginationContent>
    <PaginationItem>
      <PaginationPrevious href="#" />
    </PaginationItem>
    <PaginationItem>
      <PaginationLink href="#">1</PaginationLink>
    </PaginationItem>
    <PaginationItem>
      <PaginationLink href="#" isActive>
        2
      </PaginationLink>
    </PaginationItem>
    <PaginationItem>
      <PaginationLink href="#">3</PaginationLink>
    </PaginationItem>
    <PaginationItem>
      <PaginationEllipsis />
    </PaginationItem>
    <PaginationItem>
      <PaginationNext href="#" />
    </PaginationItem>
  </PaginationContent>
</Pagination>

Kaynaktaki davranışlar şöyle: dış kap role="navigation" ve aria-label="pagination" taşıyan bir nav öğesidir. PaginationLink bir a etiketi üretir; isActive verildiğinde aria-current="page" alır ve outline buton görünümüne geçer, değilse ghost görünümünde kalır. Varsayılan boyutu icon olduğu için sayfa numaraları kare düğmeler hâlinde görünür. PaginationPrevious ve PaginationNext sırasıyla Go to previous page ve Go to next page erişilebilir etiketlerini taşır; içlerindeki Previous ve Next yazıları küçük ekranlarda gizlenip yalnızca ok simgesi kalır. PaginationEllipsis ise ekran okuyucular için gizli More pages metni içerir.

Metinleri Türkçeleştirmek

Bu İngilizce metinler bir özellikle değil, doğrudan kaynak kodla gelir. Kod projenizde olduğu için components/ui/pagination.tsx dosyasını açıp metinleri değiştirebilirsiniz. Aşağıdaki hâl, kaynaktaki PaginationPrevious bileşeninin yapısını koruyup yalnızca metni ve etiketi Türkçeleştirir:

typescript
function PaginationPrevious({
  className,
  ...props
}: React.ComponentProps<typeof PaginationLink>) {
  return (
    <PaginationLink
      aria-label="Önceki sayfaya git"
      size="default"
      className={cn("gap-1 px-2.5 sm:pl-2.5", className)}
      {...props}
    >
      <ChevronLeftIcon />
      <span className="hidden sm:block">Önceki</span>
    </PaginationLink>
  )
}

Next.js Link ile kullanmak

Belgeye göre PaginationLink varsayılan olarak bir a etiketi render eder. Next.js Link bileşenini kullanmak için pagination.tsx içinde üç değişiklik yaparsınız: next/link içe aktarılır, PaginationLinkProps tipindeki React.ComponentProps<"a"> kısmı React.ComponentProps<typeof Link> ile değiştirilir ve render edilen a etiketi Link olur. Belgedeki fark gösterimi şu şekildedir:

typescript
+ import Link from "next/link"

- type PaginationLinkProps = ... & React.ComponentProps<"a">
+ type PaginationLinkProps = ... & React.ComponentProps<typeof Link>

const PaginationLink = ({...props }: ) => (
  <PaginationItem>
-   <a>
+   <Link>
      // ...
-   </a>
+   </Link>
  </PaginationItem>
)

Belgedeki not, CLI'nin bu değişikliği ileride otomatik yapması için çalışıldığını söyler; depo kopyası 19 Aralık 2025 tarihlidir ve bu tarihte belge hâlâ elle değişikliği tarif eder. Sayfa numaralarını hangi verilere göre üreteceğiniz, kaç numara göstereceğiniz ve üç noktayı nereye koyacağınız tamamen sizin mantığınızdır; bileşen yalnızca görünümü ve erişilebilirlik özniteliklerini sağlar.

Mini örnek: blog arşivinde breadcrumb ve sayfalama

İki bileşeni birlikte kullanan küçük bir arşiv gezinmesi düşünelim: üstte "Ana sayfa, Blog, Sayfa 3" yolu, altta sayfa numaraları. Aşağıdaki bileşen yalnızca belgede gösterilen parçaları ve özellikleri kullanır; sayfa numaralarını üretme mantığı ise bizim yazdığımız sade bir dizi işlemidir. Bileşen sayfa ve toplam değerlerini dışarıdan alır.

typescript
import Link from "next/link"

import {
  Breadcrumb,
  BreadcrumbItem,
  BreadcrumbLink,
  BreadcrumbList,
  BreadcrumbPage,
  BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
import {
  Pagination,
  PaginationContent,
  PaginationItem,
  PaginationLink,
  PaginationNext,
  PaginationPrevious,
} from "@/components/ui/pagination"

export function ArsivGezinmesi({ sayfa, toplam }: { sayfa: number; toplam: number }) {
  const numaralar = Array.from({ length: toplam }, (_, i) => i + 1)

  return (
    <div className="flex flex-col gap-6">
      <Breadcrumb>
        <BreadcrumbList>
          <BreadcrumbItem>
            <BreadcrumbLink asChild>
              <Link href="/">Ana sayfa</Link>
            </BreadcrumbLink>
          </BreadcrumbItem>
          <BreadcrumbSeparator />
          <BreadcrumbItem>
            <BreadcrumbLink asChild>
              <Link href="/blog">Blog</Link>
            </BreadcrumbLink>
          </BreadcrumbItem>
          <BreadcrumbSeparator />
          <BreadcrumbItem>
            <BreadcrumbPage>Sayfa {sayfa}</BreadcrumbPage>
          </BreadcrumbItem>
        </BreadcrumbList>
      </Breadcrumb>

      {/* ... yazı listesi ... */}

      <Pagination>
        <PaginationContent>
          {sayfa > 1 && (
            <PaginationItem>
              <PaginationPrevious href={`/blog?sayfa=${sayfa - 1}`} />
            </PaginationItem>
          )}
          {numaralar.map((n) => (
            <PaginationItem key={n}>
              <PaginationLink href={`/blog?sayfa=${n}`} isActive={n === sayfa}>
                {n}
              </PaginationLink>
            </PaginationItem>
          ))}
          {sayfa < toplam && (
            <PaginationItem>
              <PaginationNext href={`/blog?sayfa=${sayfa + 1}`} />
            </PaginationItem>
          )}
        </PaginationContent>
      </Pagination>
    </div>
  )
}

Bu örnekte üç karar var. Birincisi, önceki ve sonraki bağlantıları koşullu render ediyoruz; kaynakta PaginationPrevious ve PaginationNext birer a etiketidir ve devre dışı bırakma özelliği yoktur, bu yüzden ilk sayfada "sayfa 0" adresine giden bir bağlantı üretmemek sizin sorumluluğunuzdadır. İkincisi, etkin numarayı isActive={n === sayfa} ile işaretliyoruz; bileşen bunun karşılığında aria-current="page" ve outline görünümünü uygular. Üçüncüsü, breadcrumb bağlantılarında next/link kullanırken pagination tarafında düz href kullanıyoruz; Pagination'da da istemci tarafı gezinme istiyorsanız yukarıda anlatılan pagination.tsx değişikliğini yapmanız gerekir. Sayfa sayısı büyüdüğünde tüm numaraları basmak yerine yalnızca çevredeki birkaç numarayı gösterip aralara PaginationEllipsis koyabilirsiniz; hangi numaraların görüneceği yine sizin mantığınızdır.

Hangisini ne zaman kullanmalı?

Hangisini ne zaman kullanmalı? Navigation Menu, Breadcrumb, Pagination
BileşenTipik yerDayandığı yapıKurulum komutu
Navigation MenuSite üst menüsü, açılır panellerRadix Navigation Menunpx shadcn@latest add navigation-menu
BreadcrumbSayfa başlığının üstündeki konum yolunav, ol, li ve Slotnpx shadcn@latest add breadcrumb
PaginationListe, arşiv ve arama sonuçlarının altınav, ul ve buttonVariantsnpx shadcn@latest add pagination

Bu üç bileşen sıklıkla birlikte görünür. Örneğin resmî sidebar-07 bloğunun üst çubuğunda SidebarTrigger, dikey bir Separator ve bir Breadcrumb yan yana durur; ilk adım hidden md:block sınıfıyla mobilde gizlenir. Ayırıcının kendisi Card, Separator ve Scroll Area yazısında anlatılıyor.

Sık yapılan hatalar

  • Son adımı bağlantı yapmak: Geçerli sayfa için BreadcrumbLink yerine BreadcrumbPage kullanın; doğru aria-current değeri ancak böyle gelir.
  • Üç noktayı tek başına tıklanabilir sanmak: BreadcrumbEllipsis kaynakta aria-hidden taşıyan bir span öğesidir, kendi başına düğme değildir. Gizli adımları açtırmak için belgedeki gibi onu DropdownMenuTrigger içine koyun; duyarlı örnek tetikleyiciye ayrıca aria-label="Toggle menu" verir.
  • Router Link'i asChild olmadan sarmak: BreadcrumbLink içine asChild vermeden Link koyarsanız bir a içinde ikinci bir a oluşur. NavigationMenuLink için de aynı kural geçerlidir.
  • Pagination'ı Next.js Link ile kullanmak için yalnızca href vermek: Bileşen a ürettiği için tam sayfa gezinmesi olur; belgedeki değişikliği pagination.tsx içinde yapın.
  • Panel genişliğini bileşenden beklemek: NavigationMenuContent içindeki düzen ve genişlik sizin sınıflarınıza bağlıdır; demo içerik listelerine md:w-[400px] lg:w-[500px] ya da w-[300px] gibi açık genişlikler verir.
  • Duyarlı breadcrumb örneğini olduğu gibi kopyalamak: Örnekteki @/hooks/use-media-query yolu sitenin kendi koduna aittir; projenizde bu dosya yoksa içe aktarma başarısız olur.

Sık Sorulan Sorular

Navigation Menu mobilde nasıl davranır?

Belge ayrı bir mobil tasarım vermez. Demo, viewport={isMobile} ile ortak görüntü alanını mobilde açar ve bazı öğeleri hidden md:block ile küçük ekranda gizler. Mobilde tamamen farklı bir menü istiyorsanız Sheet ya da Sidebar ile ayrı bir çözüm kurmanız daha uygundur.

Breadcrumb için ayrı bir Radix bileşeni kurmam gerekir mi?

Hayır. Belgedeki elle kurulum adımı yalnızca dosyayı kopyalamayı ve içe aktarma yollarını düzeltmeyi ister. Depodaki kayıt tanımında tek npm bağımlılığı asChild için kullanılan @radix-ui/react-slot paketidir; simgeler lucide-react paketinden gelir. CLI ile kurduğunuzda bu bağımlılık sizin için çözülür.

Pagination sayfa numaralarını kendisi hesaplar mı?

Hayır. Bileşen yalnızca sunum katmanıdır. Toplam sayfa sayısı, etkin sayfa ve hangi numaraların gösterileceği sizin kodunuzda hesaplanır; etkin numaraya isActive verirsiniz.

Breadcrumb ile Sidebar birlikte nasıl kullanılır?

Resmî sidebar-07 bloğu iyi bir örnektir: SidebarInset içindeki üst çubukta SidebarTrigger, dikey bir Separator ve Breadcrumb yan yana durur. Breadcrumb'ın ilk adımı ve ilk ayırıcısı hidden md:block ile mobilde gizlenir, böylece dar ekranda yalnızca geçerli sayfa adı görünür.

Önceki ve Sonraki yazılarını nasıl değiştiririm?

components/ui/pagination.tsx dosyasındaki metinleri ve aria-label değerlerini doğrudan düzenleyin. Kod sizin olduğu için bu, kütüphaneyi çatallamak anlamına gelmez; yalnızca kendi dosyanızı değiştirirsiniz.

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 · DropdownMenu ve Menubar · Sheet ve Drawer · Data Table sayfalama · HTML ARIA nedir