{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "breadcrumb",
  "type": "registry:ui",
  "title": "Breadcrumb",
  "description": "@interlace/ui — breadcrumb primitive (shadcn-compatible).",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "theme"
  ],
  "files": [
    {
      "path": "registry/interlace-ui/breadcrumb.tsx",
      "target": "components/ui/breadcrumb.tsx",
      "type": "registry:ui",
      "content": "// Breadcrumb — server-rendered, semantically-tagged trail of ancestor links.\n// Compositional API (Breadcrumb / BreadcrumbList / BreadcrumbItem /\n// BreadcrumbLink / BreadcrumbSeparator / BreadcrumbPage / BreadcrumbEllipsis)\n// mirrors the shadcn surface so consumers swap drop-in. BreadcrumbLink keeps a\n// server-safe `asChild` seam (React.cloneElement, NOT Base UI useRender) so the\n// whole tree stays an RSC — composes with `next/link` without forcing a client\n// boundary. MIN_VIEWPORT=480 because long trails overflow on <480 phones; below\n// it, consumers should collapse with BreadcrumbEllipsis.\n\n/**\n * @interlace/ui — Breadcrumb\n *\n * Anatomy:\n *   Breadcrumb (nav[aria-label=\"breadcrumb\"], data-min-viewport)\n *     └─ BreadcrumbList (ol)\n *         ├─ BreadcrumbItem (li)\n *         │   └─ BreadcrumbLink (a, or asChild = cloned child)\n *         ├─ BreadcrumbSeparator (li[role=\"presentation\"] · ChevronRight)\n *         ├─ BreadcrumbItem\n *         │   └─ BreadcrumbPage (span[aria-current=\"page\"])\n *         └─ BreadcrumbEllipsis (span · MoreHorizontal + sr-only \"More\")\n *\n * | Rule | Concept                          | Where in this file                                   |\n * | ---- | -------------------------------- | ---------------------------------------------------- |\n * | R4   | Extends native els               | Every part extends `React.ComponentProps<'…'>`       |\n * | R6   | data-slot on every part          | data-slot=\"breadcrumb\" / \"-list\" / \"-item\" / …       |\n * | R7   | className merged + ...rest       | `cn(BASE, className)` + `{...props}` on every part   |\n * | R10  | Composition seam                 | BreadcrumbLink accepts `asChild` (server-safe slot)  |\n * | R13  | Ecosystem first                  | Lucide icons (ChevronRight / MoreHorizontal)         |\n * | R18  | Tailwind only                    | Zero inline style                                    |\n * | R19  | Tokens only                      | gap-xs / text-ui-sm / text-muted-foreground / size-4 |\n * | R20  | AA contrast                      | foreground vs muted-foreground; AA-cleared tokens    |\n * | R25  | Server component                 | No hooks → no 'use client'                           |\n * | R26  | A11y from native els             | `nav` + ordered list + `aria-current` + role         |\n *\n * MIN_VIEWPORT=480 rationale: a 3-segment trail with 24-32ch labels collapses\n * onto the next line under ~480px. Below that, the consumer is expected to\n * either truncate via `lineClamp` on the link text or collapse with\n * `<BreadcrumbEllipsis />` between the first and last items.\n */\n\nimport * as React from 'react';\nimport { ChevronRight, MoreHorizontal } from 'lucide-react';\n\nimport { cn } from '@/lib/utils';\n\n/** Minimum viable viewport width (px). Exposed so consumers can mirror it. */\nexport const MIN_VIEWPORT = 480;\n\n// ─────────────────────────────────────────────────────────────────\n// Breadcrumb (root <nav>)\n// ─────────────────────────────────────────────────────────────────\ninterface BreadcrumbProps extends React.ComponentProps<'nav'> {}\n\nconst Breadcrumb = React.forwardRef<HTMLElement, BreadcrumbProps>(\n  ({ className, ...props }, ref) => {\n    return (\n      <nav\n        ref={ref}\n        aria-label=\"breadcrumb\"\n        data-slot=\"breadcrumb\"\n        data-min-viewport={String(MIN_VIEWPORT)}\n        className={cn(className)}\n        {...props}\n      />\n    );\n  },\n);\nBreadcrumb.displayName = 'Breadcrumb';\n\n// ─────────────────────────────────────────────────────────────────\n// BreadcrumbList (<ol>)\n// ─────────────────────────────────────────────────────────────────\ninterface BreadcrumbListProps extends React.ComponentProps<'ol'> {}\n\nconst BreadcrumbList = React.forwardRef<HTMLOListElement, BreadcrumbListProps>(\n  ({ className, ...props }, ref) => {\n    return (\n      <ol\n        ref={ref}\n        data-slot=\"breadcrumb-list\"\n        className={cn(\n          'text-muted-foreground flex flex-wrap items-center gap-xs text-ui-sm break-words',\n          className,\n        )}\n        {...props}\n      />\n    );\n  },\n);\nBreadcrumbList.displayName = 'BreadcrumbList';\n\n// ─────────────────────────────────────────────────────────────────\n// BreadcrumbItem (<li>)\n// ─────────────────────────────────────────────────────────────────\ninterface BreadcrumbItemProps extends React.ComponentProps<'li'> {}\n\nconst BreadcrumbItem = React.forwardRef<HTMLLIElement, BreadcrumbItemProps>(\n  ({ className, ...props }, ref) => {\n    return (\n      <li\n        ref={ref}\n        data-slot=\"breadcrumb-item\"\n        className={cn('inline-flex items-center gap-1', className)}\n        {...props}\n      />\n    );\n  },\n);\nBreadcrumbItem.displayName = 'BreadcrumbItem';\n\n// ─────────────────────────────────────────────────────────────────\n// BreadcrumbLink (<a>, or cloned child when asChild)\n// ─────────────────────────────────────────────────────────────────\ntype BreadcrumbLinkProps = React.ComponentProps<'a'> & {\n  /**\n   * Render as the passed child element (e.g. `<Link href=\"…\">`) — useful when\n   * composing with a routing primitive. Server-safe slot: we `cloneElement`\n   * the single React element child and merge our data-slot + className onto\n   * it. NOT Base UI useRender (which would flip this tree to client).\n   */\n  asChild?: boolean;\n};\n\nconst BreadcrumbLink = React.forwardRef<HTMLAnchorElement, BreadcrumbLinkProps>(\n  ({ asChild, className, children, ...props }, ref) => {\n    const baseClass = cn('hover:text-foreground transition-colors', className);\n\n    if (asChild && React.isValidElement(children)) {\n      const child = children as React.ReactElement<{\n        className?: string;\n      }>;\n      return React.cloneElement(child, {\n        ...props,\n        ...child.props,\n        ref,\n        'data-slot': 'breadcrumb-link',\n        className: cn(baseClass, child.props.className),\n      } as React.HTMLAttributes<HTMLElement>);\n    }\n\n    return (\n      // href is supplied by the consumer via {...props} (this primitive is\n      // a bare navigable link); the rule can't see through the spread.\n      // eslint-disable-next-line react-a11y/anchor-is-valid\n      <a ref={ref} data-slot=\"breadcrumb-link\" className={baseClass} {...props}>\n        {children}\n      </a>\n    );\n  },\n);\nBreadcrumbLink.displayName = 'BreadcrumbLink';\n\n// ─────────────────────────────────────────────────────────────────\n// BreadcrumbPage (<span aria-current=\"page\">) — the current node.\n// ─────────────────────────────────────────────────────────────────\ninterface BreadcrumbPageProps extends React.ComponentProps<'span'> {}\n\nconst BreadcrumbPage = React.forwardRef<HTMLSpanElement, BreadcrumbPageProps>(\n  ({ className, ...props }, ref) => {\n    return (\n      // No role=\"link\" — the WAI-ARIA APG breadcrumb pattern treats the\n      // current page as plain text, not a disabled link (ARIA doesn't\n      // define a real \"disabled link\" semantic; aria-current=\"page\" is\n      // the correct and sufficient signal here).\n      <span\n        ref={ref}\n        aria-current=\"page\"\n        data-slot=\"breadcrumb-page\"\n        className={cn('text-foreground font-medium', className)}\n        {...props}\n      />\n    );\n  },\n);\nBreadcrumbPage.displayName = 'BreadcrumbPage';\n\n// ─────────────────────────────────────────────────────────────────\n// BreadcrumbSeparator (<li role=\"presentation\">) — decorative chevron.\n// ─────────────────────────────────────────────────────────────────\ninterface BreadcrumbSeparatorProps extends React.ComponentProps<'li'> {}\n\nconst BreadcrumbSeparator = React.forwardRef<\n  HTMLLIElement,\n  BreadcrumbSeparatorProps\n>(({ className, children, ...props }, ref) => {\n  return (\n    <li\n      ref={ref}\n      role=\"presentation\"\n      aria-hidden=\"true\"\n      data-slot=\"breadcrumb-separator\"\n      className={cn(\n        'text-muted-foreground inline-flex items-center [&>svg]:size-4',\n        className,\n      )}\n      {...props}\n    >\n      {children ?? <ChevronRight />}\n    </li>\n  );\n});\nBreadcrumbSeparator.displayName = 'BreadcrumbSeparator';\n\n// ─────────────────────────────────────────────────────────────────\n// BreadcrumbEllipsis (<span>) — collapsed-trail marker.\n// ─────────────────────────────────────────────────────────────────\ninterface BreadcrumbEllipsisProps extends React.ComponentProps<'span'> {}\n\nconst BreadcrumbEllipsis = React.forwardRef<\n  HTMLSpanElement,\n  BreadcrumbEllipsisProps\n>(({ className, ...props }, ref) => {\n  return (\n    <span\n      ref={ref}\n      role=\"presentation\"\n      aria-hidden=\"true\"\n      data-slot=\"breadcrumb-ellipsis\"\n      className={cn(\n        'text-muted-foreground inline-flex size-4 items-center justify-center',\n        className,\n      )}\n      {...props}\n    >\n      <MoreHorizontal className=\"size-4\" />\n      <span className=\"sr-only\">More</span>\n    </span>\n  );\n});\nBreadcrumbEllipsis.displayName = 'BreadcrumbEllipsis';\n\nexport {\n  Breadcrumb,\n  BreadcrumbList,\n  BreadcrumbItem,\n  BreadcrumbLink,\n  BreadcrumbPage,\n  BreadcrumbSeparator,\n  BreadcrumbEllipsis,\n};\nexport type {\n  BreadcrumbProps,\n  BreadcrumbListProps,\n  BreadcrumbItemProps,\n  BreadcrumbLinkProps,\n  BreadcrumbPageProps,\n  BreadcrumbSeparatorProps,\n  BreadcrumbEllipsisProps,\n};\n"
    }
  ]
}
