Skip to content

UI components ​

Implementation status: runtime discovery is authoritative. The current Host implements the ordinary stacks/grids/forms/lists/controls plus EmptyView, If, GeometryReader, Canvas, ForEach, SearchField, Searchable, ReorderList, SwipeActions, ContextMenu, ContentUnavailableView, MediaImage, NavigationTitle, Toolbar, Map, WebView, VideoPlayer, AudioPlayer, CameraPreview, BarcodeScanner, and ARView.

Input components use an explicit props.bind path such as state.profile.name, state.enabled, or global.search.query for two-way updates. Nested state and global paths are executable v1 behavior. A change event may invoke an action after the bound value changes.

ForEach uses props.items as a normal Apsule interpolation that points to a state array (for example the state.items expression), props.item as the iteration alias (default item), and props.key as the stable object key (default id). Descendants may interpolate fields from that alias, such as the item.content expression. Tap actions inside repeated content receive the iteration scope object as their first JavaScript argument so an action can identify the selected item without copying IDs into static JSON.

TextEditor is the multiline counterpart to TextField. It uses the same props.bind state binding and accepts props.minHeight for its minimum editor height.

TextField, SecureField, TextEditor, and SearchField accept native input hints such as keyboardType, autocapitalization, autocorrection, and submitLabel. Sheet accepts detents (medium, large, fraction:<0-1>, height:<points>), dragIndicator, and interactiveDismissDisabled.

Picker uses props.options as an array of { "label": "...", "value": "..." } objects and binds a string value. DatePicker binds an ISO-8601 string (and accepts an existing numeric Unix timestamp); props.dateOnly: true limits it to a date. ColorPicker binds a #RRGGBB or #RRGGBBAA string. Sheet, Alert, ConfirmationDialog, and DisclosureGroup use a boolean props.bind. Alert may invoke an optional confirm event. NavigationLink uses props.route to load a project route while retaining the same runtime/state.

LazyVGrid uses props.columns; LazyHGrid uses props.rows; both accept props.spacing and props.itemSpacing. TabView binds a string selection and reads tabTitle, tabSystemName, and optional tabValue from each direct child; props.hideTabBar: true keeps native tab selection while hiding the tab bar for app-controlled or immersive switching. ConfirmationDialog renders direct Button children as native actions and honors props.role values destructive and cancel. ShareLink accepts either props.url or string props.value.

Shape components accept props.color, props.width, and props.height. Optional props.widthBinding / props.heightBinding may resolve a numeric value from normal state interpolation; when present they override the static width/height while leaving the static value as a backward-compatible fallback for older Hosts. RoundedRectangle also accepts props.cornerRadius. Image/MediaImage may resolve either packaged assets or Project-sandbox media paths. Map accepts an initial region plus marker/polyline collections and emits regionChange/mapTap. WebView accepts props.url, emits navigate/error/message, and is controllable through host.webView. VideoPlayer and AudioPlayer resolve Project-sandbox or HTTP media URLs. CameraPreview is a native preview surface; capture remains imperative through host.camera.

The v1 goal is not to mirror every SwiftUI API. It is to cover the building blocks needed for a wide range of normal small apps while retaining native appearance.

The percentages of SwiftUI covered should not be treated as a meaningful metric: SwiftUI includes a very large API surface spanning layout, scenes, graphics, accessibility, gestures, framework integrations and platform-specific features. Apsule instead targets broad app-type coverage.

Layout ​

TypePurpose
VStackArrange children vertically.
HStackArrange children horizontally.
ZStackLayer children on top of one another.
SpacerFlexible empty space; useful for alignment.
DividerNative visual separator.
ScrollViewScroll content vertically/horizontally.
LazyVStackEfficient large vertical stack.
LazyHStackEfficient large horizontal stack.
LazyVGridEfficient grid flowing vertically.
LazyHGridEfficient grid flowing horizontally.
GeometryReaderReact to available geometry/size when necessary. Use sparingly.
CanvasDraw line/rectangle/ellipse/text/polyline command arrays and receive drag coordinates.
IfRender the first child when props.condition is truthy and the optional second child otherwise.

Text and labels ​

TypePurpose
TextRender text.
LabelNative icon + text pairing.

Inputs and controls ​

TypePurpose
ButtonTrigger an action.
TextFieldPlain text input.
TextEditorMultiline text input.
SecureFieldObscured sensitive input.
SearchFieldCompact search-style text input.
SearchableApply native search UI to its child content.
ToggleBoolean on/off input.
SliderNumeric range input.
PickerSelect from choices.
DatePickerDate/time input.
ColorPickerColor input.
MenuCompact menu of actions/options.

Data/content ​

TypePurpose
ImageLocal/system image.
AsyncImageRemote image loaded from a URL.
ProgressViewLoading indicator or progress.
GaugeNative gauge/measurement visualization.
ListNative structured list.
ReorderListNative editable list backed by a bound state/global array.
ForEachRepeat UI for collection items.
SectionGroup related rows/content.
FormNative form/settings-like structure.
DisclosureGroupExpand/collapse content.
SwipeActionsWrap content with native leading/trailing swipe actions.
ContextMenuWrap content with a native context menu.
MediaImageDisplay an image from Project assets or the Project sandbox.
VideoPlayerNative AVPlayer-backed video playback.
AudioPlayerCompact AVPlayer-backed audio playback.
ContentUnavailableViewNative empty/error-state presentation.
TypePurpose
NavigationStackNative navigation container. Routes remain defined at project level.
NavigationLinkDeclarative route trigger where useful.
NavigationTitleSet a route-local native navigation title.
ToolbarAdd project-controlled native toolbar items.
TabViewMain tab-based application navigation.
SheetPresent a modal sheet.
AlertNative alert.
ConfirmationDialogNative action/confirmation dialog.
LinkOpen a URL.
ShareLinkNative share entry point.

Shapes and graphics ​

TypePurpose
RectangleRectangle shape.
RoundedRectangleRounded rectangle shape.
CircleCircle shape.
CapsuleCapsule/pill shape.

Native framework-backed UI ​

TypePurpose
MapNative map UI backed by MapKit.
WebViewWeb content surface backed by WebKit; this is an explicit component, not the renderer for the rest of Apsule.
CameraPreviewLive native camera preview when Camera permission is granted.
BarcodeScannerLive QR/barcode scanner backed by AVCaptureMetadataOutput; emits a scan event with payload/symbology.
ARViewBasic RealityKit/ARKit world-tracking surface with optional plane detection.

Liquid Glass ​

Liquid Glass should primarily be expressed through styles/modifiers rather than proliferating special component types. For example, a normal Button may opt into supported glass styling.

The Host maps supported glass properties to the native SwiftUI APIs available in the Host SDK/OS. Unsupported effects must be reported through runtime validation rather than silently approximated with web/CSS effects.

Remaining UI candidates ​

Charts, a rich-text editor, advanced custom layout protocols, accessibility-specialized components and domain-specific Health/Home UI are not separate v1 components. Their underlying data/OS integrations can still be used from Project JavaScript where a generic UI surface is sufficient.