Layout & Presentation
Control layout structure and how flows appear on screen.
Layout & Presentation
Layout components control how child components are arranged within a screen, and presentation styles determine how the entire screen appears on the user's device. Together, they give you full control over the structure and appearance of every in-app experience.
Container
The Container is the fundamental layout component. It groups child components together and arranges them using flexbox properties. Every screen has an implicit root container, and you can nest additional containers to create complex layouts.
Properties
| Property | Type | Default | Description |
|---|---|---|---|
| Edge-to-Edge | boolean | false | Stored as ignoresSafeArea. Lets the container extend under the notch and home indicator. |
| Display | select | flex | flex or block. |
| Direction | select | column | Stored as flexDirection: row (Horizontal), column (Vertical), row-reverse, column-reverse. |
| Justify Content | select | flex-start | Main-axis: flex-start, center, flex-end, space-between, space-around, space-evenly. |
| Align Items | select | stretch | Cross-axis: flex-start, center, flex-end, stretch, baseline. |
| Wrap | select | nowrap | Stored as flexWrap: nowrap, wrap, or wrap-reverse. |
| Gap | number | 16 | Spacing between child components in pixels. |
| Width | size | 100% | Pixel value, percentage, or auto. |
| Height | size | auto | Pixel value, percentage, or auto. |
| Min Height | size | -- | Lower bound on height. |
| Max Height | size | -- | Upper bound on height. |
| Padding | spacing | 16 | Internal spacing (top, right, bottom, left). |
| Margin | spacing | 0 | External spacing. |
| Overflow | select | visible | visible, hidden, scroll, or auto. |
| Background Color | color | -- | Container fill color. |
| Background Image | image | -- | Image drawn behind the container's children. |
| Background Size | select | cover | cover, contain, or auto. |
| Background Position | select | center | center, top, bottom, left, or right. |
| Border Radius | number | 0 | Corner rounding. |
| Border | border | -- | Width, style, and color as one composite control. |
| Shadow | shadow | -- | Offset, blur, spread, and color. |
| Opacity | number | 100 | Container opacity, 0 to 100. |
| On Click | action | -- | Makes the whole container tappable. |
| Animation | animation | none | Entrance animation preset, duration, delay, easing, and trigger. |
Border is a single composite property holding width, style, and color together. There are no separate Border Width or Border Color properties.
Common layout patterns
Header with pinned footer:
Use a column container for the full screen. Place content at the top, add a spacer with fillSpace enabled, then place buttons at the bottom. The spacer expands to push the buttons to the bottom edge.
Horizontal button row:
Set Direction to row and wrap two or more buttons in the container with gap spacing. Set each button to equal width for a balanced layout, or let them size to their content.
Centered content block:
Set a container's Justify Content to center and Align Items to center to perfectly center its children both vertically and horizontally.
Stack
The Stack component is a simplified container optimized for common stacking patterns. It arranges children in a single direction with consistent spacing.
Properties
| Property | Type | Default | Description |
|---|---|---|---|
| Direction | select | vertical | vertical or horizontal. |
| Spacing | number | 16 | Stored as spacing. Gap between children in pixels. |
| Alignment | select | stretch | Stored as align. Cross-axis: start, center, end, stretch. |
| Distribution | select | start | Main-axis: start, center, end, between, around, evenly. |
| Padding | spacing | 0 | Internal spacing. |
| Margin | spacing | 0 | External spacing. |
| Animation | animation | none | Entrance animation preset, duration, delay, easing, and trigger. |
Stack is a convenience wrapper around Container with fewer configuration options, making it faster to set up for simple vertical or horizontal layouts. It has no Width property: a Stack sizes to its parent and its content. Reach for Container when you need explicit sizing, a background, a border, or wrapping.
Container and Stack express direction with different vocabularies. Container uses flexDirection with row /
column (plus the two reversed values); Stack uses direction with horizontal / vertical. Container's column
is Stack's vertical. Container's row is Stack's horizontal. The same difference applies to spacing: Container
calls it gap, Stack calls it spacing.
Accordion
A collapsible section with a header and hidden content. Tapping the header expands or collapses the body. Use it to keep a screen short while still making detail available.
Properties
| Property | Type | Default | Description |
|---|---|---|---|
| Title | text | sample | Header text, always visible. |
| Subtitle | text | -- | Secondary line under the title. |
| Background Color | color | #F9FAFB | Fill of the expanded body. |
| Header Background | color | -- | Fill of the header row. Falls back to the background when unset. |
| Border Radius | borderRadius | 8 | Corner rounding. |
| Border | border | 1px solid | Width, style, and color as one composite control. |
| Icon Position | select | right | Which side the expand indicator sits on: left or right. |
| Default Open | boolean | false | Whether the accordion starts expanded. |
| Margin | spacing | bottom 8 | External spacing. |
| Animation | animation | none | Entrance animation preset, duration, delay, easing, and trigger. |
Use cases
- FAQ blocks on a paywall, where most users only open one question
- Terms and fine print that must be present but should not dominate the screen
- Optional detail under a plan or feature summary
List
Repeats one component once per row of data from a Data Source. Build a single card, point the list at an array from your API, and it renders one card per item.
A list holds exactly one child, which acts as the row template. Inside it, {{item.field}} refers to the current row and {{item.$index}} to its position, starting at 0.
List Items: {{data.workout_plans.results}}
Card
Text {{item.name}}
Text {{item.price}}
Image {{item.image_url}}Properties
| Property | Type | Default | Description |
|---|---|---|---|
| Items | text | -- | Binding to an array from a data source bound on this screen. |
| Max Rows | number | 20 | How many rows to render, capped at 50. |
| Empty Text | text | No results found | Shown when the response has no rows. Localizable. |
| Direction | select | column | Whether rows stack vertically or run horizontally. |
| Gap | number | 8 | Space between rows. |
| Padding | spacing | 0 | Internal spacing. |
| Animation | animation | none | Entrance animation preset, duration, delay, easing, and trigger. |
A list needs a screen whose layout is Scrollable. On a Fit Screen layout the rows are squashed into whatever height is left over, and publishing is blocked until you change it.
How it renders
The repetition happens on Setgreet's servers, not on the device: the row template is cloned per row and sent as an ordinary container. That is why lists work on SDK versions released long before Data Sources existed, and why there is no list renderer to update in your app.
In the editor the canvas previews up to three rows using the sample captured the last time you tested the source, so you can build the card before any live data exists.
Use cases
- A product list filtered by answers the user gave earlier in the flow
- Plan or tier options priced from your own billing system
- A shortlist of items pulled from a search endpoint
Screen Layout
Screen layout controls how the root container of a screen relates to the viewport. It is a per-screen setting, not a component property.
| Value | Behavior |
|---|---|
fitScreen | Default. The root container fills the viewport height, so a spacer with Fill Space expands into the leftover space. The button block at the bottom stays pinned; content taller than the viewport scrolls above it. |
scrollable | The whole screen scrolls, buttons included. There is no leftover space, so spacers with Fill Space collapse. |
Keep fitScreen for screens that should present as a single frame with a CTA anchored at the bottom. On this layout the trailing button block (everything after the last spacer with Fill Space that is followed by a button, or else the last run of buttons) is pinned to the bottom of the screen, and anything above it scrolls when it does not fit. This applies in every presentation style, inside a bottom sheet and a popup as well. Switch to scrollable for document-style screens where the buttons should scroll with the content, such as dense fine print or a long stack of reviews.
Changing a screen to scrollable changes how existing spacers behave. Any spacer relying on Fill Space to push a
button to the bottom will collapse to its fixed height instead. Replace those spacers with explicit heights when you
switch a screen to scrollable.
Presentation Styles
Presentation style determines how a screen is displayed on the user's device. Each screen in a flow can have its own presentation style.
Fullscreen
The default presentation style. The screen takes over the entire device display, covering your app's UI completely. Fullscreen is appropriate for:
- Onboarding flows that require full attention
- Feature announcements with rich media
- Surveys and feedback forms
- Permission request pre-explanations
Bottom Sheet
The screen slides up from the bottom of the device as a sheet overlay. The previous fullscreen screen of the flow remains visible behind the sheet, dimmed by a configurable overlay; when the sheet is the first screen, your app's content shows through instead. Bottom sheets are appropriate for:
- Quick prompts that do not need full-screen real estate
- Contextual actions related to what the user was doing
- Non-blocking announcements
- Lightweight surveys (NPS, thumbs up/down)
Bottom sheet configuration
| Property | Key | Default | Description |
|---|---|---|---|
| Initial Height | initialHeight | medium | How tall the sheet appears: small (30%), medium (50%), large (75%), full (95%). |
| Corner Radius Top Left | cornerRadiusTopLeft | 0 | Rounding of the top-left corner. |
| Corner Radius Top Right | cornerRadiusTopRight | 0 | Rounding of the top-right corner. |
| Show Handle | showHandle | true | Display a drag indicator at the top of the sheet. |
| Handle Color | handleColor | #9CA3AF | Color of the drag indicator. |
| Handle Width | handleWidth | 32 | Width of the drag indicator in pixels. |
| Handle Height | handleHeight | 4 | Height of the drag indicator in pixels. |
| Background Color | backgroundColor | #FFFFFF | Sheet background fill. |
| Show Overlay | showBackgroundOverlay | true | Dim the content behind the sheet. |
| Overlay Color | overlayColor | #000000 | Scrim color. |
| Overlay Opacity | overlayOpacity | 0.32 | Scrim transparency, 0 to 1. |
| Draggable | isDraggable | true | Allow the user to drag the sheet up and down. |
| Dismiss on Overlay Tap | isDismissibleOnOverlayTap | true | Close the sheet when the user taps outside it. |
| Dismiss on Swipe Down | isDismissibleOnSwipeDown | true | Close the sheet when the user swipes it down. |
| Animation Duration | animationDuration | 300 | Duration of the slide-up and slide-down animation in milliseconds. |
| Content Scrollable | isContentScrollable | true | Whether the sheet's content scrolls when it exceeds the sheet height. |
| Show Scrollbar | showScrollbar | true | Whether a scrollbar is drawn for scrollable content. |
Corner radius is set per corner: cornerRadiusTopLeft and cornerRadiusTopRight are two separate values. Set both to
the same number for an evenly rounded sheet.
Bottom sheet configuration is per-screen. You can mix presentation styles within a single flow. For example, start with a fullscreen onboarding screen, then show a bottom sheet survey at the end. The survey is drawn over that onboarding screen, not over your app.
Popup
The screen appears as a centered card over a dimmed overlay. The card is a fixed share of the device width and only as tall as its content, up to a cap, after which the content scrolls above the pinned button block. Popups are appropriate for:
- Permission primers and other short prompts
- Confirmations and small decisions
- Announcements that should keep the user's context visible
Like a bottom sheet, a popup in the middle of a flow sits over the previous fullscreen screen of the flow; only a popup that opens the flow sits directly over your app. Tapping the overlay, when allowed, closes the whole flow.
Popup configuration
| Property | Key | Default | Description |
|---|---|---|---|
| Width | width | medium | Card width: small (70%), medium (85%), or large (95%) of the device width. |
| Max Height | maxHeightFraction | 0.7 | The tallest the card may grow, as a fraction of the screen height below the status bar and above the home indicator. |
| Corner Radius | cornerRadius | 20 | Rounding of all four corners. |
| Background Color | backgroundColor | #FFFFFF | Card background fill. |
| Show Overlay | showBackgroundOverlay | true | Dim the content behind the card. |
| Overlay Color | overlayColor | #000000 | Scrim color. |
| Overlay Opacity | overlayOpacity | 0.32 | Scrim transparency, 0 to 1. |
| Dismiss on Overlay Tap | isDismissibleOnOverlayTap | true | Close the flow when the user taps outside the card. |
| Animation Duration | animationDuration | 300 | Duration of the appear and disappear animation in milliseconds. |