{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"page-header","type":"registry:ui","title":"Page header","description":"A title with description, breadcrumbs and actions.","dependencies":["@radix-ui/react-slot","clsx","lucide-react","tailwind-merge"],"registryDependencies":["https://caliperui.site/r/styles.json"],"files":[{"path":"ui/breadcrumb.tsx","type":"registry:ui","target":"components/ui/breadcrumb.tsx","content":"import { Slot } from \"@radix-ui/react-slot\";\nimport { ChevronRight } from \"lucide-react\";\nimport type { ComponentProps } from \"react\";\nimport { cn } from \"./lib/cn\";\nimport \"./breadcrumb.css\";\n\nexport function Breadcrumb({\n  \"aria-label\": label = \"Breadcrumb\",\n  ...props\n}: ComponentProps<\"nav\">) {\n  return <nav data-slot=\"breadcrumb\" aria-label={label} {...props} />;\n}\n\nexport function BreadcrumbList({ className, ...props }: ComponentProps<\"ol\">) {\n  return (\n    <ol\n      data-slot=\"breadcrumb-list\"\n      className={cn(\n        \"flex min-w-0 flex-wrap items-center gap-1 text-[13px] leading-5 text-muted-foreground\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nexport function BreadcrumbItem({ className, ...props }: ComponentProps<\"li\">) {\n  return (\n    <li\n      data-slot=\"breadcrumb-item\"\n      className={cn(\n        \"inline-flex min-w-0 items-center [overflow-wrap:anywhere]\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nexport type BreadcrumbLinkProps = ComponentProps<\"a\"> & { asChild?: boolean };\n\nexport function BreadcrumbLink({\n  asChild = false,\n  className,\n  ...props\n}: BreadcrumbLinkProps) {\n  const Component = asChild ? Slot : \"a\";\n  return (\n    <Component\n      data-slot=\"breadcrumb-link\"\n      className={cn(\n        \"inline-flex min-h-[var(--control-height)] min-w-[var(--control-height)] max-w-full items-center rounded-control px-1 text-muted-foreground outline-none hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background [overflow-wrap:anywhere]\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nexport function BreadcrumbPage({\n  className,\n  ...props\n}: ComponentProps<\"span\">) {\n  return (\n    <span\n      data-slot=\"breadcrumb-page\"\n      className={cn(\n        \"px-1 font-medium text-foreground [overflow-wrap:anywhere]\",\n        className,\n      )}\n      {...props}\n      aria-current=\"page\"\n    />\n  );\n}\n\nexport function BreadcrumbSeparator({\n  className,\n  children,\n  ...props\n}: ComponentProps<\"li\">) {\n  return (\n    <li\n      data-slot=\"breadcrumb-separator\"\n      className={cn(\n        \"inline-flex shrink-0 items-center text-muted-foreground [&_svg]:size-4\",\n        className,\n      )}\n      {...props}\n      role=\"presentation\"\n      aria-hidden=\"true\"\n    >\n      {children ?? <ChevronRight />}\n    </li>\n  );\n}\n"},{"path":"ui/lib/cn.ts","type":"registry:ui","target":"components/ui/lib/cn.ts","content":"import { clsx, type ClassValue } from \"clsx\";\nimport { extendTailwindMerge } from \"tailwind-merge\";\n\nconst twMerge = extendTailwindMerge({\n  extend: { theme: { radius: [\"control\", \"surface\", \"overlay\"], shadow: [\"overlay\"] } },\n});\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}\n"},{"path":"ui/page-header.tsx","type":"registry:ui","target":"components/ui/page-header.tsx","content":"import { Fragment, type ReactNode } from \"react\";\nimport { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from \"./breadcrumb\";\nimport { cn } from \"./lib/cn\";\n\nexport type PageCrumb = { label: string; href?: string };\n\n/** The top of an app page: where you are, what this page is, and what you can do here. */\nexport function PageHeader({\n  title,\n  description,\n  breadcrumb,\n  meta,\n  actions,\n  children,\n  className,\n}: {\n  title: string;\n  description?: ReactNode;\n  /** Ancestors then the current page; the last item is the page itself. */\n  breadcrumb?: readonly PageCrumb[];\n  /** Status badges or small facts beside the title. */\n  meta?: ReactNode;\n  /** Buttons aligned to the end; they wrap under the title on narrow screens. */\n  actions?: ReactNode;\n  /** Anything that belongs to the header, such as tabs. */\n  children?: ReactNode;\n  className?: string;\n}) {\n  return (\n    <header data-slot=\"page-header\" className={cn(\"grid min-w-0 gap-4\", className)}>\n      {breadcrumb && breadcrumb.length > 0 && (\n        <Breadcrumb>\n          <BreadcrumbList>\n            {breadcrumb.map((crumb, i) => (\n              <Fragment key={`${crumb.label}-${i}`}>\n                {i > 0 && <BreadcrumbSeparator />}\n                <BreadcrumbItem>\n                  {i === breadcrumb.length - 1 || !crumb.href ? <BreadcrumbPage>{crumb.label}</BreadcrumbPage> : <BreadcrumbLink href={crumb.href}>{crumb.label}</BreadcrumbLink>}\n                </BreadcrumbItem>\n              </Fragment>\n            ))}\n          </BreadcrumbList>\n        </Breadcrumb>\n      )}\n      <div className=\"flex flex-wrap items-start justify-between gap-x-6 gap-y-3\">\n        <div className=\"grid min-w-0 flex-1 gap-1.5 [flex-basis:20rem]\">\n          <div className=\"flex min-w-0 flex-wrap items-center gap-x-3 gap-y-1\">\n            <h1 className=\"min-w-0 text-2xl font-semibold tracking-tight [overflow-wrap:anywhere]\">{title}</h1>\n            {meta}\n          </div>\n          {description && <p className=\"max-w-2xl text-sm text-muted-foreground\">{description}</p>}\n        </div>\n        {actions && <div className=\"flex shrink-0 flex-wrap items-center gap-2\">{actions}</div>}\n      </div>\n      {children}\n    </header>\n  );\n}\n"},{"path":"ui/breadcrumb.css","type":"registry:file","target":"components/ui/breadcrumb.css","content":"/* breadcrumb.tsx's styles; it imports this file. Edit freely. */\n@layer theme, base, components, utilities;\n\n@layer components {\n  [data-slot=\"breadcrumb-link\"] {\n    transition-property: background-color, color, border-color;\n    transition-duration: var(--duration-fast);\n    transition-timing-function: var(--ease-out);\n  }\n\n  @media (prefers-reduced-motion: reduce) {\n    [data-slot=\"breadcrumb-link\"] {\n      transition: none;\n    }\n  }\n}\n"}],"categories":["free-marketing"],"meta":{"tier":"free","license":"MIT","family":"page-chrome","docs":"/docs/components/page-header"}}