File: src/blocks/navbar/Navbar01.astro
Sticky full-bleed site header with desktop links (optional dropdowns), mobile panel, and CTA. Wired in BaseLayout. Floating alternative: Navbar 02.
For chrome-specific props and live demos, open a Navbar version. For authoring links, sections, and mega menus, see the Navigation guide.
Types: src/lib/nav.ts · Client: src/scripts/navbar.ts
Mobile: hamburger + slide panel below md. Dropdown parents expand into a vertical accordion list.
Config (identity.ts → navigation)
Logo paths and site name come from identity (name, logo assets). Edit navigation for links, dropdowns, CTA, and desktop trigger mode:
// src/config/identity.ts
navigation: {
sticky: true,
// Desktop dropdowns: "hover" | "click" (mobile accordion is always tap)
dropdownTrigger: "hover",
// Bottom stroke (Navbar 01 only)
borderBottom: true,
borderThickness: "sm", // "sm" | "md" | "lg"
borderColor: "soft", // "soft" | "medium" | "hard"
links: [
// Simple top-level link
{ label: "Work", href: "/work/" },
// Dropdown — children only (trigger has no own URL)
{
label: "Docs",
children: [
{ label: "Get started", href: "/docs/get-started/" },
{ label: "Blocks", href: "/docs/blocks/" },
{ label: "Components", href: "/docs/components/" },
],
},
// Dropdown — parent href + children (short form)
// Or use `sections` for mega menus — see Navbar 04
// Label links to href; chevron opens the menu. Also drives active-state matching.
{
label: "Services",
href: "/services/",
children: [
{ label: "Strategy", href: "/services/strategy/" },
{ label: "Build", href: "/services/build/" },
{ label: "Support", href: "/services/support/" },
],
},
{ label: "About", href: "/about/" },
{ label: "Contact", href: "/contact/" },
],
cta: {
label: "Hire me",
href: "/contact/",
size: "sm", // "sm" | "md" | "lg"
},
},
Link shapes
| Example | Shape | Result |
|---|---|---|
| Work | { label, href } |
Plain link |
| Docs | { label, children } |
Dropdown trigger; menu is children only |
| Services | { label, href, children } |
Dropdown; href is first item + active match |
import type { NavLink } from "@/lib/nav";
const links: NavLink[] = [
{ label: "Work", href: "/work/" },
{
label: "Docs",
children: [
{ label: "Get started", href: "/docs/get-started/" },
{ label: "Blocks", href: "/docs/blocks/" },
],
},
{
label: "Services",
href: "/services/",
children: [
{ label: "Strategy", href: "/services/strategy/" },
{ label: "Build", href: "/services/build/" },
],
},
];
| Field | Type | Notes |
|---|---|---|
label |
string |
Trigger / link text |
href |
string? |
Omit for dropdown-only triggers. With children / sections, the label links to this URL and the chevron opens the menu |
children |
{ label, href }[]? |
Short-form list → one panel section via resolveNavSections |
width |
sm | md | lg | xl? |
Per-parent dropdown panel width (overrides dropdownWidth) |
sections |
NavMegaSection[]? |
Modular mega columns — see Navbar 04 |
Dropdown panel width
Resolution: link.width → dropdownWidth prop → "sm" (Navbar 01 default for single-column lists).
| Preset | Approx. panel width |
|---|---|
sm |
20rem (default) |
md |
28rem |
lg |
40rem |
xl |
56rem |
{
label: "Docs",
href: "/docs/",
width: "md", // this menu only
children: [
{ label: "Get started", href: "/docs/get-started/" },
{ label: "Blocks", href: "/docs/blocks/" },
],
}
<Navbar01 dropdownWidth="md" />
Bottom stroke (borderBottom)
Navbar 01’s full-bleed bar can show a bottom border. Defaults match the previous look (true + sm + soft).
| Value | Thickness | Color token |
|---|---|---|
borderThickness: "sm" |
1px (border-b) |
— |
borderThickness: "md" |
2px (border-b-2) |
— |
borderThickness: "lg" |
4px (border-b-4) |
— |
borderColor: "soft" |
— | border-line-soft |
borderColor: "medium" |
— | border-line |
borderColor: "hard" |
— | border-soft |
navigation: {
borderBottom: true,
borderThickness: "md",
borderColor: "medium",
// …
},
Turn the stroke off:
<Navbar01 borderBottom={false} />
Or override thickness / color on the instance:
<Navbar01 borderThickness="lg" borderColor="hard" />
Desktop trigger (dropdownTrigger)
| Value | Behavior |
|---|---|
"click" |
Open / close on click (default if unset) |
"hover" |
Open on pointer enter, close on leave (short delay). Click still toggles for touch |
Escape and outside click close open menus. Mobile always uses tap-to-expand; sub-links render as a vertical list under the parent.
navigation: {
dropdownTrigger: "click", // or "hover"
links: [/* … */],
cta: { /* … */ },
},
Override per instance:
<Navbar01 dropdownTrigger="click" />
Add to a page
---
import Navbar01 from "@/blocks/navbar/Navbar01.astro";
---
<Navbar01 />
Props override matching keys from config — including inline dropdown links:
<Navbar01
sticky={false}
dropdownTrigger="click"
links={[
{ label: "Home", href: "/" },
{
label: "Product",
children: [
{ label: "Features", href: "/features/" },
{ label: "Pricing", href: "/pricing/" },
],
},
{
label: "Resources",
href: "/resources/",
children: [
{ label: "Blog", href: "/blog/" },
{ label: "Guides", href: "/guides/" },
],
},
]}
/>
Props
| Prop | Config key | Type / values | Default / notes |
|---|---|---|---|
links |
navigation.links |
NavLink[] |
Optional children; per-parent width for panel size |
dropdownWidth |
navigation.dropdownWidth |
sm | md | lg | xl |
Default panel width; default sm; overridable per parent via links[].width |
dropdownTrigger |
navigation.dropdownTrigger |
click | hover |
Desktop only; default click |
borderBottom |
navigation.borderBottom |
boolean |
Bottom stroke on/off; default true |
borderThickness |
navigation.borderThickness |
sm | md | lg |
Stroke weight when enabled |
borderColor |
navigation.borderColor |
soft | medium | hard |
Stroke contrast when enabled |
ctaLabel |
navigation.cta.label |
string |
— |
ctaHref |
navigation.cta.href |
string |
— |
ctaSize |
navigation.cta.size |
sm | md | lg |
— |
sticky |
navigation.sticky |
boolean |
Pin the navbar while scrolling |
