Folder: src/components/nav/ · Types: src/lib/nav.ts · Client: src/scripts/navbar.ts
Navbar blocks (Navbar01–Navbar06) own chrome only — logo, sticky bar, CTA, mobile / overlay shell. Dropdown and mega-menu content is rendered by small presentational components driven by config in identity.ts → navigation.
flowchart TB
identity["identity.ts navigation.links"] --> resolve["resolveNavSections"]
resolve -->|"sections"| sections["NavMegaSection[]"]
resolve -->|"children only"| wrap["one links or icon-links section"]
wrap --> sections
sections --> desktop["NavMegaPanel"]
sections --> mobile["NavMobileSections"]
desktop --> featured["NavFeatured"]
desktop --> iconList["NavIconList"]
desktop --> linkList["NavLinkList"]
mobile --> featured
mobile --> iconList
mobile --> linkList
Live previews: Navbar overview · Navbar 04 mega · Navbar 05 drawer · Navbar 06 fullscreen
Mental model
| Layer | Responsibility |
|---|---|
identity.ts → navigation |
Links, dropdowns, CTA, trigger mode, defaults |
src/lib/nav.ts |
Types + helpers (resolveNavSections, width, active state) |
src/components/nav/* |
Panel UI pieces |
src/blocks/navbar/* |
Header chrome + wires config → panels |
src/scripts/navbar.ts |
Hover/click open, mobile accordion |
Edit config first. Fork components only when you need a new section type.
Quick start
1. Simple link
{ label: "Pricing", href: "/pricing/" }
2. Dropdown (short form)
{
label: "Services",
href: "/services/", // optional — label links here; chevron opens menu
children: [
{ label: "Strategy", href: "/services/strategy/" },
{ label: "Build", href: "/services/build/" },
],
}
resolveNavSections turns children into one section:
- Any child has
iconordescription→icon-links - Otherwise →
links
3. Rich dropdown (icons + descriptions)
{
label: "Product",
href: "/product/",
children: [
{
label: "Features",
href: "/features/",
description: "Everything included in the kit.",
icon: "sparkles",
iconSize: 20, // optional override
},
{
label: "Pricing",
href: "/pricing/",
description: "Simple plans for teams.",
icon: "badge-dollar-sign",
},
],
}
4. Mega menu (mixed sections)
{
label: "Docs",
href: "/docs/",
width: "xl",
sections: [
{
type: "featured",
title: "Featured",
titleStroke: true,
image: "/images/nav/featured.webp",
imageAspect: "16/10",
label: "Get started",
href: "/docs/get-started/",
description: "Install, structure, and first steps.",
},
{
type: "icon-links",
title: "Explore",
titleStroke: true,
items: [
{
label: "Blocks",
href: "/docs/blocks/",
description: "Full-width sections and version docs.",
icon: "layout-template",
},
],
},
{
type: "links",
title: "More",
titleStroke: true,
items: [
{ label: "Customize", href: "/docs/customize/" },
{ label: "Site config", href: "/docs/site-config/" },
],
},
],
}
Prefer sections when you need more than one column or a featured block. Prefer children for a single list.
Parent link behavior
| Config | Desktop | Mobile |
|---|---|---|
children / sections only |
Whole control opens the menu | Accordion trigger |
href + dropdown |
Label navigates; chevron opens menu | Label navigates; chevron expands |
Top-level href only |
Plain link | Plain link |
Active state uses color (text-strong), not a heavier weight. A parent is active when its href or any nested item href matches the current path.
Section types
featured
Image card with title/description under it — one link for the whole card.
| Field | Required | Notes |
|---|---|---|
type |
yes | "featured" |
image |
yes | Public path or URL (e.g. /images/nav/featured.webp) |
label |
yes | Link title under the image |
href |
yes | Destination |
imageAlt |
no | Defaults to label |
imageAspect |
no | Crop box: square | 4/3 | 3/2 | 16/10 (default) | 16/9 | 2/1. Image uses object-cover so it never stretches |
description |
no | text-xs under the label |
title |
no | Column grouping label |
titleStroke |
no | Soft underline under title |
icon-links
Rows with optional Lucide icon, label (text-sm), and description (text-xs).
| Field | Required | Notes |
|---|---|---|
type |
yes | "icon-links" |
items |
yes | NavChildLink[] — label, href, optional description, icon, iconSize |
columns |
no | 1–4 for an inner grid |
title |
no | Column grouping label |
titleStroke |
no | Soft underline under title |
Icons: Lucide kebab-case names from lucide.dev/icons. Default size from navigation.dropdownIconSize (default 20); override per item with iconSize.
links
Plain label-only list (same visual weight as icon-link titles).
| Field | Required | Notes |
|---|---|---|
type |
yes | "links" |
items |
yes | { label, href }[] |
columns |
no | 1–4 |
title |
no | Column grouping label |
titleStroke |
no | Soft underline under title |
Section titles
Optional title on any section. Renders via NavSectionTitle — 10px, uppercase, muted.
{ type: "links", title: "Resources", titleStroke: true, items: [/* … */] }
Navigation config defaults
Set once under navigation in identity.ts:
| Key | Type | Default / notes |
|---|---|---|
links |
NavLink[] |
Top-level items |
cta |
{ label, href, size } |
Header CTA |
sticky |
boolean |
Pin full-bleed bars |
dropdownTrigger |
"hover" | "click" |
Desktop only; mobile is always tap |
dropdownWidth |
sm | md | lg | xl |
Single-section panel width |
dropdownIconSize |
number |
Default icon px size (20) |
dropdownColumns |
1–4 |
Legacy / per-parent columns fallback |
borderBottom |
boolean |
Bottom stroke (01 / 03 / 04) |
borderThickness |
sm | md | lg |
Stroke weight |
borderColor |
soft | medium | hard |
Stroke contrast |
Panel width resolution
Works on all Navbar versions (01–04):
links[].widthif set on that parent- Else if more than one section (mega) →
xl - Else →
dropdownWidthprop /navigation.dropdownWidth - Else → version default (
smon 01 / 02,lgon 03 / 04)
| Preset | Approx. width |
|---|---|
sm |
20rem |
md |
28rem |
lg |
40rem |
xl |
56rem |
All clamp to 100vw - 2rem on small screens.
// Per-parent override (any version)
{ label: "Docs", href: "/docs/", width: "md", children: [/* … */] }
<!-- Navbar-level default -->
<Navbar01 dropdownWidth="md" />
<Navbar02 dropdownWidth="sm" />
<Navbar03 dropdownWidth="lg" />
<Navbar04 dropdownWidth="xl" />
Outer columns
Desktop mega panels use one outer grid column per section (up to 4). Inner columns on links / icon-links only grid that section’s items.
Shared components
| Component | Role |
|---|---|
NavSectionTitle.astro |
Grouping label (+ optional stroke) |
NavFeatured.astro |
Featured image column |
NavLinkList.astro |
Plain link list |
NavIconList.astro |
Icon + description list |
NavMegaPanel.astro |
Desktop dropdown panel (width, grid, chrome) |
NavMobileSections.astro |
Full-width stacked sections in the mobile accordion |
NavOverlayLinks.astro |
Accordion link tree for drawer / fullscreen overlays |
Navbar versions import NavMegaPanel / NavMobileSections / NavOverlayLinks after resolveNavSections(link). You can import the leaf components in a custom header if you fork chrome — keep data-nav-* attributes so initNavbars() still works.
Navbar versions (chrome)
| Version | Chrome | Typical use |
|---|---|---|
| 01 | Full-bleed sticky | Single plain link list from children |
| 02 | Floating rounded bar | Single-column title + description from children |
| 03 | Full-bleed | Two-column icon + title + description from children |
| 04 | Full-bleed mega | sections (featured + mixed columns) — site default |
| 05 | Minimal + drawer | Slide-in panel; side left/right, panelWidth |
| 06 | Minimal + fullscreen | Full-viewport takeover with large link type |
Resolve modes: plain · described · icons · mega via resolveNavSections(link, { mode }). Overlay navs (05 / 06) resolve with mega so site sections work unchanged.
---
import Navbar05 from "@/blocks/navbar/Navbar05.astro";
import Navbar06 from "@/blocks/navbar/Navbar06.astro";
---
<Navbar05 side="right" panelWidth="md" />
<!-- or -->
<Navbar06 />
Mobile behavior
- Hamburger opens the full panel.
- Dropdown parents expand as accordions (chevron).
- With parent
href, the label stays a link; the chevron expands children. - Submenu content is indented with a left rule and spans the remaining width of the panel.
- Featured cards use a compact thumb + text layout.
Recipes
Linked parent + simple children
{
label: "Company",
href: "/about/",
children: [
{ label: "About", href: "/about/" },
{ label: "Careers", href: "/careers/" },
{ label: "Contact", href: "/contact/" },
],
}
Two-column icon grid inside one section
{
label: "Product",
width: "lg",
sections: [
{
type: "icon-links",
title: "Platform",
titleStroke: true,
columns: 2,
items: [
{ label: "Analytics", href: "/analytics/", description: "Dashboards.", icon: "chart-line" },
{ label: "Automations", href: "/automations/", description: "Workflows.", icon: "zap" },
{ label: "Integrations", href: "/integrations/", description: "Connect tools.", icon: "blocks" },
{ label: "Security", href: "/security/", description: "Controls.", icon: "shield-check" },
],
},
],
}
Featured + resources only
{
label: "Learn",
width: "lg",
sections: [
{
type: "featured",
title: "Guide",
titleStroke: true,
image: "/images/nav/featured.webp",
imageAspect: "16/10",
label: "Get started",
href: "/docs/get-started/",
description: "Install and ship your first page.",
},
{
type: "links",
title: "Resources",
titleStroke: true,
items: [
{ label: "Blocks", href: "/docs/blocks/" },
{ label: "Components", href: "/docs/components/" },
{ label: "Deploy", href: "/docs/deploy/" },
],
},
],
}
TypeScript reference
Primary exports from src/lib/nav.ts:
NavLink,NavChildLink,NavSimpleLinkNavMegaSection,NavFeaturedSection,NavLinksSection,NavIconLinksSectionresolveNavSections(link)navLinkHasDropdown(link)isNavLinkActive(path, link)/isNavHrefActive(path, href)resolveNavDropdownWidth(...),navDropdownWidthClass(...)resolveNavChildIconSize(...)
Related
- Site config — where
navigationlives - Navbar blocks — version chrome + live demos
- Elements → Icon — Lucide icon names
