Skip to content
BaseLayer Themes

Navigation

Config-driven nav panels — sections, children, featured columns, and shared components

Folder: src/components/nav/ · Types: src/lib/nav.ts · Client: src/scripts/navbar.ts

Navbar blocks (Navbar01Navbar06) 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.tsnavigation.

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.tsnavigation 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

{ 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 icon or descriptionicon-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.

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

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

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 14 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.

Plain label-only list (same visual weight as icon-link titles).

Field Required Notes
type yes "links"
items yes { label, href }[]
columns no 14
title no Column grouping label
titleStroke no Soft underline under title

Section titles

Optional title on any section. Renders via NavSectionTitle10px, uppercase, muted.

{ type: "links", title: "Resources", titleStroke: true, items: [/* … */] }

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 14 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):

  1. links[].width if set on that parent
  2. Else if more than one section (mega) → xl
  3. Else → dropdownWidth prop / navigation.dropdownWidth
  4. Else → version default (sm on 01 / 02, lg on 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.

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" },
      ],
    },
  ],
}
{
  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, NavSimpleLink
  • NavMegaSection, NavFeaturedSection, NavLinksSection, NavIconLinksSection
  • resolveNavSections(link)
  • navLinkHasDropdown(link)
  • isNavLinkActive(path, link) / isNavHrefActive(path, href)
  • resolveNavDropdownWidth(...), navDropdownWidthClass(...)
  • resolveNavChildIconSize(...)

← Components overview