Navigation

AppBar

Sticky translucent top bar for a page: Back and leading content, the page's title, and trailing icon actions that each carry a name and a tooltip.

import { AppBar } from '@lostgradient/cinder';
app-barheaderchrome
01

Overview

Reference usage

AppBar is a sticky top bar of translucent material for a page: Back and any leading content, the page's title, and trailing icon actions. It is 56px tall and draws no rule. Its surface is the canvas mixed at 82% with a 16px backdrop blur, so what scrolls under it shows through softly, and it is opaque where the platform cannot blur or when the person asks for less transparency. It is not a Toolbar, which is the WAI-ARIA control group with arrow-key navigation, and not a NavigationBar, which is a bar of navigation items.

Usage

svelte
<script lang="ts">
  import { AppBar } from '@lostgradient/cinder';
  import Share from '@lucide/svelte/icons/share';
  import Star from '@lucide/svelte/icons/star';
</script>

{#snippet shareIcon()}<Share class="cinder-icon-md" aria-hidden="true" />{/snippet}
{#snippet saveIcon()}<Star class="cinder-icon-md" aria-hidden="true" />{/snippet}

<AppBar
  title="Death & Co"
  headingLevel={1}
  back={{ href: '/places' }}
  actions={[
    { label: 'Share', icon: shareIcon, onclick: () => {} },
    { label: 'Save', icon: saveIcon, onclick: () => {} },
  ]}
/>

A phone detail page

On a phone detail page the page's identity lives in the bar: Back, the title at 20px bold, then the icon actions, pinned while the page scrolls. Give the title a headingLevel so it is the page's heading, and draw no separate title under the bar, so there is never an empty bar above a title of its own.

Each action in actions is icon-only, so its label is required: it is the action's accessible name and its tooltip. Under a coarse pointer every icon action, Back included, has a 44px target. leading and trailing hold anything else, such as a SegmentedControl; trailing content sits before the icon actions.

With a large page title

Paired with a PageHeader in its large variant, the bar shows the title only once the large title has scrolled away. Bind the header's collapsed to the bar's titleVisible, and turn off the header's own sticky bar with collapsedBar={false}. The PageHeader keeps the page's heading, so leave headingLevel unset; while the title is hidden it is also hidden from assistive technology.

svelte
<script lang="ts">
  import { AppBar, PageHeader } from '@lostgradient/cinder';

  let collapsed = $state(false);
</script>

<AppBar title="Runs" titleVisible={collapsed} back={{ href: '/' }} />
<PageHeader variant="large" title="Runs" bind:collapsed collapsedBar={false} />
Live preview

A phone detail page

Death & Co

Cocktail bar in LoDo. Happy hour runs from four to six on weekdays, with half-price classics and a short bar menu. Scroll to see the content pass under the bar.

The bar stays pinned at the top of the scrolling area while the page moves under it.

It is opaque when the person asks for less transparency.

02

When to use

Use when
  • Pinning a page's identity while it scrolls: Back, the title, then icon actions, as a phone detail page does.
  • Showing a large page title in the bar once it scrolls away, paired with the large variant of page-header.
Avoid when
  • Grouping controls with arrow-key navigation between them — use toolbar.
  • Switching between an app's top-level sections — use navigation-bar.
03

Examples

A phone detail page

Back, the page title at 20px bold, then icon actions with tooltips, pinned over the content as it scrolls. The bar is translucent and draws no rule.

04

Props

Props for app-bar
Name
Type
Default
Description
title text The page's title, 20px bold on one line that ends in an ellipsis. Snippets must emit phrasing content.
titleVisible boolean true Draws the title. Bind a large PageHeader's collapsed here so the title appears once the large title scrolls away; while it is hidden the title is also hidden from assistive technology.
headingLevel 123456 Makes the title the page's heading at this level, for a page whose identity lives in the bar. Leave it unset when a PageHeader carries the page's heading.
back { /** * The accessible name and the tooltip. * @default "Back" */ label?: string; /** Render Back as a link to this address instead of a button. …
Show full type { /** * The accessible name and the tooltip. * @default "Back" */ label?: string; /** Render Back as a link to this address instead of a button. */ href?: string; /** Called when Back is pressed. */ onclick?: (event: MouseEvent) => void; }
A Back action at the start of the bar.
leading snippet Content at the start of the bar, after Back.
trailing snippet Content at the end of the bar, before the icon actions.
actions AppBarAction[] Icon-only actions at the end of the bar, each with a required name and a tooltip.