# Navbar Floating

> Navbar flutuante com blur, borda e menu mobile — inspirado em Launch UI Navbar Floating.

A shadcn/ui block from the [@lema-ds](https://ds.lema.ufpb.br) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/lema-ds/ds-navbar-floating).

- Page, with a live preview: https://shadcn.exchange/r/lema-ds/ds-navbar-floating
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/lema-ds/ds-navbar-floating-light-882e4716fe364389.png
- Registry item: https://ds.lema.ufpb.br/r/ds-navbar-floating.json
- Categories: header, navbar
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://ds.lema.ufpb.br/r/ds-navbar-floating.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- npm packages: `class-variance-authority`, `lucide-react`
- Registry items: `@lema-ds/button`, `@lema-ds/skeleton`

## Files

### `components/ds/ds-navbar-floating.tsx`

```tsx
"use client"

import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"
import { MenuIcon, XIcon } from "lucide-react"

import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import { Skeleton } from "@/components/ui/skeleton"

// ── Types ──

export interface NavbarFloatingLink {
  label: string
  href: string
  active?: boolean
}

export interface NavbarFloatingProps
  extends
    React.HTMLAttributes<HTMLElement>,
    VariantProps<typeof navbarFloatingVariants> {
  brand?: React.ReactNode
  links?: NavbarFloatingLink[]
  actions?: React.ReactNode
  loading?: boolean
}

// ── Variants ──

export const navbarFloatingVariants = cva(
  "mx-auto flex w-full max-w-5xl items-center justify-between gap-4 rounded-2xl border bg-card/80 px-4 py-2 shadow-sm backdrop-blur-md",
  {
    variants: {
      variant: {
        default: "",
        muted: "bg-muted/70",
      },
      size: {
        sm: "h-12",
        md: "h-14",
        lg: "h-16",
      },
    },
    defaultVariants: {
      variant: "default",
      size: "md",
    },
  }
)

// ── Component ──

export function NavbarFloating({
  className,
  variant = "default",
  size = "md",
  brand = <span className="text-sm font-bold tracking-tight">Launch UI</span>,
  links = [
    { label: "Getting started", href: "#" },
    { label: "Components", href: "#" },
    { label: "Documentation", href: "#" },
  ],
  actions,
  loading = false,
  ...props
}: NavbarFloatingProps) {
  const [open, setOpen] = React.useState(false)

  if (loading) {
    return (
      <div className="w-full p-4">
        <Skeleton
          className={cn(navbarFloatingVariants({ variant, size }), "w-full")}
        />
      </div>
    )
  }

  return (
    <header
      data-slot="navbar-floating"
      role="banner"
      className={cn("sticky top-4 z-40 w-full px-4", className)}
      {...props}
    >
      <nav
        aria-label="Main navigation"
        className={cn(navbarFloatingVariants({ variant, size }))}
      >
        <a
          href="#"
          className="flex items-center gap-2 focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none"
        >
          {brand}
        </a>

        <div className="hidden items-center gap-1 md:flex">
          {links.map((link) => (
            <a
              key={link.label}
              href={link.href}
              aria-current={link.active ? "page" : undefined}
              className={cn(
                "rounded-full px-3 py-1.5 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none",
                link.active && "bg-accent text-accent-foreground"
              )}
            >
              {link.label}
            </a>
          ))}
        </div>

        <div className="flex items-center gap-2">
          <div className="hidden items-center gap-2 md:flex">
            {actions ?? (
              <>
                <Button variant="ghost" size="sm" className="rounded-full">
                  Sign in
                </Button>
                <Button size="sm" className="rounded-full">
                  Get Started
                </Button>
              </>
            )}
          </div>

          <Button
            variant="ghost"
            size="icon-sm"
            className="md:hidden"
            aria-label={open ? "Close menu" : "Open menu"}
            aria-expanded={open}
            aria-controls="navbar-floating-mobile"
            onClick={() => setOpen((v) => !v)}
          >
            {open ? (
              <XIcon className="size-4" />
            ) : (
              <MenuIcon className="size-4" />
            )}
          </Button>
        </div>
      </nav>

      {open && (
        <div
          id="navbar-floating-mobile"
          className="mx-auto mt-2 max-w-5xl rounded-2xl border bg-card p-4 shadow-lg md:hidden"
        >
          <div className="flex flex-col gap-2">
            {links.map((link) => (
              <a
                key={link.label}
                href={link.href}
                className="rounded-lg px-3 py-2 text-sm font-medium hover:bg-accent"
                onClick={() => setOpen(false)}
              >
                {link.label}
              </a>
            ))}
            <div className="mt-2 flex flex-col gap-2 border-t pt-3">
              {actions ?? (
                <>
                  <Button variant="outline" className="w-full rounded-full">
                    Sign in
                  </Button>
                  <Button className="w-full rounded-full">Get Started</Button>
                </>
              )}
            </div>
          </div>
        </div>
      )}
    </header>
  )
}
```
