# Navbar Sliding Highlight — React Navbar Component

> A pill glides between links as you hover or tab through them, then settles back on the current page when you leave.

- Category: [Navbars](https://pixelpapa.com/components/navbars.md)
- Tags: navbar, hover, layout animation, pill, tabs
- Dependencies: motion (plus React and Tailwind CSS v4)
- Last updated: 2026-11-13
- Live preview: https://pixelpapa.com/components/navbars/navbar-sliding-highlight

## Install

```bash
npx shadcn@latest add "https://pixelpapa.com/r/navbar-sliding-highlight.json"
```

The file is written to `components/pixelpapa/navbar-sliding-highlight.tsx`. To install manually, run `npm install motion` and copy the source below into your project. It imports `cn` from `@/lib/utils`, which every shadcn project has.

## Source

```tsx
"use client";

import { motion } from "motion/react";
import { useId, useState } from "react";
import { cn } from "@/lib/utils";

type NavLink = { label: string; href: string; badge?: string };

type NavbarSlidingHighlightProps = {
  links?: NavLink[];
  /** Index of the current page. */
  defaultActive?: number;
  className?: string;
};

const defaultLinks: NavLink[] = [
  { label: "Overview", href: "#" },
  { label: "Routes", href: "#" },
  { label: "Fleet", href: "#" },
  { label: "Drivers", href: "#", badge: "3" },
  { label: "Reports", href: "#" },
];

export function NavbarSlidingHighlight({
  links = defaultLinks,
  defaultActive = 0,
  className,
}: NavbarSlidingHighlightProps) {
  const id = useId();
  const [active, setActive] = useState(defaultActive);
  const [hovered, setHovered] = useState<number | null>(null);
  const target = hovered ?? active;

  return (
    <header className={cn("border-b border-border bg-background", className)}>
      <div className="mx-auto flex h-16 max-w-5xl items-center justify-between gap-4 px-6">
        <a href="#" className="flex items-center gap-2 text-sm font-semibold text-foreground">
          <svg viewBox="0 0 24 24" className="size-6 text-primary" aria-hidden>
            <path d="M3 17 L9 5 L15 17 Z" fill="currentColor" opacity="0.45" />
            <path d="M9 17 L15 5 L21 17 Z" fill="currentColor" />
          </svg>
          Waypoint
        </a>

        <nav aria-label="Main" onPointerLeave={() => setHovered(null)}>
          <ul className="flex items-center rounded-full border border-border bg-muted/60 p-1">
            {links.map((link, i) => (
              <li key={link.label}>
                <a
                  href={link.href}
                  aria-current={active === i ? "page" : undefined}
                  onPointerEnter={() => setHovered(i)}
                  onFocus={() => setHovered(i)}
                  onBlur={() => setHovered(null)}
                  onClick={(e) => {
                    e.preventDefault();
                    setActive(i);
                  }}
                  className={cn(
                    "relative flex h-8 items-center gap-1.5 rounded-full px-3.5 text-sm outline-offset-2 transition-colors duration-200 sm:px-4",
                    target === i ? "text-foreground" : "text-muted-foreground",
                  )}
                >
                  {target === i && (
                    <motion.span
                      layoutId={`navbar-sliding-highlight-pill-${id}`}
                      transition={{ type: "spring", stiffness: 420, damping: 34, mass: 0.7 }}
                      className="absolute inset-0 rounded-full bg-background shadow-sm ring-1 ring-border"
                    />
                  )}
                  <span className="relative">{link.label}</span>
                  {link.badge && (
                    <span className="relative rounded-full bg-primary px-1.5 text-[10px] leading-4 font-semibold text-primary-foreground">
                      {link.badge}
                    </span>
                  )}
                  {active === i && (
                    <motion.span
                      layoutId={`navbar-sliding-highlight-dot-${id}`}
                      transition={{ type: "spring", stiffness: 300, damping: 26 }}
                      className="absolute inset-x-0 -bottom-[11px] mx-auto h-[3px] w-4 rounded-full bg-primary"
                    />
                  )}
                </a>
              </li>
            ))}
          </ul>
        </nav>

        <div className="flex items-center gap-3">
          <span className="hidden items-center gap-1.5 text-xs text-muted-foreground md:flex">
            <span className="size-1.5 rounded-full bg-emerald-500" /> 128 vehicles live
          </span>
          <span className="flex size-8 items-center justify-center rounded-full bg-primary/10 text-xs font-semibold text-primary">
            IM
          </span>
        </div>
      </div>
    </header>
  );
}

const lanes = [
  { id: "R-204", from: "Rotterdam", to: "Lyon", eta: "14:20", pct: 72 },
  { id: "R-198", from: "Gdańsk", to: "Prague", eta: "16:05", pct: 41 },
  { id: "R-211", from: "Porto", to: "Madrid", eta: "11:48", pct: 93 },
];

export default function NavbarSlidingHighlightDemo() {
  return (
    <div className="h-[420px] w-full overflow-hidden bg-background">
      <NavbarSlidingHighlight />
      <div className="mx-auto max-w-5xl px-6 pt-10">
        <h2 className="text-2xl font-semibold tracking-tight text-foreground">Good morning, Ines</h2>
        <p className="mt-1 text-sm text-muted-foreground">Three routes are on the road. One needs a decision.</p>
        <div className="mt-6 grid gap-4 sm:grid-cols-3">
          {lanes.map((lane) => (
            <div key={lane.id} className="rounded-2xl border border-border bg-card p-5">
              <div className="flex items-center justify-between text-xs text-muted-foreground">
                <span className="font-mono">{lane.id}</span>
                <span>ETA {lane.eta}</span>
              </div>
              <p className="mt-3 font-medium text-card-foreground">
                {lane.from} → {lane.to}
              </p>
              <div className="mt-4 h-1.5 overflow-hidden rounded-full bg-muted">
                <div className="h-full rounded-full bg-primary" style={{ width: `${lane.pct}%` }} />
              </div>
              <p className="mt-2 text-xs text-muted-foreground tabular-nums">{lane.pct}% of distance covered</p>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}
```

## AI prompt

```text
Add the "Navbar Sliding Highlight" component from PixelPapa UI to this project.

What it is: A pill glides between links as you hover or tab through them, then settles back on the current page when you leave.
Category: Navbars. Depends on: motion.

1. Install it with the shadcn CLI:
   npx shadcn@latest add "https://pixelpapa.com/r/navbar-sliding-highlight.json"
   (If the CLI is unavailable, fetch that URL, write files[0].content to components/pixelpapa/navbar-sliding-highlight.tsx and install the listed dependencies.)
2. Import it from "@/components/pixelpapa/navbar-sliding-highlight" and place it where I describe below.
3. Keep its animation timings and accessibility attributes. Replace the demo copy and data with content that fits my product, and use my existing theme tokens (bg-background, text-foreground, bg-primary, border-border) rather than hard-coded colours.

Where to use it: <describe the page and position here>
```

## More navbars

- [Navbar Announcement Bar](https://pixelpapa.com/components/navbars/navbar-announcement-bar.md) (Pro): A navbar topped by a dismissible strip that ticks through announcements and folds away with a spring when closed.
- [Navbar Centered Logo](https://pixelpapa.com/components/navbars/navbar-centered-logo.md) (Pro): An editorial storefront header with a serif wordmark between two link groups; labels roll on hover and the bag count pops when it changes.
- [Navbar Command Search](https://pixelpapa.com/components/navbars/navbar-command-search.md) (Pro): A docs navbar whose compact search field widens on focus or ⌘K into a filterable result list with arrow-key navigation.
- [Navbar Dynamic Island](https://pixelpapa.com/components/navbars/navbar-dynamic-island.md) (Pro): A compact black pill of links that swells on a spring into a live notification, drains a timer line, then shrinks back to navigation.
- [Navbar Floating Pill](https://pixelpapa.com/components/navbars/navbar-floating-pill.md) (Pro): A floating pill navbar that condenses as you scroll: it narrows on a spring, drops its release chip and swaps the CTA label for an arrow.
- [Navbar Glass Blur](https://pixelpapa.com/components/navbars/navbar-glass-blur.md): A frosted floating navbar that blurs and saturates whatever scrolls beneath it, with a specular highlight that tracks the pointer along the glass.
