Output field
Shows a field's label and formatted value read-only, with an edit pencil.
Installation
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
- A page shows a record's field read-only: a label over or beside its value, as a record's Details tab does. It does what
lightning-output-fielddoes. - The value has a type that formats it: currency, percent, number, date, date and time, time of day, URL, email, phone or checkbox, as the
lightning-formatted-*components show them. Links get the right scheme. - A field needs its own format: a currency's code, a set number of decimals, a short or full date, a 24-hour clock or the time zone's name.
- A link reads as other words than its address, or opens in a new tab, as
lightning-formatted-url'slabelandtargetdo. - The field is an address or a name, Salesforce's compound fields, as
lightning-formatted-addressandlightning-formatted-nameshow them. - A date and time reads better as "3 hours ago", as
lightning-relative-date-timeshows it. - People can edit the field in place. The pencil is the trigger, and you build the editing form.
- A field needs help text in a tooltip beside its label.
Don't use it
- A whole record's sections and columns of fields. Use Record detail, which lays out output fields in SLDS's form layout.
- People type into the field. Use Field with an Input.
- Many records with the same fields. Use Data table, which formats values the same way.
Usage
OutputField
├── OutputFieldLabel
├── OutputFieldValue
├── OutputFieldEdit
└── FieldDescriptionimport {
OutputField,
OutputFieldLabel,
OutputFieldValue,
} from "@/components/wisty/output-field"<OutputField>
<OutputFieldLabel>Close Date</OutputFieldLabel>
<OutputFieldValue type="date" value="2026-11-14" />
</OutputField>A label's help shows help text in a tooltip from an info button beside it.
A lookup shows the related record's name and links to it with href. With loading, the value draws a placeholder and the pencil hides until the record arrives:
<OutputField loading={isLoading}>
<OutputFieldLabel>Account Name</OutputFieldLabel>
<OutputFieldValue value={account?.name} href={account?.url} />
<OutputFieldEdit onClick={() => edit("AccountId")} />
</OutputField>An address or a name takes its parts, and a relative time an instant and the now it counts from:
<OutputFieldValue
type="address"
value={{ street: "312 Constitution Place", city: "Austin", state: "TX" }}
/><OutputFieldValue type="relative" value={account.lastModified} now={now} />A field's format is its own: its decimals, a currency's code, a date's and a time's style, the clock and the zone's name. The org user's locale, currency and timeZone are the same on every field. A link's words, tab and hover title are linkLabel, linkTarget and linkTitle, and the value stays its address:
<OutputFieldValue
type="datetime"
value={event.start}
timeZone={user.timeZone}
dateStyle="short"
timeZoneName="short"
/>The data table formats its columns with the same formatOutputValue, so you can format a value as text anywhere with it. It takes the same format keys, and a data table column takes them in its meta. It writes an address on one line, its parts joined by ", ".
OutputFieldCompactValue draws a value with no field around it, as a table cell or a record header's detail shows it: a true checkbox is a check and a false one blank, and a relative time and a link read as they do in OutputFieldValue. The data table's cells and Record header's fields use it:
<OutputFieldCompactValue type="boolean" value={opportunity.isWon} />Examples
Value types
A lead's email, phone and website as links, a date, a date and time in its `timeZone`, and two checkboxes for true and false.
Numbers
An amount by its code with `currencyDisplay`, decimals bounded by `minimumFractionDigits` and `maximumFractionDigits`, and 18 digits passed as a string.
Date styles
Days in the four `dateStyle` values from short to full, an instant on a 24-hour clock with `hour12={false}`, and one with its zone from `timeZoneName`.
Time
Times of day as `type="time"`: the short style, a 24-hour clock with `hour12={false}`, and seconds with `timeStyle="medium"`.
Link labels
A website shown as `linkLabel`, opening in a new tab with `linkTarget` and a hover title from `linkTitle`, and an email shown by its label.
Locale and currency
An opportunity in `locale="de-DE"`, `currency="EUR"` and `timeZone="Europe/Berlin"`: euros, a percent, yen by code with no decimals, a date and a date and time.
Address
Two `address` values on their lines: a street over two lines, then city, state and postal code, then country, and one missing its street and state.
Name
A contact's `name` on one line, salutation, first and last name and suffix in order, with the empty middle name left out.
Relative time
Instants as `type="relative"` from a fixed `now`: 3 hours ago, yesterday and in 2 days, each with its date and time in a title.
Label beside the value
An account's fields with `layout="horizontal"`, and help beside one label from its `help`. Below a 48rem screen the labels stack.
API reference
| Part | Built on | Description |
|---|---|---|
OutputField | Field | |
OutputFieldLabel | FieldTitle | |
OutputFieldValue | <div> (opens in a new tab) | |
OutputFieldCompactValue | A value on one line, as a table cell or a header detail shows it: a true boolean is a check, false is blank. | |
OutputFieldEdit | Button |
OutputField
| Prop | Type | Default | Description |
|---|---|---|---|
loading | boolean | false | Still loading: the value is a placeholder, the edit button hides, the field is aria-busy. |
layout | "stacked" | "horizontal" | "auto" | "stacked" |
OutputFieldLabel
| Prop | Type | Default | Description |
|---|---|---|---|
help | React.ReactNode | Help text, in a tooltip from an info button beside the label. | |
helpLabel | string | "Help for" | The words before the label in the help button's name. Defaults to "Help for". |
OutputFieldValue
| Prop | Type | Default | Description |
|---|---|---|---|
type | OutputFieldType | "text" | How the value formats. Defaults to "text". |
value | OutputFieldPlainValue | The plain value: a percent as a fraction, a time as "HH:mm:ss", an address or name as its parts. null renders blank. | |
href | string | Links the value, like a lookup's record page or an address's map. url, email and phone link on their own. | |
linkLabel | string | Words 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. | |
linkTitle | string | The link's hover text. | |
locale | string | outputFieldFormatDefaults.locale | A BCP 47 locale. Defaults to "en-US". |
currency | string | outputFieldFormatDefaults.currency | An ISO 4217 code for "currency" values. Defaults to "USD". |
timeZone | string | outputFieldFormatDefaults.timeZone | An IANA time zone for "datetime" values, and the calendar a "relative" value counts days in. Defaults to "UTC". |
now | string | number | Date | The instant a "relative" value counts from, as ISO 8601. Defaults to the current time at render; pass it for a stable render. | |
fractionDigits | number | Digits after the decimal point, a field's scale, as both the fewest and the most. Unset, Intl's default. | |
minimumFractionDigits | number | The fewest digits after the decimal point, over fractionDigits. | |
maximumFractionDigits | number | The most digits after the decimal point, over fractionDigits; under the minimum, it reads as the minimum. | |
currencyDisplay | "symbol" | "code" | "name" | outputFieldFormatDefaults.currencyDisplay | A currency as its symbol ("$"), its code ("USD") or its name ("US dollars"). Defaults to "symbol". |
dateStyle | OutputFieldDateStyle | outputFieldFormatDefaults.dateStyle | The day's style in "date" and "datetime" values. Defaults to "medium": "Jun 18, 2026". |
timeStyle | OutputFieldDateStyle | outputFieldFormatDefaults.timeStyle | The time's style in "datetime" and "time" values. Defaults to "short": "3:30 PM". |
hour12 | boolean | true 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. |
OutputFieldCompactValue
A value on one line, as a table cell or a header detail shows it: a true boolean is a check, false is blank.
| Prop | Type | Default | Description |
|---|---|---|---|
type | OutputFieldType | "text" | How the value formats. Defaults to "text". |
value | OutputFieldPlainValue | The plain value: a percent as a fraction, a time as "HH:mm:ss", an address or name as its parts. null renders blank. | |
href | string | Links the value, like a lookup's record page or an address's map. url, email and phone link on their own. | |
linkLabel | string | Words 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. | |
linkTitle | string | The link's hover text. | |
locale | string | A BCP 47 locale. Defaults to "en-US". | |
currency | string | An ISO 4217 code for "currency" values. Defaults to "USD". | |
timeZone | string | An IANA time zone for "datetime" values, and the calendar a "relative" value counts days in. Defaults to "UTC". | |
now | string | number | Date | The instant a "relative" value counts from, as ISO 8601. Defaults to the current time at render; pass it for a stable render. | |
fractionDigits | number | Digits after the decimal point, a field's scale, as both the fewest and the most. Unset, Intl's default. | |
minimumFractionDigits | number | The fewest digits after the decimal point, over fractionDigits. | |
maximumFractionDigits | number | The 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". | |
dateStyle | OutputFieldDateStyle | The day's style in "date" and "datetime" values. Defaults to "medium": "Jun 18, 2026". | |
timeStyle | OutputFieldDateStyle | The time's style in "datetime" and "time" values. Defaults to "short": "3:30 PM". | |
hour12 | boolean | true 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. |
OutputFieldEdit
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | "Edit" | The word before the field's label in the button's name. Defaults to "Edit". |
compareOutputTimesfunction
Orders two "time" values by the clock: negative, zero or positive, or undefined when either isn't a time.
| Parameter | Type | Default |
|---|---|---|
a* | unknown | |
b* | unknown |
Returns number | undefined.
formatOutputValuefunction
Formats a value as its type shows it: a percent from a fraction (0.6 is 60%), a day in its style, an instant in its zone, a time of day, a phone number in the locale's form, an address on one line, a relative value counted from now. Text the type can't read passes through; empty values are "".
| Parameter | Type | Default |
|---|---|---|
value* | unknown | |
type | OutputFieldType | "text" |
options | OutputFieldFormatOptions |
Returns string.
outputValueHreffunction
The link for a url, email or phone value, or undefined. A relative URL stays as it is, a URL with no scheme gets https://, and one with a scheme other than http, https, mailto or tel gets no link.
| Parameter | Type | Default |
|---|---|---|
value* | unknown | |
type | OutputFieldType | "text" |
Returns string | undefined.
OutputFieldTypetype
type OutputFieldType =
| "text"
| "number"
| "currency"
| "percent"
| "date"
| "datetime"
| "time"
| "relative"
| "url"
| "email"
| "phone"
| "boolean"
| "address"
| "name"OutputFieldAddresstype
A compound address field's parts, like Billing Address. Any part may be missing.
| Member | Type | Default | Description |
|---|---|---|---|
street | string | null | The street, with a line break between lines. | |
city | string | null | The city or town. | |
state | string | null | The state or province. | |
postalCode | string | null | The postal or ZIP code. | |
country | string | null | The country's name. | |
latitude | number | null | The geocode's latitude, which isn't shown. | |
longitude | number | null | The geocode's longitude, which isn't shown. |
OutputFieldNametype
A compound name field's parts, like a contact's Name. Empty parts are left out.
| Member | Type | Default | Description |
|---|---|---|---|
salutation | string | null | "Mr.", "Ms.", "Dr." | |
firstName | string | null | The given name. | |
middleName | string | null | The middle name or initial. | |
lastName | string | null | The family name. | |
suffix | string | null | "Jr.", "III", "PhD" |
OutputFieldPlainValuetype
A plain value of any type: an address or a name is its parts.
type OutputFieldPlainValue =
| string
| number
| boolean
| Date
| OutputFieldAddress
| OutputFieldName
| nullOutputFieldDateStyletype
A named style for a day or a time of day: "short" ("6/18/26"), "medium", "long" or "full".
type OutputFieldDateStyle = "short" | "medium" | "long" | "full"OutputFieldStyleOptionstype
How one field shows its value; a key its type doesn't read is ignored.
| Member | Type | Default | Description |
|---|---|---|---|
fractionDigits | number | Digits after the decimal point, a field's scale, as both the fewest and the most. Unset, Intl's default. | |
minimumFractionDigits | number | The fewest digits after the decimal point, over fractionDigits. | |
maximumFractionDigits | number | The 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". | |
dateStyle | OutputFieldDateStyle | The day's style in "date" and "datetime" values. Defaults to "medium": "Jun 18, 2026". | |
timeStyle | OutputFieldDateStyle | The time's style in "datetime" and "time" values. Defaults to "short": "3:30 PM". | |
hour12 | boolean | true 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. |
OutputFieldFormatOptionstype
Options for formatOutputValue; a key left out or set to undefined takes its default.
| Member | Type | Default | Description |
|---|---|---|---|
locale | string | A BCP 47 locale. Defaults to "en-US". | |
currency | string | An ISO 4217 code for "currency" values. Defaults to "USD". | |
timeZone | string | An IANA time zone for "datetime" values, and the calendar a "relative" value counts days in. Defaults to "UTC". | |
now | string | number | Date | The instant a "relative" value counts from, as ISO 8601. Defaults to the current time at render; pass it for a stable render. | |
fractionDigits | number | Digits after the decimal point, a field's scale, as both the fewest and the most. Unset, Intl's default. | |
minimumFractionDigits | number | The fewest digits after the decimal point, over fractionDigits. | |
maximumFractionDigits | number | The 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". | |
dateStyle | OutputFieldDateStyle | The day's style in "date" and "datetime" values. Defaults to "medium": "Jun 18, 2026". | |
timeStyle | OutputFieldDateStyle | The time's style in "datetime" and "time" values. Defaults to "short": "3:30 PM". | |
hour12 | boolean | true 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. |
OutputFieldLinkOptionstype
How a value reads when it links: url, email and phone on their own, anything with href.
| Member | Type | Default | Description |
|---|---|---|---|
linkLabel | string | Words 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. | |
linkTitle | string | The link's hover text. |
SLDS mapping
OutputFieldisslds-form-element slds-form-element_readonly, withslds-form-element_editandslds-hint-parentwhen it holds anOutputFieldEdit.layout="horizontal"isslds-form-element_horizontal, andlayout="auto"is the same on a compact page (data-density="compact"), Lightning's compact display density.OutputFieldLabelisslds-form-element__label, a span in SLDS and aFieldTitlehere.OutputFieldValueisslds-form-element__static. A checkbox value isslds-checkbox_faux, drawn checked or empty. An address is the static value on its lines.OutputFieldEditis theslds-button_iconwithslds-button__icon_hint. A label'shelpisslds-form-element__iconwith its tooltip.
Known gaps:
- An address and a name follow Salesforce's default (en-US) order for every country and locale; Lightning's per-country and per-locale formats aren't drawn.
- An address doesn't link to a map on its own. Pass the map page as
href. - The edited state (
slds-is-edited) and its undo button (slds-form-element__undo) belong to the editing form: Record form draws them withhighlightChanges, and Record inline edit switches output fields to it. - Rich text and the user avatar beside a lookup aren't drawn.
- A phone number formats only in en-US and en-CA, as "(425) 555-0155". Other countries' formats aren't drawn.
lightning-formatted-email's envelope icon isn't drawn. Put an Icon beside the value.lightning-formatted-number's significant and integer digits, andlightning-formatted-date-time's separate weekday, era and field options, aren't taken. The four date and time styles cover record pages.
| Prop | Value | SLDS | Notes |
|---|---|---|---|
layout | stacked | slds-form-element_readonly slds-form-element_stacked | The label above the value. |
layout | horizontal | slds-form-element_readonly slds-form-element_horizontal | The label in a column beside the value, from a 48rem screen. |
layout | auto | slds-form-element_readonly, stacked or horizontal by density | Stacked, and horizontal when the page is compact (data-density="compact"). |
Accessibility
OutputFieldis a group named by its label, so a screen reader hears "Annual Revenue" and then the value. Put only the label's words inOutputFieldLabel; help goes inhelp.- The pencil is named "Edit" and the label, like "Edit Annual Revenue", and the help button "Help for" and the label. Translate the words with
labelonOutputFieldEditandhelpLabelonOutputFieldLabel. - A checkbox value is read as "True" or "False".
- A relative time is read with its date and time after it, like "3 hours ago, Oct 13, 2026, 8:00 AM", which is also its title.
- A
linkLabelis the link's name, read in place of the address, so make it say where the link goes. Nothing says a link opens a new tab; say it in the label when it matters.
Rules
- Pass plain values. A percent is a fraction: 0.6 shows as 60%, so divide a Salesforce percent field's 60 by 100.
- A date is a day (
"2026-11-14") and a datetime an instant; pick the type that matches the field, or a day can move across midnight. - An
addressis{ street, city, state, postalCode, country }and anameis{ salutation, firstName, middleName, lastName, suffix }, any partnullor left out. An address shows its street's lines, then "City, State PostalCode", then the country, and a name shows its parts in that order; a missing part drops out with its comma. One with no parts renders blank. - A
relativevalue is an instant, counted fromnow. Passnowfrom the page (one value for every field) for a render that stays the same; without it, the current time is read at render, so a server and a browser render can differ. It counts in the largest unit that fits: under 45 seconds is "now", then minutes, hours under 22, days under 26, months under 11, then years. "Yesterday" means the day before intimeZone. - Pass
nullfor a field that's empty in the record, which renders blank. Leave out a field people can't read; don't render it blank. - A
urlvalue that starts with/,./,../,#or?links as it is, relative to the page. One with no scheme links withhttps://, a host with a port included (intranet.acme.com:8443), and so does a protocol-relative//host. One with another scheme than http, https, mailto or tel, likejavascript:, shows as text and doesn't link. linkLabel,linkTargetandlinkTitleapply only to a value that links.linkTarget="_blank"addsrel="noopener noreferrer", and a blank label shows the value.- A
timevalue is a time of day,"HH:mm","HH:mm:ss"or"HH:mm:ss.SSS", as Salesforce returns a Time field; aZor an offset after it is ignored. It never moves withtimeZone, and other text shows as stored. - A
phonevalue of 10 digits, or 11 starting with 1, reads "(425) 555-0155" in an en-US or en-CAlocale. Anything else shows as stored,+1numbers and separators included. - Pass an amount over 15 digits as a decimal string, like
"123456789012345678.90", to show every digit. A number keeps about 15. timeZoneNameadds the zone after adatetimein the short or mediumtimeStyle; long and full already name it. A maximum under the minimum reads as the minimum.formatOutputValueformats in en-US, USD and UTC unless you passlocale,currencyortimeZone, the same defaults asOutputFieldValue. Pass the org user's values to both, or a record page reads one instant on two days.
Related
- FieldLays out a form control with its label, help text and error.
- Record detailA record's Details tab, read-only, for a standard or custom object.
- Record inline editA record's Details tab, edited in place with a pencil, Cancel and Save.
- Data tableShows records in a table that sorts, selects, runs row actions and loads more.
- TooltipShows a short hint about a control while it has hover or keyboard focus.