Skip to content

Record header

The top of a record page: its name, key fields and actions. Lightning's highlights panel, for a standard or custom object.

Opportunity

Edge Emergency Generator

Close Date
Jan 18, 2027
Amount
$75,000.00
Stage
Id. Decision Makers
Opportunity Owner
Ellen Hart

Installation

pnpm dlx shadcn@latest add @wisty/record-header

The CLI installs the Radix or Base UI file to match your project, with what it builds on: page-header, icon, output-field, button, button-group, dropdown-menu, skeleton.

If your project doesn't have Wisty UI's theme yet, add it once with npx shadcn@latest add @wisty/cosmos. Until then, components keep shadcn's default look. Installation has the details.

When to use

Use it

  • At the top of a record page: an opportunity, a case, an account or a custom object's record.
  • In place of Lightning's highlights panel: the record's name, Follow, its actions, and the compact layout's fields.
  • When the page starts from one record read and the object's compact layout, passed in as plain values.

Don't use it

  • For a list of records. Use List view header above a Data table.
  • For a page that isn't one record, like a report or a setup page. Use Page header.
  • For every field on the record. The header holds the few that identify it. The rest belong in the record's detail section.

Usage

import { RecordHeader } from "@/components/wisty/record-header"
<RecordHeader
  icon="standard:account"
  objectLabel="Account"
  name="GenePoint"
  fields={[
    { id: "Type", label: "Type", value: "Customer - Channel" },
    { id: "Phone", label: "Phone", value: "(650) 867-3450", type: "phone" },
    {
      id: "AnnualRevenue",
      label: "Annual Revenue",
      value: 30_000_000,
      type: "currency",
    },
  ]}
  actions={[
    { value: "edit", label: "Edit" },
    { value: "new-contact", label: "New Contact" },
  ]}
  onAction={runAction}
/>

A field's type uses Output field's value types, address, name, time and relative included, plus reference for a related record, linked through href. Values format and link with locale, currency and timeZone through Output field's formatOutputValue and outputValueHref, the same way the data table and Record detail write them: a URL with no scheme links with https://, one with another scheme than http, https, mailto or tel stays text. A field also takes Output field's format and link keys, like { type: "date", dateStyle: "short" } or { type: "url", linkLabel: "Visit website", linkTarget: "_blank" }; its hover title stays the value. The first visibleActions actions are buttons; the rest go in the menu at the end of the group. Follow shows when both following and onFollowingChange are passed, and toggles through onFollowingChange.

Examples

Case

A case followed by the user, its number as the name, and a datetime field in the `timeZone` given.

Case

00001026

Priority
High
Status
Escalated
Contact Name
Rose Gonzalez
Date/Time Opened
Oct 8, 2026, 10:32 AM
Case Owner
Tier 2 Support

Account

An account whose Billing Address is one line and whose Last Modified Date is `type="relative"`, counted from the `now` given.

Account

Edge Communications

Type
Customer - Direct
Billing Address
312 Constitution Place, Austin, TX 78767, USA
Account Owner
Jordan Lee
Last Modified Date
, Oct 13, 2026, 8:00 AM

Long name and empty fields

A long name truncates with its full text in `title`, and the close date and amount are `null`, so they show blank.

Opportunity

United Oil & Gas Corp. - Refinery Emergency Generators, Phase II Installation and Service Agreement

Close Date
Amount
Stage
Prospecting
Opportunity Owner
Ellen Hart

Loading

With `loading`, the object's label and the field labels stay, and the name, values and actions wait.

Opportunity

Account Name
Close Date
Amount
Stage
Opportunity Owner

API reference

RecordHeader

PropTypeDefaultDescription
icon*`standard:${string}` | `custom:${string}` | `action:${string}` | `doctype:${string}` | `utility:${string}`The object's icon: "standard:opportunity".
objectLabel*stringThe object's label, singular: "Opportunity".
name*stringThe record's name. It's the page's h1, and truncates to one line.
fieldsRecordHeaderField[][]The compact layout's fields after the name, in order. Up to six fit.
actionsRecordHeaderAction[][]The record's actions, in order.
visibleActionsnumber3How many actions show as buttons; the rest go in the menu. Default 3.
onAction(action: RecordHeaderAction) => voidRuns with the action that's chosen.
followingbooleanWhether the user follows the record.
onFollowingChange(following: boolean) => voidRuns with the new state when Follow is pressed; Follow shows only with this and following.
loadingbooleanfalseHolds every slot's size with placeholders while the record loads.
currencystring"USD"An ISO 4217 code for currency fields. Default "USD".
localestring"en-US"A BCP 47 locale for numbers and dates. Default "en-US".
timeZonestring"UTC"An IANA time zone for datetime fields. Default "UTC".
nowstring | number | DateThe instant relative fields count from, as ISO 8601. Defaults to the current time at render.

