Vize

App Bar

Top application bar: a header landmark that reports scroll elevation and can hide while scrolling down.

Package @vizejs/ui/app-bar
Maturity stable
Own the source vize lib pull app-bar
Requires —
Aliases top app bar, app header, navigation bar, header bar
Covers HTML header landmark, Material top app bar, Vuetify v-app-bar

Minimal setup

Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).

vp install @vizejs/ui

Add the public import below to <script setup lang="ts">. Components provide behavior without styles; the preview uses optional Paper styles.

import { AppBar } from "@vizejs/ui/app-bar";

Or copy the source into your project with vize lib pull app-bar (see Source Distribution).

Try it

This is the basic example maintained with the component source, using the public package imports. The preview adds the optional Paper styles.

Open the interactive example · Styling these components

Copy the example

<!-- Top app bar with a menu button, a title, and a search action that hides while scrolling down. -->
<script setup lang="ts">
import { useId } from "vue";
import { AppBar } from "@vizejs/ui/app-bar";

const titleId = useId();
</script>

<template>
  <AppBar hide-on-scroll :aria-labelledby="titleId">
    <template #start>
      <button type="button" aria-label="Open navigation">≡</button>
    </template>
    <template #default="{ elevated }">
      <span :id="titleId" :data-elevated="elevated ? 'true' : undefined">Inbox</span>
    </template>
    <template #end>
      <button type="button">Search</button>
    </template>
  </AppBar>
</template>

API

AppBar

Source: src/families/navigation/app-bar/app-bar.vue

Props

Prop Type Default Description
as "header" | "div" "header" Host element. A top-level header is the page's banner landmark; use div when the bar sits inside another landmark that already has a header.
target AppBarTarget null Scroll container to follow: an element, a selector, or null for the window.
elevateThreshold number 0 Scroll offset in CSS pixels past which the bar reports elevated.
hideOnScroll boolean false Report hidden while the container scrolls down, and visible again as soon as it scrolls up.
hideThreshold number 64 Scroll offset in CSS pixels before hideOnScroll may hide the bar.
ariaLabel string undefined Accessible name of the landmark when no visible title labels it.
ariaLabelledby string undefined Ids that label the landmark (overrides ariaLabel).

Events

Event Payload Description
visibilityChange [hidden: boolean] Fired when hideOnScroll hides or reveals the bar.

Slots

Slot Slot props Description
start AppBarSlotState Leading content such as a navigation or back button.
default AppBarSlotState Title and main content.
end AppBarSlotState Trailing actions.

Exposed

Member Type Description
elevated boolean Whether the followed container has scrolled past elevateThreshold.
hidden boolean Whether hideOnScroll currently asks the consumer to move the bar out of view.
state AppBarState Stable visibility token for styling and tests.
scrollTop number Current scroll offset of the followed container in CSS pixels.
element HTMLElement | null Rendered root element.
show () => void Bring a hidden bar back into view.
refresh () => number Re-read the scroll offset, for containers that scroll without a scroll event.

Behavior

Normative state x input -> outcome table for app-bar.vue (@vizejs/ui/app-bar). An app bar is the page's top bar: a header landmark with leading, main, and trailing content. It only reports scroll state (data-elevated, data-hidden, data-state); positioning, elevation, and the hide transition stay consumer-owned CSS. Every row is proven by the named test in app-bar.test.ts or app-bar-ssr.test.ts.

# State Input Outcome Proven by
AB1 render slots / as / labels <header> (or <div>) with start, content, end parts; empty start/end render nothing; ARIA labels apply renders a header landmark with start, content, and end parts
AB2 window scroll offset past elevateThreshold data-elevated="true" strictly past the threshold, removed at or below it; never hides without hideOnScroll reports elevation once the window scrolls past the threshold
AB3 hideOnScroll scroll down / up hides after hideThreshold while scrolling down, reveals on any upward scroll, emits visibilityChange each time hideOnScroll hides while scrolling down past the threshold and reveals on scroll up
AB4 hidden focus inside / show() focus reveals the bar and keeps it visible until focus leaves; show() reveals it focus inside a hidden bar reveals it and keeps it visible
AB5 element target selector container scroll follows the selected container and ignores window scrolling; refresh() re-reads the offset follows an element scroll container given as a selector
AB6 option changes hideOnScroll off / NaN turning hideOnScroll off reveals the bar; non-finite thresholds fall back to their defaults turning hideOnScroll off reveals a hidden bar, and invalid thresholds fall back
AB7 SSR / hydration isolated requests byte-identical visible markup without scroll state, hydrating without diagnostics renders byte-identical app bar markup and hydrates without mismatches

Hiding only publishes state: the bar keeps its content in the DOM and in the tab order, and keyboard focus brings it back, so a consumer's off-screen transform never traps focus out of view. Use as="div" when the bar sits inside a landmark that already has a header.