{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "section-header",
  "type": "registry:ui",
  "title": "Section Header",
  "description": "The \"section intro\" block — optional eyebrow, a heading, and a `max-w-prose` tagline — with the bottom margin, the alignment and the type rhythm owned in one place instead of being re-typed as `text-center mb-12` on every section.",
  "author": "ofri-peretz <https://github.com/ofri-peretz>",
  "categories": [
    "navigation",
    "pattern"
  ],
  "dependencies": [
    "class-variance-authority"
  ],
  "registryDependencies": [
    "https://ds.interlace.tools/r/theme.json",
    "https://ds.interlace.tools/r/cn.json"
  ],
  "files": [
    {
      "path": "registry/interlace-ui/patterns/section-header.tsx",
      "target": "components/ui/patterns/section-header.tsx",
      "type": "registry:ui",
      "content": "import * as React from 'react';\n\n// @interlace/section-header v1.2.0 — Interlace design system.\n// Docs, props and live preview: https://ds.interlace.tools/c/section-header\n// What changed since: https://ds.interlace.tools/c/section-header#history\n// Generated banner — keep it, the upgrade diff reads this version.\n\n/**\n * @interlace/ui — SectionHeader\n *\n * The \"section intro\" block — optional eyebrow, a heading, and a `max-w-prose`\n * tagline — with the bottom margin, the alignment and the type rhythm owned in\n * one place instead of being re-typed as `text-center mb-12` on every section.\n *\n * It is the LAYOUT_PHILOSOPHY §1 pattern lifted into a component.\n *\n * ## Anatomy\n *\n *   SectionHeader                    (div — data-slot=\"section-header\", data-align)\n *     ├─ div                         (data-slot=\"section-header-eyebrow\")\n *     ├─ h1 | h2 | h3                (title — `text-3xl md:text-4xl lg:text-5xl`)\n *     └─ p                           (tagline — `text-muted-foreground max-w-prose`)\n *\n * ## Variants\n *\n * `align` — `center` (default, adds `[&_p]:mx-auto`) or `start`.\n * `spacing` — the bottom margin: `md` = `mb-12`, `lg` (default) = `mb-16`.\n * `as` — the heading level, `h1` | `h2` | `h3`, defaulting to `h2` because the\n * page-level `h1` belongs to the hero. The visual size does not follow the\n * level; all three render at the same scale.\n *\n * ## `align` reaches the eyebrow too\n *\n * The eyebrow row is a flex container, and `text-center` / `text-left` on the\n * root does not place a flex child on its main axis — so the row carries its\n * own `justify-center` / `justify-start`, keyed off the same variant\n * (`sectionHeaderEyebrowVariants`). It used to be a hard-coded\n * `justify-center`, which left the eyebrow centred over a left-aligned\n * heading under `align=\"start\"`.\n *\n * | Rule | Concept                     | Where in this file                                    |\n * | ---- | --------------------------- | ----------------------------------------------------- |\n * | R4   | Extends native el           | `Omit<React.ComponentProps<'div'>, 'title'>`          |\n * | R6   | data-slot on root           | `data-slot=\"section-header\"` + `data-align`           |\n * | R7   | cva + cn + ...rest          | `cn(sectionHeaderVariants({align, spacing}), className)` |\n * | R8   | Enums, not booleans         | `align = center\\|start`; `spacing = md\\|lg`           |\n * | R10  | Composition seams           | `eyebrow` / `title` / `tagline` are `ReactNode`       |\n * | R18  | Tailwind only               | zero inline `style`                                   |\n * | R19  | Tokens only                 | `text-muted-foreground`; no palette escapes           |\n * | R25  | Server component            | no hooks → no `'use client'`                          |\n */\n\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nimport { cn } from '@/lib/utils';\n\n/**\n * The eyebrow row's own alignment, keyed by the same `align` variant as the\n * root. It is a separate cva because the eyebrow is a flex row inside a\n * text-aligned block: `text-center` on the root does not reach a flex child's\n * main-axis placement, so the row needs `justify-*` stated for it.\n */\nconst sectionHeaderEyebrowVariants = cva('mb-4 flex items-center', {\n  variants: {\n    align: {\n      center: 'justify-center',\n      start: 'justify-start',\n    },\n  },\n  defaultVariants: {\n    align: 'center',\n  },\n});\n\nconst sectionHeaderVariants = cva('', {\n  variants: {\n    align: {\n      center: 'text-center [&_p]:mx-auto',\n      start: 'text-left',\n    },\n    spacing: {\n      md: 'mb-12',\n      lg: 'mb-16',\n    },\n  },\n  defaultVariants: {\n    align: 'center',\n    spacing: 'lg',\n  },\n});\n\ninterface SectionHeaderProps\n  extends Omit<React.ComponentProps<'div'>, 'title'>,\n    VariantProps<typeof sectionHeaderVariants> {\n  /** Small label above the title (e.g. a section number, chip, or eyebrow tag). */\n  eyebrow?: React.ReactNode;\n  /** The h2 heading. */\n  title: React.ReactNode;\n  /** Optional subhead paragraph. */\n  tagline?: React.ReactNode;\n  /** Heading level. Defaults to h2 (page-level h1 lives in the hero). */\n  as?: 'h1' | 'h2' | 'h3';\n}\n\nfunction SectionHeader({\n  className,\n  eyebrow,\n  title,\n  tagline,\n  align,\n  spacing,\n  as: Heading = 'h2',\n  ...props\n}: SectionHeaderProps) {\n  return (\n    <div\n      data-slot=\"section-header\"\n      data-align={align ?? undefined}\n      className={cn(sectionHeaderVariants({ align, spacing }), className)}\n      {...props}\n    >\n      {eyebrow ? (\n        <div\n          data-slot=\"section-header-eyebrow\"\n          className={sectionHeaderEyebrowVariants({ align })}\n        >\n          {eyebrow}\n        </div>\n      ) : null}\n      <Heading className=\"text-3xl md:text-4xl lg:text-5xl font-bold mb-4\">\n        {title}\n      </Heading>\n      {tagline ? (\n        <p className=\"text-muted-foreground max-w-prose text-base md:text-lg\">\n          {tagline}\n        </p>\n      ) : null}\n    </div>\n  );\n}\n\nexport { SectionHeader, sectionHeaderVariants, sectionHeaderEyebrowVariants };\nexport type { SectionHeaderProps };\n"
    }
  ],
  "meta": {
    "tier": "pattern",
    "client": false,
    "minViewport": null,
    "loading": false,
    "version": "1.2.0",
    "since": "1.0.0"
  },
  "docs": "## @interlace/section-header\n\nInstalled to `components/ui/patterns/section-header.tsx`.\n\n```tsx\nimport { /* … */ } from '@/components/ui/patterns/section-header';\n```\n\nProps, a11y contract, live preview and source: https://ds.interlace.tools/c/section-header\n\nRequires the `@interlace/theme` CSS baseline (installed automatically as a registry dependency)."
}
