# App bar

> The bar across the top of a site: brand on one side, navigation and actions on the other.

An app bar is a `<header>` with a row inside it. The pieces are separate so you can arrange them: `appBarNav()` for links, `appBarSpacer()` to push what follows to the far end, and `appBarActions()` for the buttons at the end.

## Basic app bar

```javascript
appBar({ brand: 'sitelo' },
  appBarSpacer(),
  appBarActions(
    button({ size: 'sm', variant: 'soft' }, 'Sign in'),
  ),
)
```

## With navigation

`navLink()` is the link style for a bar; `current` marks the active page with `aria-current` as well as colour.

```javascript
appBar({ brand: 'sitelo' },
  appBarNav(
    navLink({ href: '#docs', current: true }, 'Docs'),
    navLink({ href: '#ui' }, 'UI'),
    navLink({ href: '#examples' }, 'Examples'),
  ),
  appBarSpacer(),
  appBarActions(
    button({ size: 'sm', variant: 'outline', color: 'neutral' }, 'GitHub'),
    button({ size: 'sm' }, 'Get started'),
  ),
)
```

## A brand with a mark

The brand takes any markup, and links to `/` unless `href` says otherwise.

```javascript
appBar({
  href: '#home',
  brand: stack({ direction: 'row', gap: 'sm', inline: true, align: 'center' },
    avatar({ name: 'S', size: 'sm', square: true, color: 'primary' }),
    'sitelo',
  ),
},
  appBarSpacer(),
  appBarActions(chip({ size: 'sm', color: 'neutral' }, 'v2.6.3')),
)
```

## Sticky and blurred

`sticky` pins the bar to the top of the scroll container; `blur` makes it translucent so content passes under it. Both are shown here inside a scrolling box rather than on the page itself.

```javascript
div({ style: 'height: 12rem; overflow: auto; border: 1px solid var(--su-border); border-radius: 0.6rem' },
  appBar({ brand: 'sitelo', sticky: true, blur: true },
    appBarSpacer(),
    appBarActions(chip({ size: 'sm', color: 'primary' }, 'sticky')),
  ),
  container({ size: 'sm', style: 'padding-block: 1rem' },
    stack({ gap: 'md' },
      ...Array.from({ length: 6 }, (unused, index) =>
        text({ variant: 'small', tone: 'muted' }, 'Scroll me — paragraph ' + (index + 1) + '.'),
      ),
    ),
  ),
)
```

## Out of the way while scrolling

`sticky: 'auto'` keeps the bar pinned, but slides it away while the page scrolls down and brings it back as soon as it scrolls up, or reaches the top. It stays in view while keyboard focus is inside it, or a menu in it is open.

In Chromium this is all CSS, `@container scroll-state(scrolled)`, and nothing is fetched. Other browsers fetch a small module when the page loads, which watches the scroll instead. The bar follows the page; inside a scrolling box of your own, like the one here, give the box `container-type: scroll-state` as well.

```javascript
div({ style: 'height: 12rem; overflow: auto; container-type: scroll-state; border: 1px solid var(--su-border); border-radius: 0.6rem' },
  appBar({ brand: 'sitelo', sticky: 'auto', blur: true },
    appBarSpacer(),
    appBarActions(chip({ size: 'sm', color: 'primary' }, 'auto')),
  ),
  container({ size: 'sm', style: 'padding-block: 1rem' },
    stack({ gap: 'md' },
      ...Array.from({ length: 12 }, (unused, index) =>
        text({ variant: 'small', tone: 'muted' }, 'Scroll down, then back up — paragraph ' + (index + 1) + '.'),
      ),
    ),
  ),
)
```

## With a drawer on small screens

The usual pattern: links in the bar on desktop, a button that opens a `drawer()` on a phone. The drawer is a `<dialog>` the button opens with a command, so it needs no script.

```javascript
fragment(
  appBar({ brand: 'sitelo' },
    appBarSpacer(),
    appBarActions(
      themeToggle(),
      iconButton({
        label: 'Open navigation',
        variant: 'ghost',
        color: 'neutral',
        commandfor: 'app-bar-drawer', command: 'show-modal',
        icon: icon('menu'),
      }),
    ),
  ),
  drawer({ id: 'app-bar-drawer', title: 'Navigation' },
    navLink({ href: '#docs' }, 'Docs'),
    navLink({ href: '#ui' }, 'UI'),
    navLink({ href: '#examples' }, 'Examples'),
  ),
)
```

## Props

`appBar()`:

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `brand` | `Child` | — | Content of the brand link at the start. |
| `href` | `string` | `'/'` | Where the brand links to. |
| `sticky` | `boolean \| 'auto'` | `false` | Pins the bar to the top on scroll. 'auto' also hides it while scrolling down. |
| `blur` | `boolean` | `false` | Translucent background with a backdrop blur. |
| `as` | `string` | `'header'` | Element to render. |

The pieces:

| Piece | Props | Default | Description |
| --- | --- | --- | --- |
| `appBarNav` |  | — | A nav element holding the links. |
| `appBarSpacer` |  | — | Flexible gap; everything after it goes to the far end. |
| `appBarActions` |  | — | Trailing cluster of buttons. |
| `navLink` | `href, current, color` | — | A link styled for the bar; current marks the active page. |
