ComponentNode with an id, a type, and an untyped props bag. This page lists each kind and the props the renderers read.
Props are stored as Record<string, any>. The names below are the keys the SDK renderers read (ComponentProps in both the iOS and Expo SDKs) plus the intended shapes documented in the schema. A prop can be a plain value or a dynamic (conditional) value; string props also support {{variable}} interpolation.
Universal props
These apply to every visible component (a few do not apply toscreenRoot or custom, noted in those sections).
Layout, styling, and animation props are covered in depth under Properties, Layout and sizing, and Animations. The sections below list the props that are specific to each kind.
screenRoot
The implicit root container of a screen, rendered as the “Root Stack”. Treated as a stack; it exposes stack layout props (axis, spacing, align, justify) and spacing only. It is not added from the palette.
stack
A flex container. The primary layout primitive. Children render along an axis.
Supports the
onAppear and onPress interactions.
Auto-scroll (Carousel marquee)
SetautoScroll on a horizontal stack and its children drift in a seamless,
endless loop instead of being swiped — the motion behind the Carousel block’s
Scroll automatically toggle. The children are repeated as many times as it
takes to fill the screen, so the row never trails a gap, even with two slides.
Auto-scroll is display-only. It replaces manual scrolling — the row ignores
touch on every platform, because a drifting card is not something a user can
reliably tap. Put anything interactive outside the carousel.Keep
scrollBehavior: "scroll" set alongside it. An older SDK that predates
autoScroll ignores it and renders a plain swipeable carousel, rather than a
motionless clipped row.text
A text label.
Countdown
Settingcountdown makes a text node render its own clock instead of
props.text. It is not a separate component kind — the same idea as
autoProgress on progress — so it styles like any other label and needs no
special SDK setup.
A countdown never survives a session. The deadline is held in memory for as
long as the flow is presented and is never written to disk, so relaunching the
app always starts from the full duration. Use it for urgency, not for
entitlement — anything a user could gain by force-quitting belongs on your
server.
Wiring it up. A countdown does not expose a ticking variable (a value
changing every second would re-render everything bound to it). It emits ordinary
actions instead, which is how you react to it:
setVariableflips a flag; any property elsewhere can then be a conditional value that reads it (swap a price, hide a card, disable a button).trackEventrecords it in analytics with no app-side code.customcalls into your app — see custom actions.goNext,navigate,closeFlow,hapticand the rest all work too.
onComplete fires on the
first tick back; of any milestones crossed while away, only the last one fires
(so you don’t get a burst of stale nudges on resume).
Several labels, one clock. Give multiple text nodes the same timerId and
they share a single deadline, each rendering the unit its format asks for.
That is how the boxed 03 : 12 : 45 layout is built — three cells, formats
hh / mm / ss — with no extra components. The first node to register stamps
the clock and owns its actions, so declare the emit hooks on one of them.
image
A remote or bundled image.
button
A tappable container. Shares the stack style surface, so it accepts the stack layout and box props plus the text props below.
The main interaction is
onPress. A Back Button is a button with a goBack action; a Close Button is a button with a closeFlow action.
input
A text field. Reads and writes a bound variable.
Interactions:
onChange, onFocus, onBlur (binding to the variable is implicit via variableKey).
Focus behavior
In the editor these are the Focus on open and Keep keyboard open toggles on an input, in both Simple and Advanced mode.autoFocus opens the screen with the field focused and the keyboard up. If more
than one input on a screen sets it, the first in tree order wins and the rest
are ignored.
focusLock additionally suppresses every way the user could dismiss the keyboard
— tapping outside, swiping the content, and the return key — until the flow
navigates to another screen. Use it for a screen where typing is the screen.
The lock is best-effort, and how it holds differs by path. Tapping outside
and swiping to dismiss are refused outright, so nothing blinks. The return key is
refused outright on Expo, but on iOS it blinks (SwiftUI gives no way to stop a
field resigning on submit, so the SDK re-focuses instead). The same blink applies
wherever the OS owns the dismissal and hides the keyboard regardless: iPad’s
hide-keyboard key, an attached hardware keyboard, and Android’s back button.Both props are honored for inputs in the screen layout only — an input placed
in a persistent zone ignores them, the same boundary required gating draws.
toggle
A switch bound to a boolean variable.
Interaction:
onChange.
There is no
checkbox component kind. A checkbox is composed as a Block (a tappable stack with an icon whose glyph swaps via a conditional value). Old checkbox nodes are migrated into that shape on load.progress
A linear progress bar.
progress is not in the component palette; it is added via the Progress Bar block or in a zone.
ringProgress
A circular progress ring. A separate primitive from progress.
icon
A vector icon (Lucide).
slider
A numeric range control with a draggable thumb. Binds like input: it reads its variable on appear and writes the value live on every drag.
The styling props (
trackHeight, fillColorEnd, thumbStyle, thumbSize, valueLabelPosition, valueLabelSize, valueLabelColor) are optional and additive; their defaults preserve the original look.
Interaction: onChange. Curated presets (Hours, Percentage, Rating, Amount) live in the “Sliders” subgroup of the “Pickers” category of the block library; each is the same slider pre-styled with a gradient fill, a pill thumb, and a large top readout, bound to an auto-managed number variable.
lottie
A Lottie animation.
comparisonChart
A “you with us vs you without us” comparison curve.
picker
A scroll-snapping value wheel (the iOS UIPickerView look). One primitive that holds one or more columns, so it covers the standalone number/age wheel (1 column), the side-by-side height/weight picker (2-3 columns), and the date-of-birth picker (mode: "date"). Each column binds like slider/input: it reads its variable on appear and writes the selected value back on every detent.
Imperial / Metric unit toggle
SetunitToggle to put an Imperial/Metric control above the wheel — a segmented pill or, via toggleStyle: "switch", a label on each side of an iOS toggle. Each “system” carries its own columns; toggling converts the value (150 lb → 68 kg) and the picker always writes a canonical normalized variable (kg / cm) regardless of the chosen system, so your logic stays unit-agnostic.
Conversion uses a built-in units table — mass (base kg):
kg g lb st; length (base cm): cm m mm in ft — keyed off each column’s unit. Toggling preserves the value per dimension and redistributes it into the new system’s columns (the ft+in split included). A unit not in the table means no conversion for that dimension (pure column swap).
Interaction: onChange. Curated presets (Age, Height, Weight, Height & Weight, Date of birth) live in the “Pickers” category of the block library; Weight, Height, and Height & Weight ship with the unit toggle on by default.
ruler
A tick-mark measuring scale that drags under a fixed center indicator (the inverse of slider’s drag-the-thumb). It picks a single continuous numeric value, snapped to step, and shows a big live readout — the “What is your height? / weight?” onboarding scale. Binds like slider: it reads its variable on appear and writes the snapped value back on every detent.
Imperial / Metric unit toggle
SetunitToggle to add an Imperial/Metric control below the scale — a "switch" (default for rulers) or a "segmented" pill. Each “system” carries exactly one track (a ruler is a single continuous scale, not multiple columns). Toggling converts the value and the ruler always writes a canonical normalized variable (kg / cm) regardless of the chosen system, so your logic stays unit-agnostic.
Conversion uses the same built-in units table as
picker — mass (base kg): kg g lb st; length (base cm): cm m mm in ft — keyed off the track’s unit. Because a ruler is a single value, conversion is a single scalar (no ft+in column split); a length track can set valueFormat: "feetInches" to display its inches scale as 6'1".
Interaction: onChange. Curated presets (Weight, Height, Value) live in the “Scales” subgroup of the “Pickers” category; Weight and Height ship with the unit toggle on by default.
custom
An app-scoped custom component placed by reference. Custom components render as placeholder shells in the editor and resolve to your registered native view on iOS. They have limited layout props (no background, border, shadow, padding, typography, position, z-index).
Instance props (CustomComponentInstanceProps):
Custom components emit outputs (events) that you wire to actions in the editor. The native side and the editor agree on a key + version + input keys + output keys contract. See Custom components.
Notes
- Components removed from the schema (
spacer,divider,card,chip,carousel,video,checkbox, and the old placeholderchart) are rewritten or stripped by migrations on load. See Schema versions. - Any prop the renderers do not read is ignored, not an error.