Skip to content

Component Reference

This section documents the context fields recognized by each component type. Fields prefixed _ are private (not inherited by children). Fields without _ are public and inherited down the tree.

Vertical (vstack) and horizontal (hstack) stack containers. Children are arranged along the stack axis with optional spacing and alignment.

Context keyTypeDescription
_spacing / spacingnumberGap in points between children.
_alignment / alignmentstringvstack: leading
_lazy / lazybooleanWhen true, renders children lazily on demand as they scroll into view. Default: false.

Z-axis overlay container. Children are stacked on top of each other, back to front.

Context keyTypeDescription
_alignment / alignmentstringAnchor: topLeading
Context keyTypeDescription
_axis / axisstringScroll direction: vertical (default) or horizontal.
_showIndicators / showIndicatorsboolShow or hide scroll indicators. Default: true.
_scrollTrigger / scrollTriggerany / exprOptional. When set AND style.scroll.anchor is non-nil, the scroll auto-scrolls to the anchor position whenever this value changes. Bind to an expression like {{ count(${messages}) }} so the scroll jumps on new content but not on unrelated state changes (e.g. typing in a text field outside the scroll).

ℹ Make the root a scroll when content can exceed one screen. A module renders into a finite host surface (§4.6, §17.1); content past the fold of a non-scrolling root is clipped and unreachable. Reserve non-scrolling roots for layouts designed to fill exactly one screen.

A scrollable list container that applies platform-native list styling. Children are typically one or more dynamic components. Supports navigation titles/subtitles via style.navigation.

Context keyTypeDescription
_isLoading / isLoadingbool / exprWhen true, renders _skeletonRows copies of the first child as shimmer rows.
_skeletonRows / skeletonRowsnumberNumber of skeleton rows shown while loading. Only used when _isLoading is true. Default: 5.

form wraps content in a grouped-list presentation suitable for settings and input screens. section provides logical grouping inside a form or list.

Context keyTypeDescription
_title / titlestring / exprSection header text.

ℹ Note: Row background and inset overrides are configured via style.section (see section 7.18), not as context keys.

spacer expands to fill available space along the parent stack axis. divider renders a platform-native horizontal rule. Neither requires context fields.

Renders nothing (EmptyView). Use as a no-op _falseComponent in a conditional when the false branch should produce no output.

{ "id": "nothing", "type": "empty" }

Displays children in a grid layout. The variant is selected via _gridType:

  • lazyVGrid — vertically scrolling lazy grid; columns are defined in style.grid.
  • lazyHGrid — horizontally scrolling lazy grid; rows are defined in style.grid.
  • grid — non-lazy explicit grid; row structure is defined by gridrow children.
Context keyTypeRequiredDescription
_gridType / gridTypestringOptionallazyVGrid (default) | lazyHGrid | grid.
_spacing / spacingnumberOptionalUniform gap between tracks. Applies to lazyVGrid and lazyHGrid. Default: system default.
_alignment / alignmentstringOptionallazyVGrid: horizontal alignment (leading | center | trailing). lazyHGrid: vertical alignment (top | center | bottom). grid: cell alignment. Default: center.
_horizontalSpacingnumberOptionalColumn gap. Applies to grid variant only.
_verticalSpacingnumberOptionalRow gap. Applies to grid variant only.

Column and row tracks are configured in style.grid (see §7.23). The lazyVGrid and lazyHGrid variants require columns or rows respectively; omitting them falls back to a single flexible track.

{ "id": "photo_grid", "type": "grid",
"context": { "_gridType": "lazyVGrid", "_spacing": 8 },
"style": { "grid": { "columns": [ { "kind": "adaptive", "minimum": 100 } ] } },
"children": [ ... ] }

Defines one explicit row inside a grid component (only valid when the parent grid’s _gridType is "grid").

