{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "page-header",
  "type": "registry:ui",
  "dependencies": [
    "clsx",
    "tailwind-merge"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "page-header.tsx",
      "target": "components/ui/page-header.tsx",
      "type": "registry:ui",
      "content": "\"use client\";\nimport * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nexport type PageHeaderSize = \"default\" | \"compact\";\nexport type PageHeaderHeadingLevel = \"h1\" | \"h2\" | \"h3\";\n\nexport interface PageHeaderProps\n  extends Omit<React.HTMLAttributes<HTMLElement>, \"title\"> {\n  /** Mono line above the title. A status word, a breadcrumb, a period label. */\n  eyebrow?: React.ReactNode;\n  title: React.ReactNode;\n  /** Second phrase of the title, carrying the accent color. */\n  titleAccent?: React.ReactNode;\n  /** Categorical: any CSS color. Falls back to the accent token. */\n  accentColor?: string;\n  headingLevel?: PageHeaderHeadingLevel;\n  /** Line under the title. Dates, counts, a status dot. */\n  meta?: React.ReactNode;\n  /** The right-hand column. A PageHeaderMetric, a row of stat panels, or a chart. */\n  aside?: React.ReactNode;\n  /** Control pinned to the top right. An icon-only Button toggling `controlsOpen`. */\n  action?: React.ReactNode;\n  /** Revealed under the copy column while `controlsOpen`. Pass ToggleChipGroups. */\n  controls?: React.ReactNode;\n  controlsOpen?: boolean;\n  /** Spans both columns. A Progress, a ProgressRow, a segmented bar. */\n  progress?: React.ReactNode;\n  /** Small print along the bottom edge. */\n  footer?: React.ReactNode;\n  /** Painted behind everything, under a scrim. Any color, gradient or canvas. */\n  background?: React.ReactNode;\n  size?: PageHeaderSize;\n  /** Stat row under the meta line. Pass PageHeaderStats. */\n  children?: React.ReactNode;\n}\n\nconst titleSizes: Record<PageHeaderSize, string> = {\n  // Sized against the header, not the viewport, so it survives a narrow column.\n  default: \"text-[clamp(2rem,5.5cqi,3.5rem)]\",\n  compact: \"text-[clamp(1.375rem,3cqi,1.875rem)]\",\n};\n\nconst padding: Record<PageHeaderSize, string> = {\n  default: \"px-6 py-8 @3xl:px-10 @3xl:py-10\",\n  compact: \"px-6 py-6 @3xl:px-7\",\n};\n\nexport const PageHeader = React.forwardRef<HTMLElement, PageHeaderProps>(\n  (\n    {\n      className,\n      eyebrow,\n      title,\n      titleAccent,\n      accentColor,\n      headingLevel: Heading = \"h1\",\n      meta,\n      aside,\n      action,\n      controls,\n      controlsOpen = false,\n      progress,\n      footer,\n      background,\n      size = \"default\",\n      children,\n      ...props\n    },\n    ref,\n  ) => (\n    <section\n      ref={ref}\n      data-page-header-size={size}\n      className={cn(\n        \"@container relative isolate overflow-hidden rounded-2xl border border-border bg-surface\",\n        className,\n      )}\n      {...props}\n    >\n      {background != null && (\n        <div className=\"pointer-events-none absolute inset-0 -z-10\">\n          {background}\n          <div\n            data-page-header-scrim=\"\"\n            aria-hidden=\"true\"\n            className=\"absolute inset-0\"\n            style={{\n              backgroundImage:\n                \"linear-gradient(100deg, color-mix(in oklab, var(--color-surface) 92%, transparent), color-mix(in oklab, var(--color-surface) 55%, transparent) 55%, color-mix(in oklab, var(--color-surface) 88%, transparent))\",\n            }}\n          />\n        </div>\n      )}\n\n      <div className={cn(\"relative flex flex-col gap-6\", padding[size])}>\n        <div\n          className={cn(\n            \"flex flex-col gap-6 @2xl:flex-row @2xl:justify-between\",\n            size === \"compact\" ? \"@2xl:items-center\" : \"@2xl:items-start\",\n            action != null && \"pr-12\",\n          )}\n        >\n          <div className=\"flex min-w-0 flex-col gap-3\">\n            {eyebrow != null && (\n              <p className=\"flex flex-wrap items-center gap-2 font-mono text-[0.6875rem] font-semibold uppercase tracking-[0.12em] text-muted\">\n                {eyebrow}\n              </p>\n            )}\n\n            <Heading\n              className={cn(\n                \"font-bold leading-[1.02] text-balance text-ink\",\n                titleSizes[size],\n              )}\n            >\n              {title}\n              {titleAccent != null && (\n                <>\n                  {\" \"}\n                  <span style={{ color: accentColor ?? \"var(--color-accent)\" }}>\n                    {titleAccent}\n                  </span>\n                </>\n              )}\n            </Heading>\n\n            {meta != null && (\n              <p className=\"flex flex-wrap items-center gap-2 text-sm text-muted\">\n                {meta}\n              </p>\n            )}\n\n            {children != null && <div className=\"mt-2\">{children}</div>}\n\n            {controls != null && (\n              <PageHeaderControls open={controlsOpen}>\n                {controls}\n              </PageHeaderControls>\n            )}\n          </div>\n\n          {aside != null && (\n            <div className=\"shrink-0 @2xl:text-right\">{aside}</div>\n          )}\n        </div>\n\n        {progress != null && <div>{progress}</div>}\n\n        {footer != null && (\n          <p className=\"flex flex-wrap items-center gap-2 text-sm text-muted\">\n            {footer}\n          </p>\n        )}\n      </div>\n\n      {action != null && (\n        <div className=\"absolute right-4 top-4 z-10\">{action}</div>\n      )}\n    </section>\n  ),\n);\nPageHeader.displayName = \"PageHeader\";\n\nfunction PageHeaderControls({\n  open,\n  children,\n}: {\n  open: boolean;\n  children: React.ReactNode;\n}) {\n  // A closed region still has focusable chips in it, and `hidden` would kill the\n  // height transition, so it goes inert instead. React 18 and 19 disagree on how\n  // an `inert` prop serializes, and one of them warns either way. Setting the\n  // attribute on the node sidesteps the disagreement.\n  const ref = React.useRef<HTMLDivElement>(null);\n  const useIsomorphicLayoutEffect =\n    typeof window === \"undefined\" ? React.useEffect : React.useLayoutEffect;\n  useIsomorphicLayoutEffect(() => {\n    const node = ref.current;\n    if (!node) return;\n    if (open) node.removeAttribute(\"inert\");\n    else node.setAttribute(\"inert\", \"\");\n  }, [open]);\n\n  return (\n    <div\n      ref={ref}\n      data-page-header-controls=\"\"\n      data-open={open ? \"\" : undefined}\n      className={cn(\n        \"-mx-1 grid px-1 transition-[grid-template-rows,opacity] duration-base ease-soft motion-reduce:transition-none\",\n        open ? \"grid-rows-[1fr] opacity-100\" : \"grid-rows-[0fr] opacity-0\",\n      )}\n    >\n      <div className=\"overflow-hidden\">\n        <div className=\"flex flex-col gap-2 pt-3\">{children}</div>\n      </div>\n    </div>\n  );\n}\n\nexport type PageHeaderStatsProps = React.HTMLAttributes<HTMLDListElement>;\n\nexport const PageHeaderStats = React.forwardRef<\n  HTMLDListElement,\n  PageHeaderStatsProps\n>(({ className, children, ...props }, ref) => (\n  <dl\n    ref={ref}\n    className={cn(\"flex w-fit flex-wrap items-stretch gap-2\", className)}\n    {...props}\n  >\n    {children}\n  </dl>\n));\nPageHeaderStats.displayName = \"PageHeaderStats\";\n\nexport type PageHeaderStatTone = \"default\" | \"accent\" | \"warning\" | \"danger\";\nexport type PageHeaderStatVariant = \"plain\" | \"featured\" | \"panel\";\n\nexport interface PageHeaderStatProps\n  extends React.HTMLAttributes<HTMLDivElement> {\n  label: React.ReactNode;\n  value: React.ReactNode;\n  /** Caption under the value. */\n  sub?: React.ReactNode;\n  tone?: PageHeaderStatTone;\n  /**\n   * `plain` sits on the header itself, `featured` is the tinted first tile,\n   * `panel` is a standalone card for the aside column.\n   */\n  variant?: PageHeaderStatVariant;\n}\n\nconst statValueTones: Record<PageHeaderStatTone, string> = {\n  default: \"text-ink\",\n  accent: \"text-accent\",\n  warning: \"text-warning\",\n  danger: \"text-danger\",\n};\n\nconst statFills: Record<PageHeaderStatTone, string> = {\n  default: \"bg-ink/[0.05] ring-1 ring-inset ring-ink/10\",\n  accent: \"bg-accent/[0.08] ring-1 ring-inset ring-accent/20\",\n  warning: \"bg-warning/10 ring-1 ring-inset ring-warning/25\",\n  danger: \"bg-danger/10 ring-1 ring-inset ring-danger/25\",\n};\n\nexport const PageHeaderStat = React.forwardRef<\n  HTMLDivElement,\n  PageHeaderStatProps\n>(\n  (\n    {\n      className,\n      label,\n      value,\n      sub,\n      tone = \"default\",\n      variant = \"plain\",\n      ...props\n    },\n    ref,\n  ) => (\n    <div\n      ref={ref}\n      data-page-header-stat={variant}\n      className={cn(\n        \"relative min-w-28 px-4 py-3.5 text-left\",\n        variant === \"plain\"\n          ? // The hairline is a child, not a left border, so the first tile in a\n            // wrapped row does not grow one when it reflows to a new line.\n            \"before:absolute before:inset-y-2 before:left-0 before:w-px before:bg-border before:content-['']\"\n          : \"rounded-xl backdrop-blur-sm\",\n        variant === \"featured\" && statFills[tone],\n        variant === \"panel\" && \"bg-sunken/60 ring-1 ring-inset ring-ink/10\",\n        className,\n      )}\n      {...props}\n    >\n      <dt className=\"font-mono text-[0.5625rem] font-semibold uppercase tracking-[0.12em] text-muted\">\n        {label}\n      </dt>\n      <dd\n        className={cn(\n          \"mt-2 font-bold text-2xl leading-none tabular-nums\",\n          statValueTones[tone],\n        )}\n      >\n        {value}\n      </dd>\n      {sub != null && <dd className=\"mt-1.5 text-xs text-muted\">{sub}</dd>}\n    </div>\n  ),\n);\nPageHeaderStat.displayName = \"PageHeaderStat\";\n\nexport interface PageHeaderMetricProps\n  extends React.HTMLAttributes<HTMLDivElement> {\n  value: React.ReactNode;\n  /** Renders as `value / total`, at roughly half the size. */\n  total?: React.ReactNode;\n  caption?: React.ReactNode;\n}\n\nexport const PageHeaderMetric = React.forwardRef<\n  HTMLDivElement,\n  PageHeaderMetricProps\n>(({ className, value, total, caption, ...props }, ref) => (\n  <div ref={ref} className={cn(\"shrink-0\", className)} {...props}>\n    <p className=\"font-mono font-bold text-[clamp(2.5rem,8cqi,4rem)] leading-none text-ink tabular-nums\">\n      {value}\n      {total != null && (\n        <span className=\"font-semibold text-[0.46em] text-muted\">\n          {\" \"}\n          / {total}\n        </span>\n      )}\n    </p>\n    {caption != null && <p className=\"mt-2 text-sm text-muted\">{caption}</p>}\n  </div>\n));\nPageHeaderMetric.displayName = \"PageHeaderMetric\";\n"
    }
  ]
}