Ir al contenido
NavegaciónServer Component

Breadcrumb

Dónde estoy en la jerarquía del sitio: <nav> + <ol>, con el medio colapsable en «…».

import { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, … } from "sebs7n-ui/breadcrumb"

Ejemplos

Una página de detalle

Los separadores los pone `BreadcrumbList`. El último nivel no es link: lleva `aria-current="page"`.

import Link from "next/link"
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage } from "sebs7n-ui/breadcrumb"

function Basico() {
  return (
    <Breadcrumb>
      <BreadcrumbList>
        <BreadcrumbItem>
          <BreadcrumbLink render={<Link href="/docs" />}>Inicio</BreadcrumbLink>
        </BreadcrumbItem>
        <BreadcrumbItem>
          <BreadcrumbLink render={<Link href="/docs/components/table" />}>Clientes</BreadcrumbLink>
        </BreadcrumbItem>
        <BreadcrumbItem>
          <BreadcrumbPage>Acme S.A.</BreadcrumbPage>
        </BreadcrumbItem>
      </BreadcrumbList>
    </Breadcrumb>
  )
}

Muchos niveles: colapsar el medio

`maxItems={4}` deja el primero, un «…» con nombre accesible y los dos últimos.

import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage } from "sebs7n-ui/breadcrumb"

function Colapsado() {
  return (
    <Breadcrumb>
      <BreadcrumbList maxItems={4}>
        <BreadcrumbItem>
          <BreadcrumbLink href="#">Inicio</BreadcrumbLink>
        </BreadcrumbItem>
        <BreadcrumbItem>
          <BreadcrumbLink href="#">Clientes</BreadcrumbLink>
        </BreadcrumbItem>
        <BreadcrumbItem>
          <BreadcrumbLink href="#">Acme S.A.</BreadcrumbLink>
        </BreadcrumbItem>
        <BreadcrumbItem>
          <BreadcrumbLink href="#">Facturas</BreadcrumbLink>
        </BreadcrumbItem>
        <BreadcrumbItem>
          <BreadcrumbPage>0012</BreadcrumbPage>
        </BreadcrumbItem>
      </BreadcrumbList>
    </Breadcrumb>
  )
}

Dentro de un PageHeader

Acá va `BreadcrumbList` **suelto**: el `<nav>` ya lo pone la prop `breadcrumb`.

import { BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage } from "sebs7n-ui/breadcrumb"
import { PageHeader, PageHeaderTitle } from "sebs7n-ui/page-header"
import { SlashIcon } from "lucide-react"

function EnPageHeader() {
  return (
    <PageHeader
      breadcrumb={
        <BreadcrumbList separator={<SlashIcon />}>
          <BreadcrumbItem>
            <BreadcrumbLink href="#">Facturas</BreadcrumbLink>
          </BreadcrumbItem>
          <BreadcrumbItem>
            <BreadcrumbPage>0012</BreadcrumbPage>
          </BreadcrumbItem>
        </BreadcrumbList>
      }
    >
      <PageHeaderTitle>Factura 0012</PageHeaderTitle>
    </PageHeader>
  )
}

Props

Generadas del TypeScript del paquete. Las propias del componente, más las heredadas del primitivo que tienen algo que explicar —marcadas «heredada de Base UI»—. El resto está en la línea «hereda de».

Breadcrumb

Hereda las props de <nav>.

PropTipoPor defectoDescripción
aria-labelstring"Migas de pan"Nombre accesible del elemento.
classNamestring—Se fusiona con las clases del componente vía cn() (tailwind-merge): lo que pongas gana.

BreadcrumbEllipsis

Hereda las props de <li>.

PropTipoPor defectoDescripción
labelstring"Rutas intermedias"Nombre accesible: el «…» en sí es decoración.
classNamestring—Se fusiona con las clases del componente vía cn() (tailwind-merge): lo que pongas gana.

BreadcrumbItem

Hereda las props de <li>.

PropTipoPor defectoDescripción
classNamestring—Se fusiona con las clases del componente vía cn() (tailwind-merge): lo que pongas gana.

Hereda las props de <a>.

PropTipoPor defectoDescripción
renderRenderElement—El elemento que se renderiza en lugar del <a>: render={<Link href="/x" />}. Clona el elemento del llamador —no es el render de Base UI— así que sigue siendo un <a>.
classNamestring—Se fusiona con las clases del componente vía cn() (tailwind-merge): lo que pongas gana.

BreadcrumbList

Hereda las props de <ol>.

PropTipoPor defectoDescripción
ellipsisLabelstring"Rutas intermedias"Nombre accesible del «…».
itemsAfternumber2Cuántos ítems quedan después del «…». El último es la página actual.
itemsBeforenumber1Cuántos ítems quedan antes del «…».
maxItemsnumber—A partir de cuántos ítems se colapsa el medio. Sin valor, no colapsa nunca. El «…» además tiene que tapar dos o más ítems, así que con maxItems={4} el colapso arranca recién en el quinto nivel.
separatorReact.ReactNode—Reemplaza el chevron. Es decoración: va aria-hidden.
classNamestring—Se fusiona con las clases del componente vía cn() (tailwind-merge): lo que pongas gana.

BreadcrumbPage

Hereda las props de <span>.

PropTipoPor defectoDescripción
classNamestring—Se fusiona con las clases del componente vía cn() (tailwind-merge): lo que pongas gana.

BreadcrumbSeparator

Hereda las props de <li>.

PropTipoPor defectoDescripción
classNamestring—Se fusiona con las clases del componente vía cn() (tailwind-merge): lo que pongas gana.

Teclado

Tab
Recorre los links. El último nivel no es link, así que no entra al orden de tabulación.
Enter
Navega.

Accesibilidad

  • Es un <nav aria-label="Migas de pan"> con un <ol> adentro: el orden de los niveles es información, no estilo.
  • El separador es un <li role="presentation" aria-hidden="true">: el lector lee «Inicio, Clientes, 0012», no «Inicio barra Clientes».
  • El último nivel lleva aria-current="page" y no es un link: no se navega a donde ya estás.
  • El «…» del colapso tiene nombre accesible (ellipsisLabel); el carácter en sí es aria-hidden.
  • Sin "use client": los <a> salen en el HTML del server, que es lo que ve un crawler.

Reglas de uso

  • Dentro de `PageHeader` va `BreadcrumbList` suelto, sin Breadcrumb: el <nav> ya lo pone la prop breadcrumb, y dos landmarks anidados confunden. Si igual lo envolvés, PageHeader avisa por consola en desarrollo.
  • Los separadores los pone `BreadcrumbList`, no el llamador. Para cambiarlos, separator={<SlashIcon />}.
  • No inventes otro estilo de link: usa linkVariants({ variant: "subtle" }), el mismo de cualquier link suelto del sistema.
  • Con Next, render={<Link href="/clientes" />}: sigue siendo un <a>, se abre en una pestaña nueva y el crawler lo ve.
  • De cuatro niveles para arriba, maxItems={4}. En mobile un breadcrumb de seis niveles ocupa tres líneas.
  • No es un reemplazo del botón «Volver» del navegador ni de la navegación principal: es contexto.

Relacionados