Context keyTypeRequiredDescription
_alignment / alignmentstringOptionalVertical alignment of cells in this row: top | center | bottom | firstTextBaseline | lastTextBaseline. Default: center.
{ "id": "my_grid", "type": "grid",
"context": { "_gridType": "grid", "_horizontalSpacing": 12, "_verticalSpacing": 8 },
"children": [
{ "id": "row_1", "type": "gridrow", "children": [ ... ] },
{ "id": "row_2", "type": "gridrow", "children": [ ... ] }
] }
Context keyTypeRequiredDescription
_text / textstring / exprREQUIREDThe string to display. Supports state refs (${key}), context refs (@{key}), and expressions.
_format / formatobjectOptionalFormatting descriptor. Single-key object: { “date”: … }, { “number”: … }, or { “duration”: … }. See §4.3.

ℹ Note: l10n:// source strings are valid in _text. Example: “_text”: “l10n://welcome_message” resolves the localization key at runtime.

Context keyTypeRequiredDescription
_source / sourceSource stringREQUIREDImage source. Accepts sf://, asset://, file://, rs://, and http(s):// schemes (see §6.4).
_placeholder / placeholderSource stringOptionalFallback source displayed while the primary source is loading or if it fails. Default: system photo icon.
_contentMode / contentModestringOptionalFill behaviour: fit (default) or fill.
_isLoading / isLoadingbool / exprOptionalShow shimmer skeleton instead of the image. See §15.8.

ℹ Note — image sizing. An image component MUST declare at least one dimension via style.layoutwidth, height, maxWidth, or maxHeight. Without a frame the image has no target size to fill against, and contentMode: "fill" becomes undefined. The runtime clips rendered content to the declared frame: with fill, overflow on the uncontrolled axis is cropped; with fit, the image is letterboxed within the frame. Frame-less images are rendered zero-sized.

Renders a video player backed by the platform’s media framework (AVKit on Apple). A shimmer skeleton is shown while _isLoading is true. Remote sources begin buffering on appear; if _placeholder is set it is shown as a poster until the first video frame is ready, then faded out.

Context keyTypeRequiredDescription
_source / sourceSource stringREQUIREDVideo URL. Supports https://, http://, file://, rs:// schemes.
_placeholder / placeholderSource stringOptionalPoster image shown while the video buffers. Replaced by the first frame once the item is ready. Accepts any scheme the image component accepts (see image._source).
_autoplay / autoplaybool / exprOptionalStart playback on appear. Default: false.
_loop / loopbool / exprOptionalRestart from the beginning when playback ends. Default: false.
_muted / mutedbool / exprOptionalMute the audio track. Default: false.
_isLoading / isLoadingbool / exprOptionalShow shimmer skeleton instead of the player.

Style: style.video (see §7.21).

{ "id": "intro_video", "type": "video",
"context": { "_source": "https://example.com/clip.mp4",
"_placeholder": "https://example.com/clip-poster.jpg",
"_autoplay": true, "_loop": true, "_muted": true },
"style": { "layout": { "height": 220, "maxWidth": "infinity" }, "common": { "cornerRadius": 16 },
"video": { "controls": false, "gravity": "resizeAspectFill" } } }

Renders a PDF document backed by PDFKit. Remote documents are fetched on a background thread; a shimmer skeleton is shown until the document is ready.

Context keyTypeRequiredDescription
_source / sourceSource stringREQUIREDPDF URL. Supports https://, http://, file://, rs:// schemes.
_page / pagenumber / exprOptionalInitial page to display (1-indexed). Default: 1.
_isLoading / isLoadingbool / exprOptionalShow shimmer skeleton instead of the document.

Style: style.pdf (see §7.22).

{ "id": "report_pdf", "type": "pdf",
"context": { "_source": "https://example.com/report.pdf", "_page": 1 },
"style": { "layout": { "height": 300, "maxWidth": "infinity" },
"pdf": { "displayMode": "singlePage", "autoScales": true } } }

Universal media viewer. Inspects the source URL’s file extension (or an explicit _kind hint) and delegates to the appropriate renderer — image, video, or pdf. Use this component when the content type is not known at authoring time or is resolved from state.

