Block Nav — React Page Block
Complete navigation bar: brand, desktop links, actions, and an accessible mobile sheet. Sticky variant gains a scrim once the page scrolls.

Usage
import { BlockNav } from "@/components/BlockNav";
export function SiteHeader() {
return (
<BlockNav
brand="Northwind"
links={[
{ label: "Product", href: "#product" },
{ label: "Pricing", href: "#pricing" },
{ label: "FAQ", href: "#faq" },
]}
action={{ label: "Get started", href: "/start" }}
sticky
{...{
brand: "Northwind",
accent: "#d5ed9a",
scheme: "dark"
}}
/>
);
}Implementation notes & API
Purpose: complete navigation bar with a real mobile menu (Escape closes, links stay keyboard reachable). Copy it, ship it — every string, link and color arrives through props. Runtime: pure DOM + CSS. No WebGPU, canvas, animation library or external assets; SSR-safe on first render. Theming: root custom properties (--vb-bg, --vb-fg, --vb-accent, --vb-border, --vb-radius, --vb-container) or the accent/scheme/className/style props. scheme flips the dark default to light. Guardrails: responsive via container queries down to 320px; interactive behavior degrades on touch; prefers-reduced-motion drops entrance/scroll motion while content stays complete. The mobile sheet renders only when open; at 860px+ the burger disappears entirely.
| Property | Type | Notes / default |
|---|---|---|
brand | string | Your brand; the monogram tile is generated from it |
brandHref | string | #top; destination for the brand link |
links | readonly NavLink[] | [{ label, href }]; desktop nav and mobile sheet |
action | { label, href } | null | Primary right-side action; real link |
secondaryAction | { label, href } | null | Quiet secondary link; null hides it |
sticky | boolean | false; sticky bars overlay content when enabled |
scheme | "dark" | "light" | dark |
accent | string (hex) | Sets --vb-accent for the whole block |
className / style | string / CSSProperties | Applied to the section root |
children | ReactNode | Replaces the default content entirely |