Site top navigation in four characters — corporate bar, restaurant split, minimal full-screen menu, SaaS rail. Server component: the mobile menu is a native popover (0 JS), submenus a ~1 KB disclosure island rendered only when items have children, and the scrolled background a CSS scroll timeline.
Installation
The whole kit as one package — get updates by bumping the version. Add the styles to globals.css: @import "@vamos-ui/react/styles.css";
Usage
import { Navbar } from "@vamos-ui/react/blocks";
<Navbar
wordmark="Kıyı"
items={[{ label: "Menu", href: "/menu" }, { label: "Private dining", href: "/private-dining", children: [...] }]}
phone="+902160000000" // E.164; shown as 0216 000 00 00 for tr, tel: link
actions={[{ link: { href: "/reservations", label: "Book a table" }, style: "primary" }]}
currentPath={pathname} // aria-current="page"
sticky
/>The navbar lays out by its own width (container queries): links appear from 56rem, the phone from 72rem — so it behaves the same in a builder iframe and on a phone.
Examples
Split (restaurant)
Logo dead centre, links on both sides, the CTA as a text link, EN / TR switch with hreflang.
Minimal over a full-bleed hero
overlay starts transparent with light text and pulls the hero up under it. “Menu” opens a full-screen popover with display-size links and address/hours.
Meyhane · Cevizli
Dinner, slowly.
Twenty-two cold meze and fish from the morning boats.
Rail (SaaS)
Links inside one framed pill (glassy in glass mode), Sign in + Try free at the end.
Submenus with descriptions
A disclosure dropdown: Enter/Space toggles, ArrowDown/Up move through links, Escape closes and returns focus, leaving the group closes it. The group is marked active when the current page is inside it.
API
Navbar
| Prop | Type | Default |
|---|---|---|
variantLayout character (see examples). | "bar" | "split" | "minimal" | "rail" | "bar" |
wordmarkText mark (display font). Used when there's no logo, or beside it. | ReactNode | — |
logo / logoDarkLogo, and the artwork shown inside dark sections (never invert()). | ImageData | — |
homeHrefBrand link. | string | "/" |
items{ label, href, description?, newTab?, children?: NavbarLink[] } — ≤ 7 items, ≤ 8 children. | NavbarItem[] | [] |
actions≤ 2; later primaries are demoted. bar/minimal show one; split shows a text link; rail shows ghost + primary. | SiteCta[] | — |
phoneNational format in the number's own locale, international elsewhere; tel: link with data-track="call". | string (E.164) | — |
localesLanguage switch (“EN / TR”), hreflang + lang on each link. | { code; href; current? }[] | — |
stickySticks to the top; background and hairline fill in on scroll (animation-timeline: scroll(); glass blur in glass mode). | boolean | false |
overlayTransparent with light text over a hero; overlaps the next section by the bar height. | boolean | false |
currentPathSets aria-current="page" (+ 2px accent underline) and the active group. | string | — |
panelMetaFacts at the bottom of the full-screen menu (address, hours). | SiteMeta[] | — |
skipLinkRenders “Skip to content” first in the DOM. | boolean | true |
labelsmainNavigation, openMenu, closeMenu, menuDialog, languages, callUs, phoneLabel. | Partial<Site1Labels> | — |
locale / components / id / anchor / classNameIntl locale, framework Link/Image adapters, ids. | BlockBaseProps | — |
formatSitePhone(e164, locale)
| Prop | Type | Default |
|---|---|---|
returns“0216 000 00 00” for a TR number in tr, “+90 216 000 00 00” elsewhere. | string | — |