Context keyTypeRequiredDescription
_source / sourceSource stringREQUIREDAny media URL.
_kind / kindstringOptionalContent-type hint. One of: auto (default), image, video, pdf. Overrides auto-detect.
_placeholder / placeholderSource stringOptionalPoster shown for images / unknown types on load failure, and for video while the item buffers.
_contentMode / contentModestringOptionalfit (default) or fill — image rendering only.
_autoplay / autoplaybool / exprOptional(video) Start playback on appear. Default: false.
_loop / loopbool / exprOptional(video) Loop when playback ends. Default: false.
_muted / mutedbool / exprOptional(video) Mute audio. Default: false.
_page / pagenumber / exprOptional(pdf) Initial page (1-indexed). Default: 1.
_isLoading / isLoadingbool / exprOptionalShow shimmer skeleton instead of content.

Auto-detection extension map:

ExtensionDetected kind
jpg, jpeg, png, gif, webp, heic, bmp, tiffimage
mp4, mov, m4v, avi, mkv, m3u8video
pdfpdf
sf:// or asset:// source (any extension)image
Unrecognised or absentunknown → placeholder

Style: style.video and style.pdf keys are forwarded to the respective renderer. style.common and style.layout apply to the outer container.

{ "id": "attachment", "type": "media",
"context": { "_source": "${attachmentUrl}", "_kind": "auto", "_placeholder": "sf://doc.fill" },
"style": { "layout": { "height": 240, "maxWidth": "infinity" }, "common": { "cornerRadius": 12 } } }
Context keyTypeRequiredDescription
_title / titlestring / exprREQUIREDLabel text.
_image / imageSource stringOptionalIcon source (typically sf://).
_isLoading / isLoadingbool / exprOptionalShow shimmer skeleton instead of the label. See §15.8.

Renders a platform-native progress indicator. When _value and _total are present, renders as a determinate bar. Omit both for an indeterminate spinner.

Context keyTypeRequiredDescription
_value / valuenumber / exprOptionalCurrent progress value.
_total / totalnumber / exprOptionalMaximum value. When provided alongside _value, renders a determinate bar. Default: 1.0.
_isLoading / isLoadingbool / exprOptionalShow shimmer skeleton instead of the progress indicator. See §15.8.
// Determinate progress bar:
{ "id": "upload_progress", "type": "progress",
"context": { "_value": "${uploadedBytes}", "_total": "${totalBytes}" } }
// Indeterminate spinner:
{ "id": "loading_spinner", "type": "progress" }

Renders a solid color block that fills its layout frame. Use style.layout to set width and height.

Context keyTypeRequiredDescription
_color / colorcolor valueOptionalFill color. Accepts named colors, hex strings, state refs, or expressions. Default: clear.

Renders an interactive map. Map children define custom annotation content rendered at the pin location. Visual presentation (standard / hybrid / imagery) is configured via style.map (see §7.19).

Context keyTypeRequiredDescription
_region / regionobjectConditionalCenter coordinate for the annotation pin. Only relevant when the component has children.
_position / positionobject / exprREQUIREDTwo-way state binding for the camera position. Shape: { "region": { center: {latitude, longitude}, span: {lat, lon} } }.
_name / namestring / exprOptionalAnnotation label shown at the pin. Annotation is suppressed when the component has no children.
_debounce / debouncenumber (sec)OptionalDebounce delay in seconds before region-change events fire.
_isLoading / isLoadingbool / exprOptionalShow shimmer skeleton instead of the map. See §15.8.

The _format context key on a text component transforms the numeric value of _text into a human-readable string using locale-aware formatting. It is a single-key object: the key selects the formatter kind (date, number, or duration).

"_format": { "date": "time" }
"_format": { "number": "currency" }
"_format": { "duration": "abbreviated" }
"_format": { "date": { "style": "custom", "pattern": "dd MMM yyyy" } }
"_format": { "number": { "style": "currency", "currencyCode": "EUR", "maximumFractionDigits": 2 } }
"_format": { "duration": { "style": "positional", "allowedUnits": "ms", "zeroPad": true } }

ℹ Note: _text MUST resolve to a numeric value when _format is present. For date and duration formatters the value is seconds since Unix epoch. Use #{now} for the current time.

⚠ Anti-pattern. A bare-string _format value is silently ignored by the runtime — the raw numeric value renders unformatted (e.g. 1779434773.6742659 instead of "Yesterday"). The wrapper key is mandatory.

  • "_format": "date" — silently ignored
  • "_format": "datetime" — silently ignored
  • "_format": { "style": "date" } — missing formatter-kind key
  • "_format": { "date": { "format": "MMM d" } } — no format key; the field is pattern
  • "_format": { "date": "friendly" } — single-key wrapper, value can be a style string or a dict
  • "_format": { "date": { "style": "custom", "pattern": "MMM d, h:mm a" } }

If _text references a stored timestamp (@{item.ts}, ${entry.ts}) without a valid _format wrapper, treat it as a bug — the user sees the raw Unix epoch double.

Formats a Unix timestamp (seconds) into a locale-aware date or time string.

FieldTypeDefaultDescription
stylestring enum”dateTime”Formatting preset. See style table below.
patternstringICU date pattern. Only used when style is “custom”. E.g. “dd MMM yyyy”.
dateStylestring enumstyle-dependentOverrides the date portion: short
timeStylestring enumstyle-dependentOverrides the time portion: short
localestring#{locale}BCP 47 locale identifier. Defaults to device locale.
styleOutput example
”date”Feb 26, 2026
”time”3:45 PM
”dateTime”Feb 26, 2026 at 3:45 PM
”relative”3 minutes ago
”friendly”Today / Tomorrow / Yesterday — falls back to date otherwise
”iso8601”2026-02-26T15:45:00.000Z
”rfc3339”2026-02-26T15:45:00.000Z (identical to iso8601 output)
“custom”Determined by pattern field
FieldTypeDefaultDescription
stylestring enum”number”Formatting style. See style table below.
currencyCodestringdevice localeISO 4217 code. Only used when style is “currency”.
minimumFractionDigitsintegerstyle-dependentMinimum decimal places shown.
maximumFractionDigitsintegerstyle-dependentMaximum decimal places shown.
usesGroupingSeparatorbooleantrueThousands separator: 1,000 vs 1000.
roundingModestring enum”halfEven”One of: up
signDisplaystring enum”automatic”Controls + on positive values: automatic
styleInputOutput example
”number”1234.51,234.5
”integer”1234.91,235
”percent”0.2323%
“currency”14.99$14.99
”scientific”12345671.235E6
”spellout”42forty-two
”ordinal”11st
”number.compact”15000001.5M
FieldTypeDefaultDescription
stylestring enum”abbreviated”Display style. See style table below.
allowedUnitsstring”hms”Which units to display: d=days, h=hours, m=minutes, s=seconds.
zeroPadbooleantruePositional style only. Pads to two digits: 05:03 vs 5:3.
styleOutput (3 723 sec = 1h 2m 3s)
“positional”01:02:03
”abbreviated”1h 2m
”short”1 hr, 2 min
”full”1 hour, 2 minutes

Renders a text input field. Set _isSecured: true to switch to masked password input (SecureField). Binds its value to a state key via _text.

Context keyTypeRequiredDescription
_label / labelstringREQUIREDPlaceholder / accessibility label text.
_text / textstate refREQUIREDTwo-way binding to a state key. Example: ”${email}”.
_focused / focusedbool / exprOptionalControls input focus.
_debounce / debouncenumber (sec)OptionalDelays onChange events. 0 disables debounce.
_keyboard / keyboardnumberOptionalKeyboard type hint integer.
_isSecured / isSecuredboolOptionalWhen true, renders as a masked password input. Default: false.
_isLoading / isLoadingbool / exprOptionalShow shimmer skeleton instead of the field. See §15.8.

ℹ Keyboard dismissal. Numeric keyboards (decimalPad, numberPad, phonePad) have no Return key. Wrap numeric textfields in a scroll and set style.scroll.dismissesKeyboard (see §7.16) to let the user dismiss by scrolling. Alphanumeric keyboards additionally support the Return key (see style.textField.submitLabel).

Multi-line text input field. Suitable for longer form content, notes, and messages.

Context keyTypeRequiredDescription
_text / textstate refREQUIREDTwo-way binding to a state key.
_placeholder / placeholderstringOptionalPlaceholder text shown when the field is empty.
_focused / focusedbool / exprOptionalControls input focus.
_keyboard / keyboardnumberOptionalKeyboard type hint integer.
_isLoading / isLoadingbool / exprOptionalShow shimmer skeleton instead of the editor. See §15.8.
Context keyTypeRequiredDescription
_label / labelstringREQUIREDToggle label text.
_isOn / isOnstate refREQUIREDTwo-way binding to a boolean state key.
_image / imageSource stringOptionalIcon displayed alongside the label.
_isLoading / isLoadingbool / exprOptionalShow shimmer skeleton. See §15.8.

A value picker. The presentation style is controlled by style.picker (see §7.20). Defaults to the platform-native automatic style when style.picker is absent.

Context keyTypeRequiredDescription
_label / labelstringOptionalPicker accessibility label.
_selection / selectionstate refREQUIREDTwo-way binding to the selected value.
_options / optionsarray / exprREQUIREDArray of selectable values.
_isLoading / isLoadingbool / exprOptionalShow shimmer skeleton instead of the picker. See §15.8.
{ "id": "device_picker", "type": "picker",
"context": {
"_label": "Device",
"_selection": "${pickerSelection}",
"_options": ["MacBook Pro", "Mac Studio", "Mac mini"]
},
"style": { "picker": "menu" } }
Context keyTypeRequiredDescription
_value / valuestate refREQUIREDTwo-way binding to a numeric state key. The slider writes a continuous double in [0, 1].
_isLoading / isLoadingbool / exprOptionalShow shimmer skeleton instead of the slider. See §15.8.

ℹ Slider is a normalised 0..1 input by design. The component does not declare or accept _min / _max / _step — those are author concerns, not runtime concerns. Scale, label, and discretise the raw 0..1 value wherever you consume it. This keeps the slider primitive small and pushes domain semantics to the author per §11.1.

Discrete integer scale (e.g. “1-10 severity”, “1-5 stars”). Prefer a picker with style.picker: "segmented" or "wheel" and explicit string _options — the binding is naturally discrete and the picker label IS the value.

Continuous-feel slider with a scaled integer display. Bind _value to a 0..1 state key; scale and cast at the consumer side (display label, repository write, history row):

"_value": "${rawSeverity}",
"_text": "{{ 'Severity ' + cast(${rawSeverity} * 9 + 1, 'int') + ' / 10' }}"

(Above maps 0..1 → integer in 1..10. Use the formula that matches your scale’s lower bound and step count.)

Inline or modal date/time selection component.

Context keyTypeRequiredDescription
_label / labelstringREQUIREDAccessibility label for the picker.
_date / datestate refREQUIREDTwo-way binding to a state key holding the Unix timestamp (seconds).
_components / componentsstringOptionalCalendar components to display: date (default) | time | hourAndMinute | dateAndTime | datetime. When omitted, only the date calendar is shown.
_min / minnumber / exprOptionalMinimum selectable date as Unix timestamp. Default: distant past.
_max / maxnumber / exprOptionalMaximum selectable date as Unix timestamp. Default: distant future.
_isLoading / isLoadingbool / exprOptionalShow shimmer skeleton instead of the date picker. See §15.8.
{ "id": "birth_picker", "type": "datepicker",
"context": {
"_label": "Date of Birth",
"_date": "${birthDate}",
"_components": "date",
"_max": "#{now}"
},
"style": { "datePicker": { "preset": "wheel" } } }

Buttons support two authoring forms: label form (set _label in context) or custom-content form (omit _label and provide children).

Context keyTypeRequiredDescription
_label / labelstring / exprConditionalButton label text. Required for label form; omit for custom-content buttons.
_image / imageSource stringOptionalIcon displayed alongside the label (label form only).
_isLoading / isLoadingbool / exprOptionalShow shimmer skeleton instead of the button. See §15.8.

ℹ Note: The primary event for button is onTap. Wire your action chain to events.onTap.

Wraps content in a navigable stack. Set the navigation bar title using style.navigation.navigationTitle, or by setting navigationTitle as a public context key on the child component.

A tappable row that pushes a destination module onto the navigation stack. The link’s children define the row’s visual content.

FieldTypeRequiredDescription
destinationmoduleREQUIREDThe component to push. MUST be of type module. Set style.navigation.navigationTitle on it to set the pushed screen title.

ℹ The destination MUST have "type": "module". The runtime always treats the destination as a module regardless of the declared "type". Placing a plain layout component (scroll, vstack, etc.) directly as the destination renders but its events (in particular onAppear) will not fire. Wrap your destination layout in { "type": "module", "state": {…}, "events": {…}, "children": [ <your-layout> ] }.

Scope: context is inherited; state is NOT shared. The destination module inherits the link’s per-item context (e.g. inside a dynamic prototype, @{item} from the outer dynamic is available in the destination module’s events.onAppear actions and in child expressions). State, however, is a fresh scope bound to the destination’s own state block — ${someKey} inside the destination resolves against the destination module’s own state, not the parent module’s. A child module cannot directly read parent state keys. It may indirectly update a parent’s state key only via name-matched upward propagation — i.e. if the child declares a state key of the same name and updates its own key, the parent’s matching-name key is also updated (see §11.3). The child cannot address the parent’s state by name directly.

Threading data into a pushed destination therefore has two patterns:

  1. Pass values through @{item} context (read-only, frozen at push time). Works for primitives or whole arrays — e.g. if each row object already contains the sub-list to show in the detail, _data: "@{item.children}" inside the destination’s dynamic just works.

  2. Let the destination re-fetch via a repo action in its own onAppear, using @{item.<id>} to parameterise the request. This is the pattern the weather example uses.

There is no built-in mechanism to read an outer module’s state keys from a pushed destination. If the detail needs live, two-way-synced data with the parent, restructure the parent’s state so the per-row data is carried inside each row (Pattern 1) or avoid the link/destination split and render the detail inline in the same module via conditional state.

Builds a tab-bar application layout. Each direct child SHOULD be a module. Set the following keys in each child module’s context to configure its tab bar entry.

Child module context keyTypeDescription
_tabTitle / tabTitlestringLabel shown in the tab bar.
_tabImage / tabImageSource stringIcon shown in the tab bar. A bare system-icon name (no scheme prefix) is accepted as shorthand for sf://<name> — see §6.4.
_tabBadge / tabBadgenumber / exprInteger badge count shown on the tab icon. Omit or set to 0 to hide badge.

A two- or three-column iPad layout using NavigationSplitView. On compact-width devices (iPhone, Slide Over) it collapses gracefully to a single-column stack. Children are positional:

  • children[0] — sidebar column (always required)
  • children[1] — detail column (two-column layout), or content column (three-column layout)
  • children[2] — detail column (three-column layout only)

The runtime infers the layout variant from children count. Two children → two-column; three children → three-column.

Context keyTypeRequiredDescription
_columnVisibilitystringOptionalRuntime override for visible columns: "automatic" | "all" | "detailOnly". Default: "automatic".

Style domain: style.splitView (see §7.24).

{ "id": "ipad_root", "type": "splitview",
"style": { "splitView": { "preferred": "balanced", "visibility": "all",
"sidebarWidth": { "min": 200, "ideal": 260, "max": 320 } } },
"children": [
{ "id": "sidebar", "type": "vstack", "children": [ ... ] },
{ "id": "detail", "type": "vstack", "children": [ ... ] }
]
}

A module is the executable boundary for a screen or feature. It owns an isolated state dictionary and a dependency registry.

FieldTypeRequiredDescription
idstringREQUIREDUnique module id.
type”module”REQUIREDMust be the literal string “module”.
stateobjectOptionalInitial state values. MUST be resolved literals — no expressions in initial state values.
dependenciesarrayOptionalDependency declarations (see §5).
contextobjectOptionalModule-level context (title, tab metadata, version, etc.).
childrenarrayOptionalRoot render tree for the module.
eventsobjectOptionalModule-level events (onAppear, onRotate, onCustom, etc.).

ℹ Note: State ownership and propagation. Each module owns its declared state keys exclusively. A state action always applies a local merge gated by the dispatching module’s declarations (unmatched keys are dropped from the local write). It then does one of two things: a chain-less write also propagates upward by name match to any ancestor that has declared a same-named key (the dispatching module does NOT need to declare the key); a write with an output.success chain stays local and the chain runs in the dispatching module’s context to preserve ${...} / @{item} scope — there is no propagation. Parent modules cannot write to child-module state; sibling modules cannot write to each other’s state; and no module can read another module’s state — state reads are strictly scoped to the module that declares the key.

ℹ Note — Render surface & overflow. A module’s root render tree is laid out into a host-provided surface of finite size — the area the host allocates for the module, below its own chrome (back button, title bar, tabs). The surface is a hard boundary: a conforming runtime MUST contain the module within it (§17.1), so an oversized root is clipped to the surface and can never overdraw host chrome or intercept touches outside it. Because clipping cuts content rather than revealing it, author the root to fit the surface: when a screen’s content can exceed the viewport — long forms, dynamic lists, anything that grows with state — make the root, or the region that overflows, a scroll (§4.1). A non-scrolling root (e.g. a vstack with spacers) is only for layouts meant to fill exactly one screen; size their primary content responsively (maxWidth / maxHeight: "infinity", ratios) rather than fixed width / height in points, so they still fit smaller viewports and larger Dynamic Type.

A non-visual proxy that renders a component pulled from the dependency registry by its source. A template instance MAY supply additional context keys that override or parameterize the referenced component.

Context keyTypeRequiredDescription
_source / sourceSource stringREQUIREDLocation of the component. Use dp://id for registered dependencies, or file://path for a packaged JSON component file.
_inline / inlinebooleanOptionalWhen true, the component is immediately initialized. Default: true.

Renders a prototype component repeatedly for each element in an array data source. Injects item (the current element) and index (zero-based position) into the prototype’s context.

FieldTypeRequiredDescription
context._data / context.dataarray / exprREQUIREDArray value or state ref. Example: ”${items}“.
prototypecomponentREQUIREDComponent rendered once per item. Access item data with @{item.field} and @{index}.
context._isLoading / isLoadingbool / exprOptionalWhen true, renders _skeletonRows copies of the prototype with "isLoading": true injected, so each primitive inside shows its own skeleton.
context._skeletonRowsnumberOptionalNumber of prototype skeleton rows to show while loading. Only used when _isLoading is true. Default: 5.

Renders one of two component branches based on a boolean condition. The un-rendered branch is not instantiated.

Context keyTypeRequiredDescription
_condition / conditionbool / exprREQUIREDBoolean or expression selecting the branch.
_trueComponent / trueComponentcomponentREQUIREDRendered when condition is truthy.
_falseComponent / falseComponentcomponentOptionalRendered when condition is falsy. If omitted, nothing is rendered. Use { "type": "empty" } for an explicit no-op branch. Omitting this field produces a validation warning.

A speech-bubble shape component. Controls which side the tail appears on.

Context keyTypeDescription
_outgoing / outgoingbool / exprWhen true the bubble tail points right (outgoing). When false, tail points left (incoming).
Context keyTypeDescription
_points / pointsintegerNumber of star points. Default: 5.