Menu

Change language

GitHub repo

Header — Mega Menu

blockmarketing

Navbar whose product and resources items open a full-width mega panel of grouped, described links plus a highlighted feature card, keyboard navigable and closing on Escape.

Installation

$npx shadcn-svelte@latest add https://uipkge.dev/r/svelte/header-mega-menu.json
Manifest:https://uipkge.dev/r/svelte/header-mega-menu.jsonInstalls to:src/lib/components/blocks/header-mega-menu/

Variants

Loading interactive previews…

Files installed (1)

  • src/lib/components/blocks/header-mega-menu/HeaderMegaMenu.svelte8 kB
    <script lang="ts">
      import { ArrowRight, BarChart3, BookOpen, Boxes, Layers, LifeBuoy, Lock, Menu, Workflow } from '@lucide/svelte'
      import { Button } from '$lib/components/ui/button'
      import {
        NavigationMenu,
        NavigationMenuContent,
        NavigationMenuItem,
        NavigationMenuLink,
        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'
    
      const menus = [
        {
          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 Icon = 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"
                              >
                                <Icon 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}>
                <NavigationMenuLink href={link.href} class={navigationMenuTriggerStyle()}>{link.label}</NavigationMenuLink>
              </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 variant="ghost" size="icon" {...props} 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>
    

Raw manifest:https://uipkge.dev/r/svelte/header-mega-menu.json