Skip to main content

Toolbar

Info:Shell html svelte astro Success: coverage 23/23

The header bar: a title plus structured start, center, and end regions for actions and navigation.

Live demo

live · @xoji/astro

Toolbar

Full bar — start · center · end

xoji
Success:Live

Density — sm · md · lg

Compact
Default
Roomy

Bare — nested in a surface, no fill or divider

Inbox
Info:Unread3

A bare Toolbar reuses the region layout inside a Card or Panel header — no standalone chrome.

Toolbar is the chrome bar that runs across the top of an app, a page, or a panel. It carries an optional heading (a plain title, or a link when given an href) and three layout regions (start, center, and end) that flex apart so leading controls sit left, primary content centers, and trailing actions push right.

It adds layout, not semantics: by default it renders a neutral <div> with no landmark role, and opts into a page-banner <header> only when you ask for it with landmark, since whether a given bar is the page banner is the consumer's call. A bare mode drops the surface fill and divider for nesting inside another container, sticky pins it to the top of its scroll area, and the size scale tightens or loosens its padding.

When to use

How this component composes with the rest of the set.

Fill the regions with Button (ghost/link variants read best as bar actions) and Badge for status pips.
Pair a landmark Toolbar with the app's main content region so assistive tech gets a banner/main split.
Drop bare Toolbars inside a Panel or Card header to reuse the region layout without the standalone chrome.

Props

6 props, straight from the manifest.

PropTypeDefaultBindingsDescription
heading string
html svelte astro
The bar's title. Rendered as a link when `href` is also set.
href string
html svelte astro
When set alongside `heading`, the title renders as a focusable `<a>` (typically the home link).
size Size
sm md lg
md
html svelte astro
Bar density: tightens or loosens padding, gap, and minimum height.
landmark boolean false
html svelte astro
Renders the bar as a `<header>` banner landmark instead of a plain `<div>`. Opt in only when this is *the* page header.
sticky boolean false
html svelte astro
Pins the bar to the top of its scroll container.
bare boolean false
html svelte astro
Drops the surface fill and bottom divider, for nesting inside another surface.

Appearance

Variants

bare

.xoji-toolbar--bare

Transparent background with no divider. Chrome for nesting, not for standing alone.

sticky

.xoji-toolbar--sticky

Pinned to the top of its scroll area at an elevated stacking layer.

Sizes

sm

.xoji-toolbar--sm

Tight, compact density.

md

default
.xoji-toolbar

Default.

lg

.xoji-toolbar--lg

Roomy, generous padding.

States

title-hover

a.xoji-toolbar__title:hover

Pointer over a linked title. The title shifts to the link-hover ink.

title-focus-visible

a.xoji-toolbar__title:focus-visible

Keyboard focus on a linked title. A token ring plus a transparent outline that becomes real in forced-colors mode.

Anatomy

The named parts that make up the component, with their selectors.

toolbar

.xoji-toolbar

The bar element carrying the size, sticky, and bare classes; a <div> by default, a <header> landmark when opted in.

--font-sans --fg-1 --bg-1 --border-thin --line --space-2 --space-3 --space-4 --space-8

title

.xoji-toolbar__title

The heading text; a <span>, or a focusable <a> when an href is set.

--font-display --weight-bold --text-lg --leading-tight --fg-0 --link-hover

group

.xoji-toolbar__group

One of the three flex regions (start / center / end) that hold the bar's controls.

--space-2

spacer

.xoji-toolbar__spacer

A flexible gap that pushes the content on either side of it apart.

Tokens & coverage

What the component consumes, checked live against what the algorithm produces.

Success:fully covered 23/23 consumed tokens produced default register: 276 tokens

Live coverage check against the xoji-default register (derive(xojiDefault, { anchors })coverComponent(manifest, register)). Every token this component consumes must be a key the algorithm produces.

--bg-1 --border-normal --border-thick --border-thin --elevation-3 --fg-0 --fg-1 --font-display --font-sans --leading-tight --line --link-hover --radius-sm --ring --space-1 --space-2 --space-3 --space-4 --space-5 --space-7 --space-8 --text-lg --weight-bold

Slots

start
html svelte astro

Leading region: typically a menu trigger, logo, or back button.

center
html svelte astro

Centered region: typically navigation, search, or a breadcrumb.

end
html svelte astro

Trailing region: typically primary actions, pushed to the far edge.

default
html svelte astro

Unstructured content placed between the heading and the center region, for bars that don't need the three named regions.

Accessibility

Defaults to a plain <div> with no landmark role; opts into a <header> banner only via landmark, so the page never ends up with competing banners.
Avoids the ARIA toolbar role. That role implies roving-tabindex keyboard semantics this presentational bar does not manage; its controls keep their own native focus order.
A linked title is a real <a>, so it is keyboard-focusable and shows the token focus ring plus the forced-colors outline promotion.
Decorative leading graphics passed to the start region should be marked aria-hidden; the accessible name comes from the heading or the controls themselves.

Code

App banner and docs bar

A landmark app header with leading icon and trailing actions, and a bare linked-title docs bar with centered nav.

<xoji-toolbar heading="Project Atlas" landmark>
	<svg slot="start" viewBox="0 0 24 24" width="20" height="20" aria-hidden="true">
		<path fill="currentColor" d="M3 5h18v2H3V5Zm0 6h18v2H3v-2Zm0 6h18v2H3v-2Z" />
	</svg>
	<span slot="end">
		<xoji-button variant="ghost" tone="neutral">Settings</xoji-button>
		<xoji-button variant="solid" tone="accent">Publish</xoji-button>
	</span>
</xoji-toolbar>

<xoji-toolbar heading="Docs" href="/" size="sm" bare>
	<nav slot="center">
		<xoji-button variant="link" tone="neutral" href="/guide">Guide</xoji-button>
		<xoji-button variant="link" tone="neutral" href="/api">API</xoji-button>
	</nav>
</xoji-toolbar>
<script lang="ts">
	import { Toolbar, Button } from "@xoji/svelte";
</script>

<Toolbar heading="Project Atlas" landmark>
	{#snippet start()}
		<svg viewBox="0 0 24 24" width="20" height="20" aria-hidden="true">
			<path fill="currentColor" d="M3 5h18v2H3V5Zm0 6h18v2H3v-2Zm0 6h18v2H3v-2Z" />
		</svg>
	{/snippet}
	{#snippet end()}
		<Button variant="ghost" tone="neutral">Settings</Button>
		<Button variant="solid" tone="accent">Publish</Button>
	{/snippet}
</Toolbar>

<Toolbar heading="Docs" href="/" size="sm" bare>
	{#snippet center()}
		<Button variant="link" tone="neutral" href="/guide">Guide</Button>
		<Button variant="link" tone="neutral" href="/api">API</Button>
	{/snippet}
</Toolbar>
---
import { Toolbar, Button } from "@xoji/astro";
---

<Toolbar heading="Project Atlas" landmark>
	<svg slot="start" viewBox="0 0 24 24" width="20" height="20" aria-hidden="true">
		<path fill="currentColor" d="M3 5h18v2H3V5Zm0 6h18v2H3v-2Zm0 6h18v2H3v-2Z" />
	</svg>
	<Fragment slot="end">
		<Button variant="ghost" tone="neutral">Settings</Button>
		<Button variant="solid" tone="accent">Publish</Button>
	</Fragment>
</Toolbar>

<Toolbar heading="Docs" href="/" size="sm" bare>
	<nav slot="center">
		<Button variant="link" tone="neutral" href="/guide">Guide</Button>
		<Button variant="link" tone="neutral" href="/api">API</Button>
	</nav>
</Toolbar>