block

Topbar

A responsive navigation bar block that sticks to the top of the page. Renders a full-width container with support for a logo, desktop navigation links, and a theme mode toggle. On smaller screens, the menu collapses into a slide-up drawer triggered by a menu button.

Default

Provide menuItems for the navigation links and place your logo in the logo slot.

Pindoba

Navigation

---
import Topbar from "../Topbar.astro";
import type { MenuItem } from "@pindoba/astro-navigation";
import { css } from "@pindoba/styled-system/css";

const menuItems: MenuItem[] = [
  { label: "Home", href: "#" },
  { label: "About", href: "#" },
  { label: "Blog", href: "#" },
  { label: "Contact", href: "#" },
];
---

<Topbar menuItems={menuItems}>
  <div
    slot="logo"
    class={css({
      display: "flex",
      alignItems: "center",
      gap: "sm",
      fontSize: "lg",
      fontWeight: "bold",
    })}
  >
    Pindoba
  </div>
</Topbar>

Custom

Use showThemeModeSelect to hide the built-in theme toggle, menuActiveItem to highlight the current page, and passThrough to override styles on individual slots such as container for layout adjustments.

Without Theme Mode Select

MyApp

With Active Menu Item

Pindoba

Navigation

Custom Bottom Border

Pindoba

Navigation

---
import Topbar from "../Topbar.astro";
import type { MenuItem } from "@pindoba/astro-navigation";
import { css } from "@pindoba/styled-system/css";
import { stack } from "@pindoba/styled-system/patterns";

const menuItems: MenuItem[] = [
  { label: "Home", href: "#" },
  { label: "Docs", href: "#" },
  { label: "Examples", href: "#" },
];
---

<div
  class={stack({
    gap: "xl",
    direction: "column",
    width: "100%",
  })}
>
  <!-- Without theme mode select -->
  <div>
    <h3>Without Theme Mode Select</h3>
    <Topbar menuItems={menuItems} showThemeModeSelect={false}>
      <div
        slot="logo"
        class={css({
          fontSize: "lg",
          fontWeight: "bold",
          color: "primary.text",
        })}
      >
        MyApp
      </div>
    </Topbar>
  </div>

  <!-- Active menu item -->
  <div>
    <h3>With Active Menu Item</h3>
    <Topbar menuItems={menuItems} menuActiveItem="Docs">
      <div
        slot="logo"
        class={css({
          fontSize: "lg",
          fontWeight: "bold",
        })}
      >
        Pindoba
      </div>
    </Topbar>
  </div>

  <!-- Custom bottom border via passThrough -->
  <div>
    <h3>Custom Bottom Border</h3>
    <Topbar
      menuItems={menuItems}
      passThrough={{
        root: css.raw({
          backgroundColor: "primary.surface.ground",
        }),
      }}
    >
      <div
        slot="logo"
        class={css({
          fontSize: "lg",
          fontWeight: "bold",
          color: "primary.text.contrast.bold",
        })}
      >
        Pindoba
      </div>
    </Topbar>
  </div>
</div>
props · 33 shown · 33 total
active
boolean"current""checked""current-within"
default false

Mark this as the chosen one in a set (a current nav item, a checked option, a selected card). Where `interactive` says it *can* be clicked, `active` says it *is* the current choice. Use `activeEmphasis` to control how loud the state is. Combined with `interactive`, hover and press restart their stepping from the active baseline rather than falling back to the unchosen ramp. The three values differ only in what drives the state: `true` by the prop (via `data-panel-active`), `"checked"` by a wrapped native input (`:has(input:checked)` — zero JS, nothing to re-render), and `"current"` by an existing `aria-current`.

activeEmphasis
"primary""secondary""tertiary"
default the panel's `emphasis`

How loud the `active` state is. Defaults to the panel's own `emphasis`, so the chosen state lands on the same ramp as the resting look — this prop is the override for when the active item should be louder (or quieter) than the panel itself. `"primary"` fills with the feedback accent ramp and flips text to the contrast scale (~150 RGB units of separation — the option that reads at a glance in a dense list). `"secondary"` tints the feedback surface ramp and `"tertiary"` the neutral ramp; both promote text to `bold` and lift the border to the default line, but move the surface only ~7–18 units.

as
"div""section""article""aside""main""header""footer""nav""dialog""form""fieldset""ul""ol""li""a""button""label""span""kbd"
default "div"

HTML element to render. Curated to container-like tags so semantic intent stays clear (no html/script/style/etc).

background
string
default "surface.ground"

Surface background forwarded to the **Navigation** inside the bar — not the Topbar's own Panel surface, which is fixed at `surface.peak`.