Also takes every <div> (opens in a new tab) prop.

RecordHeaderFieldTypetype

type RecordHeaderFieldType = OutputFieldType | "reference"

RecordHeaderFieldtype

One field from the compact layout, with how its value reads.

MemberTypeDefaultDescription
id*stringA stable key, like the field's API name: "CloseDate".
label*stringThe field's label, as the org names it: "Close Date".
value*string | number | boolean | OutputFieldAddress | OutputFieldName | nullThe plain value: a percent as a fraction, a date as YYYY-MM-DD, an instant as ISO 8601; null shows blank.
typeRecordHeaderFieldTypeHow the value reads. Default "text".
hrefstringFor a reference, where the related record's name links.
fractionDigitsnumberDigits after the decimal point, a field's scale, as both the fewest and the most. Unset, Intl's default.
minimumFractionDigitsnumberThe fewest digits after the decimal point, over fractionDigits.
maximumFractionDigitsnumberThe most digits after the decimal point, over fractionDigits; under the minimum, it reads as the minimum.
currencyDisplay"symbol" | "code" | "name"A currency as its symbol ("$"), its code ("USD") or its name ("US dollars"). Defaults to "symbol".
dateStyleOutputFieldDateStyleThe day's style in "date" and "datetime" values. Defaults to "medium": "Jun 18, 2026".
timeStyleOutputFieldDateStyleThe time's style in "datetime" and "time" values. Defaults to "short": "3:30 PM".
hour12booleantrue for a 12-hour clock, false for 24 hours. Unset, the locale's own clock.
timeZoneName"short" | "long"The zone's name after a "datetime" value, "EDT" or "Eastern Daylight Time". Unset, none.
linkLabelstringWords the link shows instead of the value, like "Visit website". The value stays its address.
linkTarget"_blank" | "_self" | "_parent" | "_top"Where the link opens; "_blank" adds rel="noopener noreferrer". Defaults to the same tab.
linkTitlestringThe link's hover text.

RecordHeaderActiontype

One of the record's actions, as a button or a menu item.

MemberTypeDefaultDescription
value*stringIdentifies the action in onAction: "edit", "clone".
label*stringThe action's name, in title case: "Change Owner".
disabledbooleanShows the action but doesn't let it run.

Accessibility

  • The record's name is the page's h1, so render one record header per page.
  • The action group is named for the object ("Opportunity actions"), and the menu trigger is named "More actions".
  • Follow is a toggle button: it reads as pressed while the user follows the record.
  • While loading, the header is busy and has no heading yet. The field labels stay readable.

Responsive behavior

  • The name stays on one line and truncates, with the full name on hover.
  • When the actions don't fit beside the name, they move under it.
  • The fields wrap when they don't fit in one row, and go two to a row on a narrow page. A long value truncates, with its full text on hover.

Rules

  • Pass the compact layout's fields in its order, after the name. Up to six fit in a row, as Lightning shows; which fields are highlights is the org's choice, so take it from the layout, not from this block.
  • Pass raw values with a type: numbers for amounts and percents (a percent as a fraction), YYYY-MM-DD for dates. Never pass formatted strings, which can't follow locale.
  • Pass null for an empty field. It shows blank, as Salesforce shows it. Never pass a dash, "None" or 0.
  • An address is { street, city, state, postalCode, country } and shows on one line, its parts joined by ", ". A name is { salutation, firstName, middleName, lastName, suffix }, in that order. Empty parts drop out; one with no parts shows blank.
  • A relative value is an instant, shown as "3 hours ago" with its date and time on hover. Pass now from the page, or the current time is read at render and a server and a browser render can differ.
  • Pass amounts in one currency and set currency to match.
  • The object icons come from @salesforce-ux/icons, a dependency licensed CC BY-ND 4.0: use them unaltered, and credit them.
  • Never pass asChild or render.