Frappe UIFrappe UI

PageHeader

App-shell headers: a desktop PageHeader, a mobile PageHeaderMobile, and the PageHeaderBase primitive they share. A page declares its header; it renders into the layout's <PageHeaderTarget />.

vue
<script setup lang="ts">
import { Breadcrumbs, Button, PageHeader } from 'frappe-ui'
</script>

<template>
  <div
    class="w-full overflow-hidden border-t border-l border-r bg-surface-base"
  >
    <PageHeader>
      <Breadcrumbs
        :items="[
          { label: 'Spaces', route: '#' },
          { label: 'Engineering', route: '#' },
        ]"
      />
      <Button label="New discussion" variant="solid" />
    </PageHeader>
  </div>
</template>

Clicking the header's empty area scrolls the page to the top. Interactive elements are ignored; opt others out with data-no-scroll-top.

PageHeaderMobile

Keeps its title centered regardless of the #left / #right control widths, and clamps it to two lines. PageHeaderBackButton navigates to to, or falls back to browser history.

A discussion title that is long enough to need centering

vue
<script setup lang="ts">
import { Button, PageHeaderMobile, PageHeaderMobileTitle } from 'frappe-ui'
</script>

<template>
  <div class="w-80 overflow-hidden border border-b-0 bg-surface-base">
    <PageHeaderMobile>
      <template #left>
        <Button
          variant="ghost"
          size="md"
          icon="lucide-chevron-left"
          label="Back"
        />
      </template>
      <PageHeaderMobileTitle
        title="A discussion title that is long enough to need centering"
      />
      <template #right>
        <Button variant="ghost" icon="lucide-more-horizontal" label="Options" />
      </template>
    </PageHeaderMobile>
  </div>
</template>

PageHeaderBase

The unstyled <header> primitive behind both. Use it directly for a custom strip — a toolbar or a second row — that shares the same target.

API Reference

PageHeader

default
{}

PageHeaderBase

default
{}

PageHeaderMobile

Show types
typescript
import type { RouteLocationRaw } from 'vue-router'

export interface PageHeaderMobileProps {
  /** Title shown centered in the header. Overridden by the default slot. */
  title?: string
}

export interface PageHeaderMobileTitleProps {
  /** Title text. Overridden by the default slot. */
  title?: string
}

export interface PageHeaderBackButtonProps {
  /** Where to navigate on tap. Omit to fall back to browser history. */
  to?: RouteLocationRaw

  /** Accessible label for the button. */
  label?: string
}
title
string

Title shown centered in the header. Overridden by the default slot.

left
{}
default
{}
right
{}

PageHeaderMobileTitle

Show types
typescript
import type { RouteLocationRaw } from 'vue-router'

export interface PageHeaderMobileProps {
  /** Title shown centered in the header. Overridden by the default slot. */
  title?: string
}

export interface PageHeaderMobileTitleProps {
  /** Title text. Overridden by the default slot. */
  title?: string
}

export interface PageHeaderBackButtonProps {
  /** Where to navigate on tap. Omit to fall back to browser history. */
  to?: RouteLocationRaw

  /** Accessible label for the button. */
  label?: string
}
title
string

Title text. Overridden by the default slot.

icon
{}
default
{}

PageHeaderBackButton

Show types
typescript
import type { RouteLocationRaw } from 'vue-router'

export interface PageHeaderMobileProps {
  /** Title shown centered in the header. Overridden by the default slot. */
  title?: string
}

export interface PageHeaderMobileTitleProps {
  /** Title text. Overridden by the default slot. */
  title?: string
}

export interface PageHeaderBackButtonProps {
  /** Where to navigate on tap. Omit to fall back to browser history. */
  to?: RouteLocationRaw

  /** Accessible label for the button. */
  label?: string
}
to
string | kt | Tt

Where to navigate on tap. Omit to fall back to browser history.

label
= "Back"
string

Accessible label for the button.