Page Title

The page header with a heading, optional subtitle, description and back link, plus room for actions.

Preview

Usage

import { PageTitle } from '@vitnode/core/components/ui/page-title'
<PageTitle desc="Group users and decide what each group can do." h1="Roles">
  <Button>
    <PlusIcon />
    Create role
  </Button>
</PageTitle>

children become actions on the right. On phones everything stacks and the actions go full width. From sm up, heading left, actions right.

h1 or h2

Pass exactly one of h1 or h2. TypeScript complains about both or neither.

  • h1 is the page heading (text-2xl sm:text-3xl). One per page.
  • h2 is a section inside a page that already has an h1, like a settings panel (text-xl sm:text-2xl).
<PageTitle h2="Danger zone" />

The previews use h2, since this page already has an h1.

Subtitle

A small muted line above the heading. Use it for where the page lives.

<PageTitle
  desc="Sign in faster with accounts you already have."
  h1="Connected accounts"
  subtitle="Settings"
/>

back adds an arrow link above the heading (and above subtitle). Good for edit and detail pages under a list. It's a TanStack Router Link, so it navigates client-side and preloads. The actions side stays free.

<PageTitle
  back={{ href: '/admin/core/users', label: 'Back to users' }}
  desc="Edit the details shown on the public profile."
  h1="Edit user"
>
  <Button>Save changes</Button>
</PageTitle>

Multiple actions

Pass as many children as you need; they wrap on small screens. Keep one primary button and make the rest outline or ghost.

<PageTitle
  desc="Everything published on the site, newest first."
  h1="Blog posts"
>
  <Button variant="outline">
    <DownloadIcon />
    Export
  </Button>
  <Button>
    <PlusIcon />
    New post
  </Button>
</PageTitle>

Spacing

PageTitle has a built-in mb-6. Drop it when the parent already uses gap-*:

<div className="flex flex-col gap-4">
  <PageTitle className="mb-0" h1="Devices" />
  <DevicesList />
</div>

Accessibility

  • The heading is a real h1 or h2, so it appears in heading navigation.
  • subtitle is a p, not a heading, so it stays out of the outline.
  • Give icon-only actions an aria-label or sr-only text.

Props

Prop

Type