{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "page-header",
  "title": "Page Header",
  "description": "The title row of a page: breadcrumbs, title, status, actions and optional page tabs.",
  "dependencies": [
    "@base-ui/react@^1.9.0"
  ],
  "registryDependencies": [
    "https://sproutboat.com/ikada/r/theme.json",
    "https://sproutboat.com/ikada/r/cn.json"
  ],
  "files": [
    {
      "path": "registry/ikada/ui/page-header.tsx",
      "content": "\"use client\";\n\nimport { useRender } from \"@base-ui/react/use-render\";\nimport type { ComponentProps, ReactNode } from \"react\";\nimport { cn, coarseTarget, focusRingInset, type WithClass } from \"@/components/ikada/lib/cn\";\n\nexport interface PageHeaderProps extends Omit<ComponentProps<\"header\">, \"title\"> {\n  /** Usually <Breadcrumbs />. */\n  breadcrumbs?: ReactNode;\n  /** Page title, rendered as the h1. */\n  title: ReactNode;\n  /** Next to the title: a StatusDot or Badge. */\n  status?: ReactNode;\n  /** One muted line under the title: domain, repo, branch. */\n  description?: ReactNode;\n  /** Buttons, right-aligned; they wrap under the title on narrow screens. */\n  actions?: ReactNode;\n  /** Usually <PageTabs>. Sits on the header's bottom rule. */\n  tabs?: ReactNode;\n  /** Heading level of the title. Default `h1`; use a lower level when the header is not the page's own title. */\n  headingLevel?: \"h1\" | \"h2\" | \"h3\" | \"h4\";\n}\n\n/** Title row for a page. The title is the page's only `h1` unless `headingLevel` says otherwise. */\nexport function PageHeader({\n  breadcrumbs,\n  title,\n  status,\n  description,\n  actions,\n  tabs,\n  headingLevel: Title = \"h1\",\n  className,\n  ref,\n  ...props\n}: PageHeaderProps) {\n  return (\n    <header data-slot=\"page-header\" ref={ref} className={cn(\"flex flex-col gap-4\", className)} {...props}>\n      {breadcrumbs}\n      <div className=\"flex flex-wrap items-start justify-between gap-x-6 gap-y-3\">\n        <div className=\"flex min-w-0 flex-col gap-1.5\">\n          <div className=\"flex min-w-0 flex-wrap items-center gap-x-3 gap-y-1\">\n            <Title className=\"min-w-0 break-words text-balance text-sb-xl font-bold\">{title}</Title>\n            {status}\n          </div>\n          {description ? <p className=\"break-words text-pretty text-sb-base text-fg-muted\">{description}</p> : null}\n        </div>\n        {actions ? <div className=\"flex flex-wrap items-center gap-2\">{actions}</div> : null}\n      </div>\n      {tabs}\n    </header>\n  );\n}\n\n/** Page-level navigation: links with an underline under the current one. Scrolls sideways when narrow. */\nexport function PageTabs({\n  className,\n  children,\n  label = \"Page sections\",\n  ...props\n}: ComponentProps<\"nav\"> & { label?: string }) {\n  return (\n    <nav\n      data-slot=\"page-tabs\"\n      aria-label={label}\n      className={cn(\n        \"-mx-1 overflow-x-auto px-1 shadow-[inset_0_-1px_0_var(--sb-hairline)] [scrollbar-width:none]\",\n        className,\n      )}\n      {...props}\n    >\n      <ul className=\"flex min-w-max gap-3.5\">{children}</ul>\n    </nav>\n  );\n}\n\nexport interface PageTabProps extends WithClass<useRender.ComponentProps<\"a\">> {\n  /** Marks the tab as the current page (aria-current and the underline). */\n  current?: boolean;\n}\n\n/** One tab link. With a router, `render={<RouterLink to=\"/x\" />}`. */\nexport function PageTab({ current = false, className, ref, render, ...props }: PageTabProps) {\n  const tab = useRender({\n    defaultTagName: \"a\",\n    render,\n    ref,\n    props: {\n      \"aria-current\": current ? \"page\" : undefined,\n      className: cn(\n        \"relative -mb-px inline-flex h-10 items-center whitespace-nowrap rounded-xs px-1.5 text-sb-base font-medium text-fg-muted\",\n        \"transition-colors duration-(--sb-duration-hover) ease-hover hover:text-fg aria-[current=page]:text-fg\",\n        \"after:absolute after:inset-x-1.5 after:bottom-0 after:h-0.5 after:rounded-full after:bg-fg after:opacity-0 after:transition-opacity after:duration-(--sb-duration-hover) aria-[current=page]:after:opacity-100\",\n        coarseTarget,\n        // Inset ring: the nav scrolls sideways, so an outer ring would be clipped top and bottom.\n        focusRingInset,\n        className,\n      ),\n      ...props,\n    },\n  });\n  return <li data-slot=\"page-tab\">{tab}</li>;\n}\n",
      "type": "registry:ui",
      "target": "@components/ikada/page-header.tsx"
    }
  ],
  "categories": [
    "navigation",
    "layout"
  ],
  "type": "registry:ui"
}