ObjectStackObjectStack

Component

Component protocol schemas

Empty Properties Schema

Source: packages/spec/src/ui/component.zod.ts

TypeScript Usage

import { AIChatWindowProps, ElementButtonPropsSchema, ElementFilterPropsSchema, ElementFormPropsSchema, ElementImagePropsSchema, ElementMetadataViewerPropsSchema, ElementNumberPropsSchema, ElementRecordPickerPropsSchema, ElementTextInputPropsSchema, ElementTextPropsSchema, ObjectCalendarPropsSchema, ObjectFormPropsSchema, ObjectGridPropsSchema, ObjectKanbanPropsSchema, ObjectMasterDetailFormPropsSchema, ObjectMetricPropsSchema, PageAccordionProps, PageCardProps, PageContainerProps, PageHeaderProps, PageTabsProps, RecordActivityProps, RecordChatterProps, RecordDetailsProps, RecordHighlightsField, RecordHighlightsProps, RecordPathProps, RecordRelatedListProps } from '@objectstack/spec/ui';
import type { ElementNumberProps, ElementRecordPickerProps, ObjectCalendarProps, ObjectFormProps, ObjectGridProps, ObjectKanbanProps, ObjectMasterDetailFormProps, ObjectMetricProps, PageContainerProps, RecordHighlightsField, RecordPathProps } from '@objectstack/spec/ui';

// Validate data
const result = AIChatWindowProps.parse(data);

AIChatWindowProps

Properties

PropertyTypeRequiredDescription
modeEnum<'float' | 'sidebar' | 'inline'>Display mode for the chat window
agentIdstringoptionalSpecific AI agent to use
contextRecord<string, any>optionalContextual data to pass to the AI
aria{ ariaLabel?: string | Record<string, string>; ariaDescribedBy?: string; role?: string }optionalARIA accessibility attributes

ElementButtonProps

Properties

PropertyTypeRequiredDescription
labelstring | Record<string, string>Button display label
variantEnum<'primary' | 'secondary' | 'danger' | 'ghost' | 'link'>optionalButton visual variant
sizeEnum<'small' | 'medium' | 'large'>optionalButton size
iconstringoptionalIcon name (Lucide icon)
iconPositionEnum<'left' | 'right'>optionalIcon position relative to label
disabledbooleanoptionalDisable the button
action{ type?: Enum<'script' | 'url' | 'modal' | 'flow' | 'api' | 'form'>; name?: string; label?: string | Record<string, string>; target?: string; … }optionalInline action executed on click
aria{ ariaLabel?: string | Record<string, string>; ariaDescribedBy?: string; role?: string }optionalARIA accessibility attributes

ElementFilterProps

Properties

PropertyTypeRequiredDescription
objectstringObject to filter
fieldsstring[]Filterable field names
targetVariablestringoptionalPage variable to store filter state
layoutEnum<'inline' | 'dropdown' | 'sidebar'>Filter display layout
showSearchbooleanShow search input
aria{ ariaLabel?: string | Record<string, string>; ariaDescribedBy?: string; role?: string }optionalARIA accessibility attributes

ElementFormProps

Properties

PropertyTypeRequiredDescription
objectstringObject for the form
fieldsstring[]optionalFields to display (defaults to all editable fields)
modeEnum<'create' | 'edit'>optionalForm mode
submitLabelstring | Record<string, string>optionalSubmit button label
onSubmitstring | { dialect: Enum<'cel' | 'cron' | 'template'>; source?: string; ast?: any; meta?: object }optionalAction expression on form submit (CEL)
aria{ ariaLabel?: string | Record<string, string>; ariaDescribedBy?: string; role?: string }optionalARIA accessibility attributes

ElementImageProps

Properties

PropertyTypeRequiredDescription
srcstringImage URL or attachment field
altstringoptionalAlt text for accessibility
fitEnum<'cover' | 'contain' | 'fill'>Image object-fit mode
heightnumberoptionalFixed height in pixels
aria{ ariaLabel?: string | Record<string, string>; ariaDescribedBy?: string; role?: string }optionalARIA accessibility attributes

ElementMetadataViewerProps

Properties

