Skip to content
Component installs need the registry setup
VegaStack Design

Record Header

One head for every record, on its page and in a peek — key, title renamed in place, status, meta, chips and actions.

Status
preview
Since
0.25.88
Accessibility pattern
one heading, an editable title with its label

Last updated

Sales · Pricing
DOC-31

Pricing note for the Q4 range

In review
Created 12 OctUpdated 2h ago

Install

Configure registry credentials first using the Quickstart. Before copying this item or any transitive registry dependency, verify the signed manifest and save the exact bytes for Record Header before installation. Retain the digest printed by this command.

pnpm exec vegastack-design verify record-header

Install with the pinned shadcn CLI. Bare shadcn does not verify VegaStack signature or integrity.

pnpm dlx shadcn@4.21.0 add @vegastack/record-header

Run the exact offline --post-write command printed by the preflight, using its saved item path and independently retained --expected-integrity digest. Use the saved preflight for every transitive registry dependency too; stop on any mismatch before using the components.

The same command installs the registry items it composes: @vegastack/badge, @vegastack/editable-cell, @vegastack/skeleton, @vegastack/truncated-text.

Usage

import { RecordHeader } from "@/components/ui/record-header";

<RecordHeader
  eyebrow={<SpaceChip space={space} />}
  keyBadge={task.ref}
  title={task.title}
  onRename={(title) => updateTask({ title })}
  status={<StatusBadge status={task.status} />}
  presence={<AvatarStack people={here} max={3} />}
  actions={<TaskActionsMenu task={task} />}
  meta={<MetaLine>…</MetaLine>}
  chips={<TaskChips task={task} />}
/>;

Scope

One anatomy for every record kind and both places a record opens. An eyebrow line holds where the record lives and its key, with presence and the actions at its end; then the icon and the title — renamed in place with onRename — with the status beside it; then the meta line and the chip row. Every slot but the title is optional and leaves no gap when empty. On a full page the breadcrumb and the actions usually live in the top bar (AppShellHeaderActions); inside a RecordPeek they belong here, with level={2}.

Anatomy

RecordHeader — data-slot="record-header" | "record-header-actions" | "record-header-chips" | "record-header-eyebrow" | "record-header-icon" | "record-header-key" | "record-header-location" | "record-header-meta" | "record-header-status" | "record-header-title" | "record-header-title-row"
RecordHeaderSkeleton — data-slot="record-header-skeleton"

Examples

A record page

Sales · Pricing
DOC-31

Pricing note for the Q4 range

In review
Created 12 OctUpdated 2h ago

In a peek

level={2} makes the title an h2 at the peek's size, under the peek's own name.

TASK-12

Draft the Q4 pricing note

Loading

RecordHeaderSkeleton draws the same heights, so nothing moves when the record arrives.

API Reference

PropTypeDefaultDescription
title*string—The record's title.
actionsReact.ReactNode—The record's actions at the end of the eyebrow line, in the contract's order: Share, Watch, the ⋮ menu. On a full page they usually live in the top bar instead.
chipsReact.ReactNode—The chip row under the meta line: the record's key properties as RecordChips (assignee, due, priority).
eyebrowReact.ReactNode—Where the record lives, before the key: a breadcrumb, a space chip. On a full page this is usually the top bar's job; inside a peek it belongs here.
iconReact.ReactNode—The record's icon or emoji before the title (an IconGlyph, a file-kind icon).
keyBadgeReact.ReactNode—The record's key or reference ("TASK-42", "SR-12") — a string is a small outline chip; pass a node for a copy-on-click chip.
level1 | 21The heading level: 1 on the record's own page, 2 inside a peek or a dialog.
metaReact.ReactNode—The meta line under the title: a MetaLine of facts (created, updated, owner).
onRename((next: string) => void | Promise<void>)—Rename in place: the title becomes an EditableCell heading that saves on Enter or blur and rolls back on a failed save. Omit for a read-only title.
placeholderstring"Untitled"What an empty title reads as ("Untitled").
presenceReact.ReactNode—Who else is here (an AvatarStack), at the end of the eyebrow line.
statusReact.ReactNode—The record's status beside the title (a StatusBadge, a StatusLine).
titleLabelstring"Title"The title's accessible label while it is editable.

Data attributes and CSS variables on RecordHeader

AttributeValues
data-levelmirrors a prop or state value
data-slot"record-header" | "record-header-actions" | "record-header-chips" | "record-header-eyebrow" | "record-header-icon" | "record-header-key" | "record-header-location" | "record-header-meta" | "record-header-status" | "record-header-title" | "record-header-title-row"

RecordHeaderSkeleton

PropTypeDefaultDescription
chipsbooleantrueReserve the chip row.
eyebrowbooleantrueReserve the eyebrow line.
level1 | 21The heading level it stands in for, so the title bar is the right height.

Data attributes and CSS variables on RecordHeaderSkeleton

AttributeValues
data-slot"record-header-skeleton"

Accessibility

  • The title is the record's one heading (h1 on its page, h2 in a peek). Renamed in place it is an EditableCell labelled by titleLabel: Enter or blur saves, Esc reverts, a failed save rolls back and is announced.
  • The key chip, status and meta are text; icons beside them are decorative.
ContractStates tested
Behaviourdefault, renamable, loading
Accessibilitylabeled
Visualdefault, with-icon

Do / Don't

Do
Head every record — task, meeting, row, page, customer — with RecordHeader, on its page and in its peek.
Don't
Compose a record title, key and status by hand per module, or put a second heading above the title.

On this page