border
"none""bold""default""muted""accent"

Border style: `none`, `default`, `bold`, or `muted`.

borderActive
"none""bold""inherit""default""muted""accent"

Border color while the surface is `active` — the explicit form of the ring `activeEmphasis` would otherwise pick. It holds through hover, so a `borderInteract` color can't steal it. `inherit` keeps whatever `activeEmphasis` chose; `none` clears it.

borderInteract
"none""bold""default""muted""accent"

Border style applied on hover / focus interaction.

desktopThemeModeSelectProps
ThemeModeSelectBaseProps

Props forwarded only to the desktop ThemeModeSelect. Takes precedence over `themeModeSelectProps` for the desktop placement.

emphasis
"primary""secondary""tertiary"

Visual emphasis / prominence level.

extras slot svelte
Snippet

Extra content placed beside the ThemeModeSelect.

feedback
"primary""neutral""success""warning""danger""inherit"

Semantic color tone: `neutral`, `primary`, `success`, `warning`, `danger`, or `inherit`.

id
string

Root element id. Seeds the desktop/mobile ThemeModeSelect ids.

interactive
boolean

Enable interactive (hover / focus / press) affordances and states.

logo slot svelte
Snippet

Brand / logo content.

menu slot svelte
Snippet

Replaces the default Navigation with custom menu content.

menuActiveItem
string

Label of the currently active navigation item — applies the active style.

menuItems
TopbarMenuItem[]

Navigation items rendered by the internal Navigation on both desktop and mobile.

mobileDialogProps
Record<string, unknown>

Props forwarded to the Dialog used as the mobile navigation drawer.

mobileThemeModeSelectProps
ThemeModeSelectBaseProps

Props forwarded only to the mobile ThemeModeSelect (inside the drawer). Takes precedence over `themeModeSelectProps` for the mobile placement.

navigationProps
Record<string, unknown>

Props forwarded to both the desktop and mobile Navigation components.

padding
"sm""md""lg""xl""2xl""none""xs""3xl""4xl""5xl""6xl""7xl""8xl""4xs""3xs""2xs""9xl""10xl""11xl"

Inner padding from the spacing scale.

passThrough
{ [K in TopbarSlots]?: SystemStyleObject }

Per-slot Panda CSS style overrides applied to individual topbar slots.

radius
"sm""md""lg""xl""2xl""none""xs""3xl""4xl""5xl""6xl""full""2xs""inner""inherit"

Corner radius override from the spacing scale (or `full` for fully rounded).

radiusBottom
"sm""md""lg""xl""2xl""none""xs""3xl""4xl""5xl""6xl""full""2xs""inner""inherit"

Corner radius for the bottom-left and bottom-right corners.

radiusLeft
"sm""md""lg""xl""2xl""none""xs""3xl""4xl""5xl""6xl""full""2xs""inner""inherit"

Corner radius for the top-left and bottom-left corners.

radiusRight
"sm""md""lg""xl""2xl""none""xs""3xl""4xl""5xl""6xl""full""2xs""inner""inherit"

Corner radius for the top-right and bottom-right corners.

radiusTop
"sm""md""lg""xl""2xl""none""xs""3xl""4xl""5xl""6xl""full""2xs""inner""inherit"

Corner radius for the top-left and top-right corners.

reactive
boolean
default false

Serialize the panel's resolved surface inputs into a `data-panel-config` attribute on the root, enabling runtime surface changes via `updatePanelElement()` (and, for inheritors like Card, `updateCard()`) without a framework runtime — the primary consumer is Astro / vanilla JS, where props don't re-render. Reactive frameworks (Svelte/React/Vue) don't need this: their prop changes re-run the connect already.

reserveBorderSpace
boolean

Keep (or drop) the always-1px transparent border the panel reserves so a border appearing or changing never shifts layout. Computed automatically — it's reserved when a resting `border` is visible, or when `interactive` / `borderInteract` / `active` can change the border at runtime. Set `false` only on a panel that must not occupy that 1px (e.g. a borderless housing frame that would otherwise add 2px around a set).

shadow
"sm""md""lg""xl""none""xs"

Elevation shadow applied to the surface.

showThemeModeSelect
boolean
default true

Render the built-in ThemeModeSelect toggle in the desktop and mobile extras area.

themeModeSelectProps
ThemeModeSelectBaseProps

Props forwarded to both ThemeModeSelect instances.

translucent
boolean

Apply a frosted-glass effect with backdrop blur over a surface background.

Plus all standard <div> HTML attributes.

Type

  • Components
  • Blocks