Skip to content

shadcn.io is an independent project built on shadcn/ui

Mixed Content Types Navigation Menu for Solid

A Solutions mega menu of four solution cards, some with badges, plus a webinar promo and a Start Building panel.

UI library: Ark UI

The bar shows Solutions. The panel mixes solution cards, including Developer Platform and Design System, some with Popular or New badges, a webinar with Watch Now, and Start Building with two buttons.

Mix links, a promo, and a signup when the header is doing more than navigation. Keep a single list in a Dropdown Menu when that is all you need. In Solid, Ark UI closes the open panel when you press Escape.

Preview

Preview width

Installation

MCP · Pro
Make your AI a shadcn expert
Your agent installs components, builds pages and restyles your app from one prompt, in Claude Code, Cursor or VS Code.
Part of Pro

Anatomy

Navigation Menu anatomy: list, trigger, indicator, content, link

Usage

<div class="w-full max-w-md rounded-md border bg-background p-px">
    <NavigationMenu>
      <NavigationMenuList>
        <NavigationMenuItem>
          <NavigationMenuTrigger>Solutions</NavigationMenuTrigger>
          <NavigationMenuContent>
            <div class="grid w-[800px] max-w-full grid-cols-[1fr_300px] gap-6 p-4">
              <div class="grid grid-cols-2 gap-x-6 gap-y-4">
                {solutions.map(solution => <NavigationMenuLink asChild={props => <a {...props()} href="#">
                      <div class="flex items-center justify-between gap-2">
                        <Dynamic component={solution.icon} aria-hidden="true" class="size-5" />
                        {solution.badge ? <Badge variant={solution.badgeVariant}>
                            {solution.badge}
                          </Badge> : null}
                      </div>
                      <div class="flex flex-col gap-0.5">
                        <span class="font-medium">{solution.title}</span>
                        <span class="text-muted-foreground">
                          {solution.description}
                        </span>
                      </div>
                    </a>} class="flex-col items-stretch justify-between gap-4" />)}
              </div>
              <div class="flex flex-col gap-4">
                <div class="overflow-hidden rounded-lg bg-muted">
                  <div class="aspect-video bg-linear-to-br from-primary/20 to-primary/5" />
                  <div class="flex flex-col items-start gap-1 p-4">
                    <Badge class="mb-1">Webinar</Badge>
                    <h4 class="font-semibold">Building at Scale</h4>
                    <p class="mb-2 text-muted-foreground text-sm">
                      Learn how teams scale their applications
{/* The rest of the file is under Installation. */}

FAQ

How are the solution cards built?

Each card is a NavigationMenuLink with flex-col: the icon and an optional Badge on top, the title and description below.

Do the buttons navigate?

Not in the demo: Watch Now, Create Account and View Docs are Buttons with no handler. Link them to their pages.

What happens on narrow screens?

The panel is w-[800px] with max-w-full, so it never grows past the screen, but its columns get tight. Below the md breakpoint, show the same links in a Sheet or a Drawer instead.

How do the links use my router?

Each link is your router's link rendered through NavigationMenuLink, so it keeps the menu's styles and focus handling. NavigationMenuLink takes asChild, a function that renders your router's A with the props it gets.

How does the menu work from the keyboard?

Tab moves between the triggers and the links, Enter or Space opens a trigger's panel, and Escape closes it and returns focus to the trigger. The root is a nav, so screen readers list it as a navigation landmark.

How do I mark the current page?

Set aria-current="page" on the NavigationMenuLink that matches the route, and style it with the aria-[current=page]: variant.

API Reference

Navigation Menu

Sets asChild and props. The rest is on the Navigation Menu page.

Badge

Sets variant={solution.badgeVariant}. The rest is on the Badge page.

Button

Sets size="sm" and variant="outline". The rest is on the Button page.