Header
blockmarketingSite header collection: sticky top bar, dismissible announcement stack, centered-logo split, floating pill, full-width mega menu, inline search with command palette, and a transparent-over-hero scroll variant — each with a mobile sheet fallback.
Installation
$pnpm dlx shadcn-svelte@latest add https://uipkge.dev/r/svelte/header.json$npx shadcn-svelte@latest add https://uipkge.dev/r/svelte/header.json$yarn dlx shadcn-svelte@latest add https://uipkge.dev/r/svelte/header.json$bunx shadcn-svelte@latest add https://uipkge.dev/r/svelte/header.jsonManifest:
https://uipkge.dev/r/svelte/header.jsonInstalls to:src/lib/components/blocks/header/Variants
Loading interactive previews…
Loading interactive previews…
npm dependencies
Files installed (7)
src/lib/components/blocks/header/Header01.svelte3.9 kB
<script lang="ts"> import { Boxes, Menu, X } from '@lucide/svelte' import { Button } from '$lib/components/ui/button' import { Sheet, SheetContent, SheetTrigger } from '$lib/components/ui/sheet' let mobileOpen = $state(false) </script> <header data-slot="header-01" class="bg-background/80 supports-[backdrop-filter]:bg-background/60 sticky top-0 z-40 border-b backdrop-blur" > <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"> <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"> <a href="#features" class="text-muted-foreground hover:text-foreground text-sm transition-colors">Features</a> <a href="#pricing" class="text-muted-foreground hover:text-foreground text-sm transition-colors">Pricing</a> <a href="#customers" class="text-muted-foreground hover:text-foreground text-sm transition-colors">Customers</a> <a href="#docs" class="text-muted-foreground hover:text-foreground text-sm transition-colors">Docs</a> <a href="#blog" class="text-muted-foreground hover:text-foreground text-sm transition-colors">Blog</a> </nav> <div class="hidden items-center gap-2 md:flex"> <Button variant="ghost" size="sm">Sign in</Button> <Button size="sm">Start free trial</Button> </div> <Sheet bind:open={mobileOpen}> <SheetTrigger> {#snippet child({ props })} <Button {...props} variant="ghost" size="icon" class="md:hidden" aria-label="Open menu"> <Menu class="size-5" /> </Button> {/snippet} </SheetTrigger> <SheetContent 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"> <Boxes class="size-3.5" /> </div> <span class="text-sm font-semibold">Acme</span> </div> <Button variant="ghost" size="icon" class="size-8" aria-label="Close menu" onclick={() => (mobileOpen = false)} > <X class="size-4" /> </Button> </div> <nav class="flex flex-1 flex-col gap-1 p-4" aria-label="Mobile"> <a href="#features" class="hover:bg-muted rounded-md px-3 py-2 text-sm transition-colors" onclick={() => (mobileOpen = false)}>Features</a > <a href="#pricing" class="hover:bg-muted rounded-md px-3 py-2 text-sm transition-colors" onclick={() => (mobileOpen = false)}>Pricing</a > <a href="#customers" class="hover:bg-muted rounded-md px-3 py-2 text-sm transition-colors" onclick={() => (mobileOpen = false)}>Customers</a > <a href="#docs" class="hover:bg-muted rounded-md px-3 py-2 text-sm transition-colors" onclick={() => (mobileOpen = false)}>Docs</a > <a href="#blog" class="hover:bg-muted rounded-md px-3 py-2 text-sm transition-colors" onclick={() => (mobileOpen = false)}>Blog</a > </nav> <div class="flex flex-col gap-2 border-t p-4"> <Button variant="outline" class="w-full">Sign in</Button> <Button class="w-full">Start free trial</Button> </div> </div> </SheetContent> </Sheet> </div> </header>src/lib/components/blocks/header/HeaderAnnouncementStack.svelte4.1 kB
<script lang="ts"> import { onMount } from 'svelte' import { ArrowRight, Layers, Menu, X } from '@lucide/svelte' import { Badge } from '$lib/components/ui/badge' import { Button } from '$lib/components/ui/button' import { Separator } from '$lib/components/ui/separator' import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from '$lib/components/ui/sheet' const STORAGE_KEY = 'uipkge:announcement-dismissed' const links = [ { label: 'Platform', href: '#platform' }, { label: 'Pricing', href: '#pricing' }, { label: 'Customers', href: '#customers' }, { label: 'Docs', href: '#docs' }, ] // Rendered on the server and dismissed only on the client, so there is no flash // of a strip that then vanishes. let dismissed = $state(false) let open = $state(false) function dismiss() { dismissed = true try { window.sessionStorage.setItem(STORAGE_KEY, '1') } catch { // Blocked storage: the dismissal still holds for this page view. } } onMount(() => { try { dismissed = window.sessionStorage.getItem(STORAGE_KEY) === '1' } catch { dismissed = false } }) </script> <div data-slot="header-announcement-stack" class="sticky top-0 z-40"> {#if !dismissed} <div class="border-border bg-muted/60 border-b backdrop-blur"> <div class="mx-auto flex h-10 max-w-6xl items-center gap-3 px-6 text-sm"> <Badge variant="secondary" class="shrink-0">New</Badge> <p class="min-w-0 truncate"> Row-level scoping now evaluates against SCIM groups. <a href="#changelog" class="hover:text-foreground underline underline-offset-4">Read the changelog</a> </p> <ArrowRight class="text-muted-foreground hidden size-3.5 shrink-0 sm:block" aria-hidden="true" /> <Button variant="ghost" size="icon" class="ml-auto size-7 shrink-0" aria-label="Dismiss announcement" onclick={dismiss} > <X class="size-3.5" aria-hidden="true" /> </Button> </div> </div> {/if} <header class="border-border bg-background/90 border-b backdrop-blur"> <div class="mx-auto flex h-16 max-w-6xl items-center gap-6 px-6"> <a href="#top" class="flex shrink-0 items-center gap-2 font-semibold tracking-tight"> <Layers class="text-primary size-5" aria-hidden="true" /> Northwind </a> <nav class="hidden items-center gap-1 md:flex" aria-label="Primary"> {#each links as link (link.href)} <a href={link.href} class="text-muted-foreground hover:text-foreground hover:bg-muted focus-visible:ring-ring rounded-md px-3 py-1.5 text-sm font-medium transition-colors focus-visible:ring-2 focus-visible:outline-none" > {link.label} </a> {/each} </nav> <div class="ml-auto hidden items-center gap-2 md:flex"> <Button variant="ghost" size="sm">Sign in</Button> <Button size="sm">Book a demo</Button> </div> <Sheet bind:open> <SheetTrigger> {#snippet child({ props })} <Button {...props} variant="ghost" size="icon" class="ml-auto md:hidden" aria-label="Open navigation menu"> <Menu class="size-5" aria-hidden="true" /> </Button> {/snippet} </SheetTrigger> <SheetContent side="right" class="w-72"> <SheetHeader> <SheetTitle>Menu</SheetTitle> </SheetHeader> <nav class="mt-6 grid gap-1" aria-label="Mobile"> {#each links as link (link.href)} <a href={link.href} class="hover:bg-muted rounded-md px-3 py-2 text-sm font-medium transition-colors" onclick={() => (open = false)} > {link.label} </a> {/each} </nav> <Separator class="my-5" /> <div class="grid gap-2"> <Button variant="outline">Sign in</Button> <Button>Book a demo</Button> </div> </SheetContent> </Sheet> </div> </header> </div>src/lib/components/blocks/header/HeaderCenteredLogo.svelte3 kB
<script lang="ts"> import { Compass, Menu, ShoppingBag, User } from '@lucide/svelte' import { Button } from '$lib/components/ui/button' import { Separator } from '$lib/components/ui/separator' import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from '$lib/components/ui/sheet' const leftLinks = [ { label: 'Collections', href: '#collections' }, { label: 'New in', href: '#new' }, { label: 'Studio', href: '#studio' }, ] const rightLinks = [ { label: 'Journal', href: '#journal' }, { label: 'Stockists', href: '#stockists' }, { label: 'Contact', href: '#contact' }, ] let open = $state(false) const linkClass = 'text-muted-foreground hover:text-foreground focus-visible:ring-ring rounded-md px-3 py-1.5 text-sm font-medium transition-colors focus-visible:ring-2 focus-visible:outline-none' </script> <header data-slot="header-centered-logo" class="border-border bg-background border-b"> <div class="mx-auto flex h-16 max-w-6xl items-center px-6"> <!-- Equal-basis flanks keep the wordmark optically centred regardless of how long the link labels are. --> <nav class="hidden flex-1 basis-0 items-center gap-1 lg:flex" aria-label="Primary left"> {#each leftLinks as link (link.href)} <a href={link.href} class={linkClass}>{link.label}</a> {/each} </nav> <Sheet bind:open> <SheetTrigger> {#snippet child({ props })} <Button {...props} variant="ghost" size="icon" class="lg:hidden" aria-label="Open navigation menu"> <Menu class="size-5" aria-hidden="true" /> </Button> {/snippet} </SheetTrigger> <SheetContent side="left" class="w-72"> <SheetHeader> <SheetTitle>Menu</SheetTitle> </SheetHeader> <nav class="mt-6 grid gap-1" aria-label="Mobile"> {#each [...leftLinks, ...rightLinks] as link (link.href)} <a href={link.href} class="hover:bg-muted rounded-md px-3 py-2 text-sm font-medium transition-colors" onclick={() => (open = false)} > {link.label} </a> {/each} </nav> <Separator class="my-5" /> <Button class="w-full">Account</Button> </SheetContent> </Sheet> <a href="#top" class="mx-auto flex items-center gap-2 text-base font-semibold tracking-[0.18em] uppercase lg:mx-6"> <Compass class="text-primary size-4" aria-hidden="true" /> Halden </a> <nav class="hidden flex-1 basis-0 items-center justify-end gap-1 lg:flex" aria-label="Primary right"> {#each rightLinks as link (link.href)} <a href={link.href} class={linkClass}>{link.label}</a> {/each} </nav> <div class="flex items-center gap-1 lg:ml-4"> <Button variant="ghost" size="icon" aria-label="Account"> <User class="size-4" aria-hidden="true" /> </Button> <Button variant="ghost" size="icon" aria-label="Bag"> <ShoppingBag class="size-4" aria-hidden="true" /> </Button> </div> </div> </header>src/lib/components/blocks/header/HeaderFloatingPill.svelte3.6 kB
<script lang="ts"> import { onMount } from 'svelte' import { CircleDot, Menu } from '@lucide/svelte' import { Button } from '$lib/components/ui/button' import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from '$lib/components/ui/sheet' const links = [ { label: 'Product', href: '#product' }, { label: 'Pricing', href: '#pricing' }, { label: 'Customers', href: '#customers' }, { label: 'Docs', href: '#docs' }, ] let active = $state(0) let open = $state(false) let navEl = $state<HTMLElement | null>(null) // Measured from the live element, so the indicator fits any label length or // font — no hard-coded widths to drift out of sync with the copy. let indicator = $state({ left: 0, width: 0 }) function measure(index = active) { const items = navEl?.querySelectorAll<HTMLElement>('[data-pill-link]') const el = items?.[index] if (!el) return indicator = { left: el.offsetLeft, width: el.offsetWidth } } onMount(() => { measure() let observer: ResizeObserver | undefined if ('ResizeObserver' in window && navEl) { observer = new ResizeObserver(() => measure()) observer.observe(navEl) } return () => observer?.disconnect() }) </script> <div data-slot="header-floating-pill" class="pointer-events-none sticky top-0 z-40 px-4 pt-4"> <header 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" > <a href="#top" class="flex shrink-0 items-center gap-2 pl-2 font-semibold tracking-tight"> <CircleDot class="text-primary size-4" aria-hidden="true" /> Verity </a> <nav bind:this={navEl} class="relative hidden items-center md:flex" aria-label="Primary"> <span class="bg-muted absolute inset-y-1 rounded-full transition-colors duration-200 ease-out" style="left: {indicator.left}px; width: {indicator.width}px" aria-hidden="true" ></span> {#each links as link, index (link.href)} <a href={link.href} data-pill-link 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 {index === active ? 'text-foreground' : 'text-muted-foreground hover:text-foreground'}" aria-current={index === active ? 'page' : undefined} onmouseenter={() => measure(index)} onmouseleave={() => measure()} onfocus={() => measure(index)} onblur={() => measure()} onclick={() => (active = index)} > {link.label} </a> {/each} </nav> <Button size="sm" class="ml-auto rounded-full">Start free</Button> <Sheet bind:open> <SheetTrigger> {#snippet child({ props })} <Button {...props} variant="ghost" size="icon" class="rounded-full md:hidden" aria-label="Open navigation menu"> <Menu class="size-5" aria-hidden="true" /> </Button> {/snippet} </SheetTrigger> <SheetContent side="top"> <SheetHeader> <SheetTitle>Menu</SheetTitle> </SheetHeader> <nav class="mt-6 grid gap-1" aria-label="Mobile"> {#each links as link (link.href)} <a href={link.href} class="hover:bg-muted rounded-md px-3 py-2 text-sm font-medium transition-colors" onclick={() => (open = false)} > {link.label} </a> {/each} </nav> </SheetContent> </Sheet> </header> </div>src/lib/components/blocks/header/HeaderMegaMenu.svelte8.3 kB
<script lang="ts"> import type { Component } from 'svelte' import { ArrowRight, BarChart3, BookOpen, Boxes, Layers, LifeBuoy, Lock, Menu, Workflow, } from '@lucide/svelte' import { Button } from '$lib/components/ui/button' import { NavigationMenu, NavigationMenuContent, NavigationMenuItem, NavigationMenuList, NavigationMenuTrigger, navigationMenuTriggerStyle, } from '$lib/components/ui/navigation-menu' import { Separator } from '$lib/components/ui/separator' import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from '$lib/components/ui/sheet' interface MegaItem { icon: Component title: string body: string } interface MegaGroup { heading: string items: MegaItem[] } interface MegaMenu { label: string groups: MegaGroup[] highlight: { title: string; body: string; cta: string } } const menus: MegaMenu[] = [ { label: 'Product', groups: [ { heading: 'Core', items: [ { icon: Boxes, title: 'Metric layer', body: 'Versioned definitions your whole org shares.' }, { icon: BarChart3, title: 'Dashboards', body: 'Composed from certified metrics, not raw SQL.' }, { icon: Workflow, title: 'Pipelines', body: 'Scheduled materialisation with cost ceilings.' }, ], }, { heading: 'Governance', items: [ { icon: Lock, title: 'Row-level access', body: 'Scope evaluated per query, per identity.' }, { icon: BookOpen, title: 'Change history', body: 'Every definition edit reviewed and revertible.' }, { icon: LifeBuoy, title: 'Audit exports', body: 'Generated from the same history, not by hand.' }, ], }, ], highlight: { title: 'Ship your first dashboard today', body: 'Connect a warehouse, publish one certified metric, and invite the team. No migration required.', cta: 'Start the walkthrough', }, }, { label: 'Resources', groups: [ { heading: 'Learn', items: [ { icon: BookOpen, title: 'Documentation', body: 'Setup, modelling, and the access model.' }, { icon: Layers, title: 'Guides', body: 'Reconciliation and first-close checklists.' }, { icon: BarChart3, title: 'Benchmarks', body: 'Close speed across 240 finance teams.' }, ], }, { heading: 'Support', items: [ { icon: LifeBuoy, title: 'Help centre', body: 'Answers to the questions support gets most.' }, { icon: Workflow, title: 'Status', body: 'Live uptime and incident history.' }, { icon: Lock, title: 'Trust centre', body: 'SOC 2, subprocessors, and data residency.' }, ], }, ], highlight: { title: 'Read the rollout plan', body: 'The five-week implementation we run for every customer, written down so you can run it yourself.', cta: 'Open the plan', }, }, ] const plainLinks = [ { label: 'Pricing', href: '#pricing' }, { label: 'Customers', href: '#customers' }, ] let open = $state(false) </script> <header data-slot="header-mega-menu" class="border-border bg-background/90 border-b backdrop-blur"> <div class="mx-auto flex h-16 max-w-6xl items-center gap-6 px-6"> <a href="#top" class="flex shrink-0 items-center gap-2 font-semibold tracking-tight"> <Layers class="text-primary size-5" aria-hidden="true" /> Northwind </a> <NavigationMenu class="hidden lg:flex"> <NavigationMenuList> {#each menus as menu (menu.label)} <NavigationMenuItem value={menu.label}> <NavigationMenuTrigger>{menu.label}</NavigationMenuTrigger> <NavigationMenuContent> <div class="grid w-[46rem] grid-cols-[1fr_1fr_16rem] gap-6 p-6"> {#each menu.groups as group (group.heading)} <div> <p class="text-muted-foreground font-mono text-xs tracking-[0.14em] uppercase"> {group.heading} </p> <ul class="mt-3 space-y-1"> {#each group.items as item (item.title)} {@const ItemIcon = item.icon} <li> <a href="#" class="hover:bg-muted focus-visible:ring-ring flex gap-3 rounded-md p-2 transition-colors focus-visible:ring-2 focus-visible:outline-none" > <ItemIcon class="text-muted-foreground mt-0.5 size-4 shrink-0" aria-hidden="true" /> <span class="min-w-0"> <span class="block text-sm font-medium">{item.title}</span> <span class="text-muted-foreground block text-xs leading-snug">{item.body}</span> </span> </a> </li> {/each} </ul> </div> {/each} <!-- Highlight rail: one promoted destination per panel, on the muted surface so it reads as an aside, not a sixth link. --> <div class="bg-muted/50 flex flex-col rounded-lg p-4"> <p class="text-sm font-semibold">{menu.highlight.title}</p> <p class="text-muted-foreground mt-2 text-xs leading-relaxed">{menu.highlight.body}</p> <Button variant="link" class="mt-auto h-auto justify-start p-0 pt-4 text-xs"> {menu.highlight.cta} <ArrowRight class="ml-1 size-3" aria-hidden="true" /> </Button> </div> </div> </NavigationMenuContent> </NavigationMenuItem> {/each} {#each plainLinks as link (link.href)} <NavigationMenuItem value={link.label}> <a href={link.href} class={navigationMenuTriggerStyle()}>{link.label}</a> </NavigationMenuItem> {/each} </NavigationMenuList> </NavigationMenu> <div class="ml-auto flex items-center gap-2"> <Button variant="ghost" size="sm" class="hidden sm:inline-flex">Sign in</Button> <Separator orientation="vertical" class="hidden h-5 sm:block" /> <Button size="sm">Book a demo</Button> </div> <Sheet bind:open> <SheetTrigger> {#snippet child({ props })} <Button {...props} variant="ghost" size="icon" class="ml-auto lg:hidden" aria-label="Open navigation menu"> <Menu class="size-5" aria-hidden="true" /> </Button> {/snippet} </SheetTrigger> <SheetContent side="right" class="w-72 overflow-y-auto"> <SheetHeader> <SheetTitle>Menu</SheetTitle> </SheetHeader> <nav class="mt-6 grid gap-5" aria-label="Mobile"> {#each menus as menu (menu.label)} <div> <p class="text-muted-foreground/70 text-xs font-medium tracking-wide uppercase">{menu.label}</p> <ul class="mt-2 grid gap-1"> {#each menu.groups as group (group.heading)} <li> {#each group.items as item (item.title)} <a href="#" class="hover:bg-muted block rounded-md px-3 py-2 text-sm font-medium transition-colors" onclick={() => (open = false)} > {item.title} </a> {/each} </li> {/each} </ul> </div> {/each} <Separator /> {#each plainLinks as link (link.href)} <a href={link.href} class="hover:bg-muted rounded-md px-3 py-2 text-sm font-medium transition-colors" onclick={() => (open = false)} > {link.label} </a> {/each} <Separator /> <div class="grid gap-2"> <Button variant="outline">Sign in</Button> <Button>Book a demo</Button> </div> </nav> </SheetContent> </Sheet> </div> </header>src/lib/components/blocks/header/HeaderSearchCommand.svelte4.9 kB
<script lang="ts"> import { onMount } from 'svelte' import type { Component } from 'svelte' import { BarChart3, BookOpen, Compass, FileText, History, Menu, Search, Users } from '@lucide/svelte' import { Button } from '$lib/components/ui/button' import { CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from '$lib/components/ui/command' import { Kbd } from '$lib/components/ui/kbd' import { Separator } from '$lib/components/ui/separator' import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from '$lib/components/ui/sheet' const links = [ { label: 'Documentation', href: '#docs' }, { label: 'Components', href: '#components' }, { label: 'Templates', href: '#templates' }, { label: 'Showcase', href: '#showcase' }, ] const groups: { heading: string; items: { icon: Component; label: string }[] }[] = [ { heading: 'Documentation', items: [ { icon: BookOpen, label: 'Getting started' }, { icon: FileText, label: 'Installation guide' }, { icon: BarChart3, label: 'Telemetry & analytics' }, ], }, { heading: 'Company', items: [ { icon: Users, label: 'Customer stories' }, { icon: History, label: 'Changelog' }, ], }, ] let open = $state(false) let menuOpen = $state(false) function onKeydown(event: KeyboardEvent) { if (event.key.toLowerCase() !== 'k' || !(event.metaKey || event.ctrlKey)) return event.preventDefault() open = !open } onMount(() => { window.addEventListener('keydown', onKeydown) return () => window.removeEventListener('keydown', onKeydown) }) </script> <header data-slot="header-search-command" class="border-border bg-background/90 border-b backdrop-blur"> <div class="mx-auto flex h-16 max-w-6xl items-center gap-4 px-6"> <a href="#top" class="flex shrink-0 items-center gap-2 font-semibold tracking-tight"> <Compass class="text-primary size-5" aria-hidden="true" /> Halden </a> <nav class="hidden items-center gap-1 md:flex" aria-label="Primary"> {#each links as link (link.href)} <a href={link.href} class="text-muted-foreground hover:text-foreground hover:bg-muted focus-visible:ring-ring rounded-md px-3 py-1.5 text-sm font-medium transition-colors focus-visible:ring-2 focus-visible:outline-none" > {link.label} </a> {/each} </nav> <!-- Trigger is a button, not an input: the real field lives in the dialog, so focus lands there and the shortcut hint stays visible until then. --> <button type="button" class="border-border bg-muted/40 text-muted-foreground hover:bg-muted focus-visible:ring-ring ml-auto flex h-9 w-full max-w-64 items-center gap-2 rounded-md border px-3 text-sm transition-colors focus-visible:ring-2 focus-visible:outline-none" onclick={() => (open = true)} > <Search class="size-4 shrink-0" aria-hidden="true" /> <span class="truncate">Search docs…</span> <Kbd class="ml-auto hidden sm:inline-flex">⌘K</Kbd> </button> <Separator orientation="vertical" class="hidden h-5 md:block" /> <Button size="sm" class="hidden shrink-0 sm:inline-flex">Start free</Button> <Sheet bind:open={menuOpen}> <SheetTrigger> {#snippet child({ props })} <Button {...props} variant="ghost" size="icon" class="shrink-0 md:hidden" aria-label="Open navigation menu"> <Menu class="size-5" aria-hidden="true" /> </Button> {/snippet} </SheetTrigger> <SheetContent side="right" class="w-72"> <SheetHeader> <SheetTitle>Menu</SheetTitle> </SheetHeader> <nav class="mt-6 grid gap-1" aria-label="Mobile"> {#each links as link (link.href)} <a href={link.href} class="hover:bg-muted rounded-md px-3 py-2 text-sm font-medium transition-colors" onclick={() => (menuOpen = false)} > {link.label} </a> {/each} </nav> <Separator class="my-5" /> <div class="grid gap-2"> <Button variant="outline">Sign in</Button> <Button>Start free</Button> </div> </SheetContent> </Sheet> </div> <CommandDialog bind:open> <CommandInput placeholder="Search documentation, guides, and stories…" /> <CommandList> <CommandEmpty>No results.</CommandEmpty> {#each groups as group (group.heading)} <CommandGroup heading={group.heading}> {#each group.items as item (item.label)} {@const ItemIcon = item.icon} <CommandItem value={item.label}> <ItemIcon class="text-muted-foreground mr-2 size-4" aria-hidden="true" /> {item.label} </CommandItem> {/each} </CommandGroup> {/each} </CommandList> </CommandDialog> </header>src/lib/components/blocks/header/HeaderTransparentScroll.svelte3 kB
<script lang="ts"> import { onMount } from 'svelte' import { Layers, Menu } from '@lucide/svelte' import { Button } from '$lib/components/ui/button' import { Separator } from '$lib/components/ui/separator' import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from '$lib/components/ui/sheet' const links = [ { label: 'Product', href: '#product' }, { label: 'Solutions', href: '#solutions' }, { label: 'Pricing', href: '#pricing' }, { label: 'Docs', href: '#docs' }, ] // Starts unscrolled so server and first client paint agree; the listener is the // only thing that swaps in the solid surface. let scrolled = $state(false) let open = $state(false) function onScroll() { scrolled = window.scrollY > 24 } onMount(() => { onScroll() window.addEventListener('scroll', onScroll, { passive: true }) return () => window.removeEventListener('scroll', onScroll) }) </script> <header data-slot="header-transparent-scroll" class="fixed inset-x-0 top-0 z-40 transition-colors duration-200 {scrolled ? 'border-border bg-background/85 border-b backdrop-blur' : 'border-b border-transparent'}" > <div class="mx-auto flex h-16 max-w-6xl items-center gap-6 px-6"> <a href="#top" class="flex items-center gap-2 font-semibold tracking-tight"> <Layers class="text-primary size-5" aria-hidden="true" /> Northwind </a> <nav class="hidden items-center gap-1 md:flex" aria-label="Primary"> {#each links as link (link.href)} <a href={link.href} class="text-muted-foreground hover:text-foreground hover:bg-muted focus-visible:ring-ring rounded-md px-3 py-1.5 text-sm font-medium transition-colors focus-visible:ring-2 focus-visible:outline-none" > {link.label} </a> {/each} </nav> <div class="ml-auto hidden items-center gap-2 md:flex"> <Button variant="ghost" size="sm">Sign in</Button> <Button size="sm">Start free</Button> </div> <Sheet bind:open> <SheetTrigger> {#snippet child({ props })} <Button {...props} variant="ghost" size="icon" class="ml-auto md:hidden" aria-label="Open navigation menu"> <Menu class="size-5" aria-hidden="true" /> </Button> {/snippet} </SheetTrigger> <SheetContent side="right" class="w-72"> <SheetHeader> <SheetTitle>Menu</SheetTitle> </SheetHeader> <nav class="mt-6 grid gap-1" aria-label="Mobile"> {#each links as link (link.href)} <a href={link.href} class="hover:bg-muted rounded-md px-3 py-2 text-sm font-medium transition-colors" onclick={() => (open = false)} > {link.label} </a> {/each} </nav> <Separator class="my-5" /> <div class="grid gap-2"> <Button variant="outline">Sign in</Button> <Button>Start free</Button> </div> </SheetContent> </Sheet> </div> </header>
Raw manifest:https://uipkge.dev/r/svelte/header.json