{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "header-floating-pill",
  "title": "Header — Floating Pill",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/header-floating-pill/header-floating-pill.component.ts",
      "content": "// Detached pill navbar floating above the page with a blurred surface, a sliding\n// active indicator tracking the current link, and a compact CTA on the right.\n// Port of the Vue/React block 1:1 — the indicator is measured from the live element\n// so it fits any label length or font, with no hard-coded widths to drift.\nimport {\n  AfterViewInit,\n  ChangeDetectionStrategy,\n  Component,\n  ElementRef,\n  Input,\n  OnDestroy,\n  ViewChild,\n  signal,\n} from '@angular/core'\nimport { Layers, LucideAngularModule, Menu } from 'lucide-angular'\nimport { cn } from '@/lib/utils'\nimport { UiButtonComponent } from '@/ui/button/button.component'\nimport {\n  UiSheetCloseComponent,\n  UiSheetComponent,\n  UiSheetContentComponent,\n  UiSheetHeaderComponent,\n  UiSheetTitleComponent,\n} from '@/ui/sheet/sheet.component'\n\nexport interface FloatingPillLink {\n  label: string\n  href: string\n}\n\nexport interface PillIndicator {\n  left: number\n  width: number\n}\n\nconst links: FloatingPillLink[] = [\n  { label: 'Product', href: '#product' },\n  { label: 'Pricing', href: '#pricing' },\n  { label: 'Customers', href: '#customers' },\n  { label: 'Docs', href: '#docs' },\n]\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-header-floating-pill, [ui-header-floating-pill]',\n  standalone: true,\n  // The block renders its own root <div>: keep this wrapper out of the layout.\n  host: { '[attr.class]': '\"contents\"' },\n  imports: [\n    LucideAngularModule,\n    UiButtonComponent,\n    UiSheetCloseComponent,\n    UiSheetComponent,\n    UiSheetContentComponent,\n    UiSheetHeaderComponent,\n    UiSheetTitleComponent,\n  ],\n  template: `\n    <div data-slot=\"header-floating-pill\" [class]=\"rootClass\">\n      <header\n        class=\"border-border bg-card/85 pointer-events-auto mx-auto flex h-14 max-w-4xl items-center gap-3 rounded-full border px-3 shadow-sm backdrop-blur\"\n      >\n        <a href=\"#top\" class=\"flex shrink-0 items-center gap-2 pl-2 font-semibold tracking-tight\">\n          <lucide-icon [img]=\"Layers\" class=\"text-primary size-4\" />\n          Verity\n        </a>\n\n        <nav #navEl class=\"relative hidden items-center md:flex\" aria-label=\"Primary\">\n          <span\n            class=\"bg-muted absolute inset-y-1 rounded-full transition-colors duration-200 ease-out\"\n            [style.left.px]=\"indicator().left\"\n            [style.width.px]=\"indicator().width\"\n            aria-hidden=\"true\"\n          ></span>\n          @for (link of pillLinks; track link.href; let i = $index) {\n            <a\n              [href]=\"link.href\"\n              data-pill-link\n              class=\"focus-visible:ring-ring relative rounded-full px-3.5 py-1.5 text-sm font-medium transition-colors focus-visible:ring-2 focus-visible:outline-none\"\n              [class]=\"i === active() ? 'text-foreground' : 'text-muted-foreground hover:text-foreground'\"\n              [attr.aria-current]=\"i === active() ? 'page' : null\"\n              (mouseenter)=\"measure(i)\"\n              (mouseleave)=\"measure()\"\n              (focus)=\"measure(i)\"\n              (blur)=\"measure()\"\n              (click)=\"setActive(i)\"\n            >\n              {{ link.label }}\n            </a>\n          }\n        </nav>\n\n        <button ui-button size=\"sm\" class=\"ml-auto rounded-full\">Start free</button>\n\n        <div ui-sheet [open]=\"mobileOpen()\" (openChange)=\"mobileOpen.set($event)\">\n          <button\n            ui-button\n            variant=\"ghost\"\n            size=\"icon\"\n            class=\"rounded-full md:hidden\"\n            aria-label=\"Open navigation menu\"\n            (click)=\"mobileOpen.set(true)\"\n          >\n            <lucide-icon [img]=\"Menu\" class=\"size-5\" />\n          </button>\n          <div ui-sheet-content side=\"top\">\n            <div ui-sheet-header>\n              <h2 ui-sheet-title>Menu</h2>\n            </div>\n            <nav class=\"mt-6 grid gap-1\" aria-label=\"Mobile\">\n              @for (link of pillLinks; track link.href; let i = $index) {\n                <a\n                  [href]=\"link.href\"\n                  class=\"hover:bg-muted rounded-md px-3 py-2 text-sm font-medium transition-colors\"\n                  (click)=\"selectMobile(i)\"\n                >\n                  {{ link.label }}\n                </a>\n              }\n            </nav>\n          </div>\n        </div>\n      </header>\n    </div>\n  `,\n})\nexport class UiHeaderFloatingPillComponent implements AfterViewInit, OnDestroy {\n  protected readonly Layers = Layers\n  protected readonly Menu = Menu\n\n  protected readonly pillLinks = links\n\n  @ViewChild('navEl') navEl?: ElementRef<HTMLElement>\n\n  @Input('class') className?: string\n\n  readonly active = signal(0)\n  readonly mobileOpen = signal(false)\n  readonly indicator = signal<PillIndicator>({ left: 0, width: 0 })\n\n  private observer?: ResizeObserver\n\n  ngAfterViewInit(): void {\n    this.measure()\n    const nav = this.navEl?.nativeElement\n    if (typeof ResizeObserver !== 'undefined' && nav) {\n      this.observer = new ResizeObserver(() => this.measure())\n      this.observer.observe(nav)\n    }\n  }\n\n  ngOnDestroy(): void {\n    this.observer?.disconnect()\n    this.observer = undefined\n  }\n\n  setActive(index: number): void {\n    this.active.set(index)\n  }\n\n  selectMobile(index: number): void {\n    this.active.set(index)\n    this.mobileOpen.set(false)\n  }\n\n  measure(index = this.active()): void {\n    const items = this.navEl?.nativeElement.querySelectorAll<HTMLElement>('[data-pill-link]')\n    const el = items?.[index]\n    if (!el) return\n    this.indicator.set({ left: el.offsetLeft, width: el.offsetWidth })\n  }\n\n  get rootClass(): string {\n    return cn('pointer-events-none sticky top-0 z-40 px-4 pt-4', this.className)\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/header-floating-pill/header-floating-pill.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/header-floating-pill/index.ts",
      "content": "export {\n  UiHeaderFloatingPillComponent,\n  type FloatingPillLink,\n  type PillIndicator,\n} from './header-floating-pill.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/header-floating-pill/index.ts"
    }
  ],
  "dependencies": [
    "lucide-angular"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/angular/button.json",
    "https://uipkge.dev/r/angular/sheet.json"
  ],
  "description": "Detached pill navbar that floats above the page with a blurred surface, a sliding active indicator that tracks the current link, and a compact CTA on the right.",
  "categories": [
    "marketing"
  ],
  "deprecated": true,
  "replacedBy": "header"
}