Menu

Change language

GitHub repo

Sticky Top Navbar

blockmarketing

Sticky marketing top-bar. Brand mark on the left, five inline anchor links in the centre on desktop, "Sign in" + primary trial CTA on the right. Below the md breakpoint the right side collapses into a hamburger that opens a right-side Sheet with the same links and CTAs stacked. Translucent background uses backdrop-blur so content can scroll behind it.

Installation

$npx uipkge-ng@latest add header-01
Manifest:https://uipkge.dev/r/angular/header-01.jsonInstalls to:src/app/components/blocks/header-01/

Variants

Loading interactive previews…

Schema

Type aliases exported from this item's source. Use these to shape the data you pass in.

Header01Link
interface Header01Link {
  label: string
  href: string
}

npm dependencies

Includes

Files installed (2)

  • src/app/components/blocks/header-01/header-01.component.ts4.7 kB
    // Sticky marketing top-bar: brand mark left, five inline anchor links centre on
    // desktop, "Sign in" + primary trial CTA right. Below md the right side collapses
    // into a hamburger opening a right-side sheet with the same links and CTAs stacked.
    // Translucent background uses backdrop-blur so content scrolls behind it.
    // Port of the Vue/React block 1:1 — same links, same copy, same sheet behaviour.
    import { ChangeDetectionStrategy, Component, Input, signal } from '@angular/core'
    import { Boxes, LucideAngularModule, Menu, X } from 'lucide-angular'
    import { cn } from '@/lib/utils'
    import { UiButtonComponent } from '@/ui/button/button.component'
    import { UiSheetCloseComponent, UiSheetComponent, UiSheetContentComponent } from '@/ui/sheet/sheet.component'
    
    export interface Header01Link {
      label: string
      href: string
    }
    
    const links: Header01Link[] = [
      { label: 'Features', href: '#features' },
      { label: 'Pricing', href: '#pricing' },
      { label: 'Customers', href: '#customers' },
      { label: 'Docs', href: '#docs' },
      { label: 'Blog', href: '#blog' },
    ]
    
    @Component({
      changeDetection: ChangeDetectionStrategy.Eager,
      selector: 'ui-header-01, [ui-header-01]',
      standalone: true,
      // The block renders its own <header>: keep this wrapper out of the layout.
      host: { '[attr.class]': '"contents"' },
      imports: [LucideAngularModule, UiButtonComponent, UiSheetCloseComponent, UiSheetComponent, UiSheetContentComponent],
      template: `
        <header data-slot="header-01" [class]="rootClass">
          <div class="mx-auto flex h-16 max-w-6xl items-center justify-between px-6">
            <a href="#" class="flex items-center gap-2">
              <div class="bg-primary text-primary-foreground flex size-8 items-center justify-center rounded-md">
                <lucide-icon [img]="Boxes" class="size-4" />
              </div>
              <span class="text-base font-semibold">Acme</span>
            </a>
    
            <nav class="hidden items-center gap-6 md:flex" aria-label="Primary">
              @for (link of navLinks; track link.href) {
                <a [href]="link.href" class="text-muted-foreground hover:text-foreground text-sm transition-colors">
                  {{ link.label }}
                </a>
              }
            </nav>
    
            <div class="hidden items-center gap-2 md:flex">
              <button ui-button variant="ghost" size="sm">Sign in</button>
              <button ui-button size="sm">Start free trial</button>
            </div>
    
            <div ui-sheet [open]="mobileOpen()" (openChange)="mobileOpen.set($event)">
              <button
                ui-button
                variant="ghost"
                size="icon"
                class="md:hidden"
                aria-label="Open menu"
                (click)="mobileOpen.set(true)"
              >
                <lucide-icon [img]="Menu" class="size-5" />
              </button>
              <div ui-sheet-content side="right" class="w-72">
                <div class="flex h-full flex-col">
                  <div class="flex items-center justify-between border-b px-4 py-3">
                    <div class="flex items-center gap-2">
                      <div class="bg-primary text-primary-foreground flex size-7 items-center justify-center rounded-md">
                        <lucide-icon [img]="Boxes" class="size-3.5" />
                      </div>
                      <span class="text-sm font-semibold">Acme</span>
                    </div>
                    <button ui-button ui-sheet-close variant="ghost" size="icon" class="size-8" aria-label="Close menu">
                      <lucide-icon [img]="X" class="size-4" />
                    </button>
                  </div>
                  <nav class="flex flex-1 flex-col gap-1 p-4" aria-label="Mobile">
                    @for (link of navLinks; track link.href) {
                      <a
                        [href]="link.href"
                        class="hover:bg-muted rounded-md px-3 py-2 text-sm transition-colors"
                        (click)="mobileOpen.set(false)"
                      >
                        {{ link.label }}
                      </a>
                    }
                  </nav>
                  <div class="flex flex-col gap-2 border-t p-4">
                    <button ui-button variant="outline" class="w-full">Sign in</button>
                    <button ui-button class="w-full">Start free trial</button>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </header>
      `,
    })
    export class UiHeader01Component {
      protected readonly Boxes = Boxes
      protected readonly Menu = Menu
      protected readonly X = X
    
      protected readonly navLinks = links
    
      @Input('class') className?: string
    
      readonly mobileOpen = signal(false)
    
      get rootClass(): string {
        return cn(
          'bg-background/80 supports-[backdrop-filter]:bg-background/60 sticky top-0 z-40 border-b backdrop-blur',
          this.className,
        )
      }
    
      closeMobile(): void {
        this.mobileOpen.set(false)
      }
    }
    
  • src/app/components/blocks/header-01/index.ts0.1 kB

Raw manifest:https://uipkge.dev/r/angular/header-01.json