PropertyTypeRequiredDescription
typeEnum<'state_machine' | 'flow' | 'permission'>Metadata view kind (ADR-0051): state_machine | flow | permission
namestringTarget metadata item name; resolved package-scoped (ADR-0048), then dependencies (ADR-0046 §3.3)
objectstringoptionalOwning object — required for object-scoped kinds: state_machine is a rule ON an object (ADR-0020), permission renders a matrix FOR one; omit for top-level flow
modeEnum<'diagram' | 'matrix' | 'summary'>optionalRender form; defaults per type (diagram for flow/state_machine, matrix for permission)
detailEnum<'business' | 'technical'>Authoring altitude (ADR-0051 §3.4): business collapses technical flow nodes to business steps + approvals. NOT access (cf. book.audience); permission projection is automatic and render-time, never set here
aria{ ariaLabel?: string | Record<string, string>; ariaDescribedBy?: string; role?: string }optionalARIA accessibility attributes

ElementNumberProps

Properties

PropertyTypeRequiredDescription
objectstringSource object
fieldstringoptionalField to aggregate
aggregateEnum<'count' | 'sum' | 'avg' | 'min' | 'max'>Aggregation function
filteranyoptionalFilter criteria
formatEnum<'number' | 'currency' | 'percent'>optionalNumber display format
prefixstringoptionalPrefix text (e.g. "$")
suffixstringoptionalSuffix text (e.g. "%")
aria{ ariaLabel?: string | Record<string, string>; ariaDescribedBy?: string; role?: string }optionalARIA accessibility attributes

ElementRecordPickerProps

Properties

PropertyTypeRequiredDescription
objectstringObject to pick records from
labelFieldstringoptionalField rendered as each row's text (default name)
valueFieldstringoptionalField whose value is written into the bound page variable (default id)
labelstring | Record<string, string>optionalControl label rendered above the select
filteranyoptionalFilter criteria for available records
sort{ field: string; order: Enum<'asc' | 'desc'> }[]optionalRow order — synonym of the component-level dataSource.sort, which takes precedence when both are set
limitintegeroptionalMax records offered — synonym of the component-level dataSource.limit, which takes precedence when both are set (renderer default 50)
targetVariablestringoptionalPage variable to bind selected record ID(s)
placeholderstring | Record<string, string>optionalPlaceholder text
emptyTextstring | Record<string, string>optionalText shown when the query returns no records (default "No records")
displayFieldneveroptional[REMOVED] element:record_picker property displayField was removed in @objectstack/spec 17.0.0 (#5775, ADR-0087 D2) — it was a required declaration no renderer ever read, while the renderer honoured labelField for the same thing and defaulted to name. Rename the key to labelField; the value (a field name) is unchanged. Run os migrate meta --from 16 to rewrite existing sources automatically.
searchFieldsneveroptional[REMOVED] element:record_picker property searchFields was removed in @objectstack/spec 17.0.0 (#5775, ADR-0049) — the picker renders a plain single-select with no search input, so no renderer ever read it and it narrowed nothing. Delete the key. To restrict which records the picker offers, use filter (or the component-level dataSource.filter), which the query path does apply. Run os migrate meta --from 16 to rewrite existing sources automatically.
multipleneveroptional[REMOVED] element:record_picker property multiple was removed in @objectstack/spec 17.0.0 (#5775, ADR-0049) — the picker is a single-select Select and the bound page variable holds one record id, so multiple: true selected nothing extra and reported success. Delete the key; multi-record selection is not implemented on this element. Run os migrate meta --from 16 to rewrite existing sources automatically.
aria{ ariaLabel?: string | Record<string, string>; ariaDescribedBy?: string; role?: string }optionalARIA accessibility attributes

ElementTextInputProps

Properties

PropertyTypeRequiredDescription
inputTypeEnum<'text' | 'email' | 'number' | 'tel' | 'url' | 'password'>Native input type — drives keyboard/validation affordance and how the bound value is coerced (number → numeric).
labelstring | Record<string, string>optionalField label shown above the input
placeholderstring | Record<string, string>optionalPlaceholder text shown when empty
defaultValuestring | numberoptionalInitial value; seeds the bound page variable on mount
requiredbooleanMark the field as required
disabledbooleanDisable the input
descriptionstring | Record<string, string>optionalHelper text shown below the input
targetVariablestringoptionalPage variable this input writes to. Declarative hint; the live binding resolves via the variable whose source equals this component id (see PageVariableSchema).
aria{ ariaLabel?: string | Record<string, string>; ariaDescribedBy?: string; role?: string }optionalARIA accessibility attributes

ElementTextProps

Properties

PropertyTypeRequiredDescription
contentstring | Record<string, string>Text or Markdown content — a plain string, or an inline locale map
variantEnum<'heading' | 'subheading' | 'body' | 'caption'>Text style variant
alignEnum<'left' | 'center' | 'right'>Text alignment
aria{ ariaLabel?: string | Record<string, string>; ariaDescribedBy?: string; role?: string }optionalARIA accessibility attributes

ObjectCalendarProps

Properties

PropertyTypeRequiredDescription
objectNamestringoptionalObject this calendar binds to. Optional because the component-level dataSource binding can supply the object instead (#6953)
calendaranyoptionalCalendar field config: { startDateField, endDateField?, titleField?, colorField?, allDayField? }
defaultViewEnum<'month' | 'week' | 'day'>optionalInitial view mode
filteranyoptionalBase query filter
sortanyoptionalSort for the fetched events
dataany[]optionalPre-fetched records — skips the internal fetch
staticDataany[]optionalStatic inline records
localestringoptionalLocale override for the calendar chrome
loadingbooleanoptionalExternal loading state (honoured only alongside data)

ObjectFormProps

Properties

PropertyTypeRequiredDescription
objectNamestringoptionalObject this form creates/edits. Optional because the component-level dataSource binding can supply the object instead (#6953)
recordIdstring | numberoptionalRecord to load (edit/view modes)
modeEnum<'create' | 'edit' | 'view'>optionalForm mode
formTypeEnum<'simple' | 'tabbed' | 'wizard' | 'split' | 'drawer' | 'modal'>optionalForm presentation
layoutEnum<'vertical' | 'horizontal' | 'inline' | 'grid'>optionalField layout
columnsnumberoptionalField columns in grid layout
fieldsany[]optionalLimit/order the fields shown
customFieldsanyoptionalCustom field definitions merged into the generated set
sectionsany[]optionalForm sections ({ label, description?, fields } — wizard steps / tab panes)
titlestring | Record<string, string>optionalForm title
descriptionstring | Record<string, string>optionalForm description (rendered by the drawer/modal presentations)
defaultTabstringoptionalInitially active tab (tabbed)
tabPositionEnum<'top' | 'bottom' | 'left' | 'right'>optionalTab strip position (tabbed)
allowSkipbooleanoptionalAllow skipping steps (wizard)
showStepIndicatorbooleanoptionalShow the step indicator (wizard)
splitDirectionEnum<'horizontal' | 'vertical'>optionalSplit direction (split)
splitSizenumberoptionalSplit panel size in percent (split)
splitResizablebooleanoptionalAllow resizing the split (split)
drawerSideEnum<'top' | 'bottom' | 'left' | 'right'>optionalDrawer side (drawer)
drawerWidthstring | numberoptionalDrawer width (drawer)
modalSizeEnum<'sm' | 'default' | 'lg' | 'xl' | 'full'>optionalModal size (modal)
modalCloseButtonbooleanoptionalShow the modal close button (modal)
contentLayoutanyoptionalModal content layout config (modal)
confirmOnDiscardbooleanoptionalConfirm before discarding edits (drawer/modal)
submitTextstring | Record<string, string>optionalSubmit button label
cancelTextstring | Record<string, string>optionalCancel button label
nextTextstring | Record<string, string>optionalNext-step button label (wizard)
prevTextstring | Record<string, string>optionalPrevious-step button label (wizard)
showSubmitbooleanoptionalShow the submit button
showCancelbooleanoptionalShow the cancel button
showResetbooleanoptionalShow the reset button
submitBehavioranyoptionalWhat happens after a successful submit ({ kind: 'thank-you' | …, title?, message? })
successMessagestring | Record<string, string>optionalToast message on successful submit
resetOnSuccessbooleanoptionalReset the form after a successful submit
navigateOnSuccessanyoptionalNavigate after a successful submit
readOnlybooleanoptionalRender every field read-only
initialValuesRecord<string, any>optionalPrefill values (create mode)
initialDataRecord<string, any>optionalAlternate spelling of initialValues the renderer also reads
mobileanyoptionalMobile presentation overrides

ObjectGridProps

Properties

PropertyTypeRequiredDescription
objectNamestringoptionalObject this grid binds to. Optional because the component-level dataSource binding can supply the object instead (#6953)
labelstring | Record<string, string>optionalGrid label — used as the table caption and export file title
titlestring | Record<string, string>optionalFallback for label (the renderer reads label || title)
columnsany[]optionalColumns: field names or column definition objects
fieldsany[]optionalField list fallback used when columns is absent
filteranyoptionalBase query filter (ObjectQL filter array/AST) — lowered to the wire $filter. THE key #7750 misspelled as plural
defaultFiltersanyoptionalLegacy base-filter fallback, read only when filter is absent. Prefer filter
sortanyoptionalInitial sort (array of { field, order })
defaultSortanyoptionalLegacy single-sort fallback ({ field, order }), read only when sort is absent. Prefer sort
paginationanyoptionalPagination config ({ pageSize, pageSizeOptions, … }); its presence enables paging
pageSizenumberoptionalFlat page-size shorthand; pagination.pageSize wins when both are set
showPaginationbooleanoptionalShow the pager (read only when pagination is absent)
searchableFieldsstring[]optionalFields the toolbar search queries; a non-empty list enables search
showSearchbooleanoptionalShow the search box (read only when searchableFields is absent)
rowHeightanyoptionalRow density mode (e.g. compact / comfortable)
groupinganyoptionalRow grouping config
aggregationsanyoptionalGroup aggregation config (sum/avg/… per column)
conditionalFormattinganyoptionalConditional row/cell formatting rules
rowColoranyoptionalRow color rules
selectionanyoptionalSelection config ({ type: none | single | multiple })
selectableanyoptionalLegacy selection shorthand, read only when selection is absent. Prefer selection
rowActionsany[]optionalPer-row action names
bulkActionsany[]optionalBulk action names shown on selection
batchActionsany[]optionalAlternate spelling the renderer reads FIRST (batchActions ?? bulkActions)
bulkActionDefsany[]optionalInline bulk-action definitions (full defs, not names)
navigationanyoptionalRow-click navigation config ({ mode: page | drawer | modal | split | none })
editablebooleanoptionalEnable inline cell editing
singleClickEditbooleanoptionalEnter cell edit on single click (default true when editable)
resizablebooleanoptionalAllow column resize (read before resizableColumns)
resizableColumnsbooleanoptionalAlternate spelling of resizable (the renderer reads resizable ?? resizableColumns)
reorderableColumnsbooleanoptionalAllow column drag-reorder
frozenColumnsnumberoptionalHow many leading columns stay frozen (default 1)
showColumnTypeIconsbooleanoptionalShow field-type icons in column headers
exportOptionsanyoptionalExport config ({ formats, streaming })
operationsanyoptionalOperation toggles ({ export: false, … })
dataany[]optionalStatic inline rows — bypasses the object query
staticDataany[]optionalAlternate spelling of data the renderer also reads

ObjectKanbanProps

Properties

PropertyTypeRequiredDescription
objectNamestringoptionalObject this board binds to. Optional because the component-level dataSource binding can supply the object instead (#6953)
groupBystringoptionalField whose values become the board columns
columnsany[]optionalSwimlane definitions ({ id, title } per groupBy value, or bare value strings) — NOT a field projection
filteranyoptionalBase query filter, handed to the wire $filter
dataany[]optionalStatic inline cards — bypasses the object query
cardTitlestringoptionalField rendered as each card title
titleFieldstringoptionalLegacy fallback for cardTitle (the board reads cardTitle || titleField). Prefer cardTitle
cardFieldsstring[]optionalFields rendered on each card
swimlaneFieldstringoptionalField for horizontal swimlanes (in addition to columns)
groupinganyoptionalView grouping config; its first field is the swimlane fallback
quickAddbooleanoptionalShow the per-column quick-add affordance
coverImageFieldstringoptionalImage field rendered as the card cover
conditionalFormattinganyoptionalCard conditional formatting rules

ObjectMasterDetailFormProps

Properties

PropertyTypeRequiredDescription
objectNamestringoptionalPARENT object. Optional because the component-level dataSource binding can supply the object instead (#7121)
recordIdstring | numberoptionalParent record to load (edit mode)
modeEnum<'create' | 'edit'>optionalForm mode
formTypestringoptionalParent form presentation
sectionsany[]optionalParent form sections
fieldsany[]optionalParent fields shown
detailsany[]optionalDetail collections ({ title, childObject, addLabel?, columns?, relationshipField? } — FK and columns auto-derive from child metadata)
titlestring | Record<string, string>optionalForm title
submitTextstring | Record<string, string>optionalSubmit button label
cancelTextstring | Record<string, string>optionalCancel button label
showSubmitbooleanoptionalShow the submit button
initialValuesRecord<string, any>optionalPrefill values for the parent (create mode)
initialDataRecord<string, any>optionalAlternate spelling of initialValues the renderer also reads
taxRateFieldstringoptionalChild field holding the per-line tax rate (line-items totals)

ObjectMetricProps

Properties

PropertyTypeRequiredDescription
objectNamestringoptionalObject this metric aggregates. Optional because the component-level dataSource binding can supply the object instead (#6953)
labelstring | Record<string, string>optionalMetric label
descriptionstring | Record<string, string>optionalHelper text under the value
titlestring | Record<string, string>optionalDrill-down panel title; defaults to the metric label
iconstringoptionalIcon name (Lucide)
colorVariantEnum<'default' | 'blue' | 'teal' | 'orange' | 'purple' | 'success' | 'warning' | 'danger'>optionalIcon container color variant
aggregateanyoptionalAggregation config ({ field, function, groupBy? }) run against the object
filteranyoptionalFilter the aggregation is scoped by
formatstringoptionalNumber format pattern (e.g. '0,0', '$0,0', '0%')
currencystringoptionalISO currency code (e.g. 'USD') — enables currency formatting
prefixstringoptionalStatic prefix before the formatted value
suffixstringoptionalStatic suffix after the formatted value
invertbooleanoptionalDisplay 1 - value for opposite-signal gauges (compliance/uptime)
variantEnum<'card' | 'bare'>optionalLayout variant
fallbackValuestring | numberoptionalStatic value shown when no data source is available
trendanyoptionalStatic trend info ({ value, label, direction })
drillDownanyoptionalClick-through drill config — opens the underlying records
compareToanyoptionalPeriod-over-period comparison ({ kind: 'previousPeriod' | 'previousYear' })

PageAccordionProps

Properties

PropertyTypeRequiredDescription
items{ label: string | Record<string, string>; icon?: string; collapsed: boolean; children: any[] }[]
allowMultiplebooleanAllow multiple panels to be expanded simultaneously
variantEnum<'flush' | 'card'>Panel framing: 'flush' draws a divider under each panel; 'card' leaves the border to each panel's own content
aria{ ariaLabel?: string | Record<string, string>; ariaDescribedBy?: string; role?: string }optionalARIA accessibility attributes

PageCardProps

Properties

PropertyTypeRequiredDescription
titlestring | Record<string, string>optionalDisplay label — the default-language string, or an inline locale map ({ en, "zh-CN" }) resolved at render time
borderedboolean
actionsneveroptional[REMOVED] page:card property actions was removed in @objectstack/spec 17.0.0 (#6946, ADR-0087 D2) — no renderer ever read it: objectui's card renderer builds its <Card> from title, bordered, children and footer only, has no actions area, and the component registry never published it as an input, so an authored value was accepted and dropped. Delete the key and author the buttons as components in the card's children or footer (element:button, record:quick_actions), which is what actually renders. Run os migrate meta --from 16 to rewrite existing sources automatically.
childrenany[]optionalCard content components, in order (the card body slot)
bodyneveroptional[REMOVED] page:card property body was removed in @objectstack/spec 17.0.0 (#5775, ADR-0087 D2) — it was a second spelling of the composition slot every other container calls children, and the renderer reads both. Rename the key to children; the value (an array of child components) is unchanged. Run os migrate meta --from 16 to rewrite existing sources automatically.
footerany[]optionalCard footer components (slot)
aria{ ariaLabel?: string | Record<string, string>; ariaDescribedBy?: string; role?: string }optionalARIA accessibility attributes

PageContainerProps

Properties

PropertyTypeRequiredDescription
childrenany[]optionalChild components rendered inside this container, in order

PageHeaderProps

Properties

PropertyTypeRequiredDescription
titlestring | Record<string, string>optionalPage title. Omit to let the renderer derive the heading from the record (the default for record pages) — set explicitly on non-record pages (dashboard, landing) with no record to derive from.
subtitlestring | Record<string, string>optionalPage subtitle
iconneveroptional[REMOVED] page:header property icon was removed in @objectstack/spec 17.0.0 (#6946, ADR-0087 D2) — no renderer ever read it: objectui resolves icon only per header action (action.icon), never off the header's own props bag, and the component registry never published it as an input, so an authored value was accepted and dropped. Delete the key. The header's own identity is drawn by the record chrome (recordChrome, on by default) and each action carries its own icon. Run os migrate meta --from 16 to rewrite existing sources automatically.
breadcrumbbooleanShow breadcrumb
actionsstring[]optionalAction IDs to show in header
recordChromebooleanRender the record chrome — the title as a record chip with its follow star and copy-id button. Set false on a non-record page (dashboard, landing) to fall back to the bare heading layout.
showStarbooleanShow the follow (favourite) star beside the record title. Part of the record chrome — no effect when recordChrome is false.
showCopyIdbooleanShow the copy-record-id button beside the record title. Part of the record chrome — no effect when recordChrome is false.
maxVisibleintegeroptionalHow many header actions render as inline buttons before the rest fold into the overflow menu (renderer default 3).
mobileMaxVisibleintegeroptionalThe maxVisible budget on mobile viewports (renderer default 1).
aria{ ariaLabel?: string | Record<string, string>; ariaDescribedBy?: string; role?: string }optionalARIA accessibility attributes

PageTabsProps

Properties

PropertyTypeRequiredDescription
tabStyleEnum<'line' | 'card' | 'pill'>optionalTab-strip visual style: 'line' underlines the active tab, 'card' frames each tab, 'pill' renders rounded pills
typeneveroptional[REMOVED] page:tabs property type was removed in @objectstack/spec 17.0.0 (#6776, ADR-0087 D2) — a props key named type collides with the page component's own dispatch key, so it is unauthorable in the flat and JSX carriers and was never validated in them. Rename the key to tabStyle; the value (line | card | pill) is unchanged. Run os migrate meta --from 16 to rewrite existing sources automatically.
positionEnum<'top' | 'left'>optional
alwaysShowStripbooleanoptionalRender the tab strip even when only one tab is visible (renderer default: a one-tab strip is hidden).
items{ label: string | Record<string, string>; icon?: string; visibleWhen?: string | object; value?: string; … }[]
aria{ ariaLabel?: string | Record<string, string>; ariaDescribedBy?: string; role?: string }optionalARIA accessibility attributes

RecordActivityProps

Properties

PropertyTypeRequiredDescription
typesEnum<'comment' | 'field_change' | 'task' | 'event' | 'email' | 'call' | 'note' | 'file' | 'record_create' | 'record_delete' | 'approval' | 'sharing' | 'system'>[]optionalFeed item types to show (default: all)
filterModeEnum<'all' | 'comments_only' | 'changes_only' | 'tasks_only'>Default activity filter
showFilterTogglebooleanShow filter dropdown in panel header
limitintegerNumber of items to load per page
showCompletedbooleanInclude completed activities
unifiedTimelinebooleanMix field changes and comments in one timeline (Airtable style)
showCommentInputbooleanShow "Leave a comment" input at the bottom
enableMentionsbooleanEnable @mentions in comments
enableReactionsbooleanEnable emoji reactions on feed items
enableThreadingbooleanEnable threaded replies on comments
showSubscriptionTogglebooleanShow bell icon for record-level notification subscription
aria{ ariaLabel?: string | Record<string, string>; ariaDescribedBy?: string; role?: string }optionalARIA accessibility attributes

RecordChatterProps

Properties

PropertyTypeRequiredDescription
positionEnum<'sidebar' | 'inline' | 'drawer'>Where to render the chatter panel
widthstring | numberoptionalPanel width (e.g., "350px", "30%")
collapsiblebooleanWhether the panel can be collapsed
defaultCollapsedbooleanWhether the panel starts collapsed
feed{ types?: Enum<'comment' | 'field_change' | 'task' | 'event' | 'email' | 'call' | 'note' | … +6 more>[]; filterMode: Enum<'all' | 'comments_only' | 'changes_only' | 'tasks_only'>; showFilterToggle: boolean; limit: integer; … }optionalEmbedded activity feed configuration
aria{ ariaLabel?: string | Record<string, string>; ariaDescribedBy?: string; role?: string }optionalARIA accessibility attributes

RecordDetailsProps

Properties

PropertyTypeRequiredDescription
columnsEnum<'1' | '2' | '3' | '4'>Number of columns for field layout (1-4)
layoutneveroptional[REMOVED] record:details property layout was removed in @objectstack/spec 17.0.0 (#6946, ADR-0087 D2) — its declared auto | custom semantics were never implemented: the renderer tests layout only against inline | compact, two values the schema never permitted, so both legal values took the same branch and the key selected nothing. Delete the key — the body is already chosen by what you author: sections renders the explicit groups (the old custom), and omitting it falls back to the object's highlightFields (the old auto). Run os migrate meta --from 16 to rewrite existing sources automatically.
sections{ name?: string; label?: string | Record<string, string>; columns?: integer; fields: string[] }[]optionalField groups rendered as the detail body, in order. Object form: { name?, label?, columns?, fields }.
fieldsstring[]optionalExplicit field list to display (optional, overrides highlightFields)
hideFieldsstring[]optionalField names to omit from the body — applied to fields and to every section's fields (used to dedupe fields already shown in record:highlights or as the page title)
inlineEditbooleanoptionalAllow inline field editing in the detail body (renderer default: on, where the object itself is editable — set false to force it off).
showHeaderbooleanoptionalRender the detail body's own heading (renderer default: off).
aria{ ariaLabel?: string | Record<string, string>; ariaDescribedBy?: string; role?: string }optionalARIA accessibility attributes

RecordHighlightsField

Highlight field: bare name, or {name,label?,icon?,type?,readonly?}

Union Options

This schema accepts one of the following structures:

Option 1

Type: string


Option 2

Properties

PropertyTypeRequiredDescription
namestringField name on the record
labelstringoptionalDisplay label (overrides schema label)
iconstringoptionalIcon name (lucide icon key)
typestringoptionalOverride cell renderer type (rare)
readonlybooleanoptionalRender this chip read-only — suppresses inline editing on the highlight card. Use for hook/automation-maintained columns that must not be hand-edited from the record header.


RecordHighlightsProps

Properties

PropertyTypeRequiredDescription
fields(string | { name: string; label?: string; icon?: string; type?: string; … })[]Key fields to highlight (1-7 fields max, typically displayed as prominent cards). Each item may be a bare field name or {name, label?, icon?, type?, readonly?} for inline overrides.
layoutEnum<'horizontal' | 'vertical'>Layout orientation for highlight fields
aria{ ariaLabel?: string | Record<string, string>; ariaDescribedBy?: string; role?: string }optionalARIA accessibility attributes

RecordPathProps

Properties

PropertyTypeRequiredDescription
statusFieldstringField name representing the current status/stage
stages{ value: string; label: string | Record<string, string>; terminal?: Enum<'won' | 'lost'> }[]optionalExplicit stage definitions (if not using field metadata)
aria{ ariaLabel?: string | Record<string, string>; ariaDescribedBy?: string; role?: string }optionalARIA accessibility attributes

RecordRelatedListProps

Properties

PropertyTypeRequiredDescription
objectNamestringRelated object name (e.g., "task", "opportunity")
relationshipFieldstringField on related object that points to this record (e.g., "account_id")
relationshipValueFieldstringParent-record field whose value relationshipField stores (default 'id'; e.g. 'name' for name-keyed junctions).
columnsstring[]optionalFields to display in the related list. Optional: when omitted, columns derive from the related object's highlightFields / default list columns (a related list is just another surface that lists that object). Override chain: child highlightFields → field-level relatedListColumns → this inline list.
sortstring | { field: string; order: Enum<'asc' | 'desc'> }[]optionalSort order for related records
limitintegerNumber of records to display initially
filter{ field: string; operator: Enum<'equals' | 'not_equals' | 'contains' | 'not_contains' | 'starts_with' | … +14 more>; value?: string | number | boolean | null | (string | number)[] }[]optionalAdditional filter criteria for related records
titlestring | Record<string, string>optionalCustom title for the related list
showViewAllbooleanShow "View All" link to see all related records
actionsstring[]optionalAction IDs available for related records
add{ picker: object; linkField?: string; label?: string | Record<string, string> }optionalAdd-existing-via-picker config (generic m2m/junction assignment).
aria{ ariaLabel?: string | Record<string, string>; ariaDescribedBy?: string; role?: string }optionalARIA accessibility attributes

On this page