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, andARView.
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
| Type | Purpose |
|---|---|
VStack | Arrange children vertically. |
HStack | Arrange children horizontally. |
ZStack | Layer children on top of one another. |
Spacer | Flexible empty space; useful for alignment. |
Divider | Native visual separator. |
ScrollView | Scroll content vertically/horizontally. |
LazyVStack | Efficient large vertical stack. |
LazyHStack | Efficient large horizontal stack. |
LazyVGrid | Efficient grid flowing vertically. |
LazyHGrid | Efficient grid flowing horizontally. |
GeometryReader | React to available geometry/size when necessary. Use sparingly. |
Canvas | Draw line/rectangle/ellipse/text/polyline command arrays and receive drag coordinates. |
If | Render the first child when props.condition is truthy and the optional second child otherwise. |
Text and labels
| Type | Purpose |
|---|---|
Text | Render text. |
Label | Native icon + text pairing. |
Inputs and controls
| Type | Purpose |
|---|---|
Button | Trigger an action. |
TextField | Plain text input. |
TextEditor | Multiline text input. |
SecureField | Obscured sensitive input. |
SearchField | Compact search-style text input. |
Searchable | Apply native search UI to its child content. |
Toggle | Boolean on/off input. |
Slider | Numeric range input. |
Picker | Select from choices. |
DatePicker | Date/time input. |
ColorPicker | Color input. |
Menu | Compact menu of actions/options. |
Data/content
| Type | Purpose |
|---|---|
Image | Local/system image. |
AsyncImage | Remote image loaded from a URL. |
ProgressView | Loading indicator or progress. |
Gauge | Native gauge/measurement visualization. |
List | Native structured list. |
ReorderList | Native editable list backed by a bound state/global array. |
ForEach | Repeat UI for collection items. |
Section | Group related rows/content. |
Form | Native form/settings-like structure. |
DisclosureGroup | Expand/collapse content. |
SwipeActions | Wrap content with native leading/trailing swipe actions. |
ContextMenu | Wrap content with a native context menu. |
MediaImage | Display an image from Project assets or the Project sandbox. |
VideoPlayer | Native AVPlayer-backed video playback. |
AudioPlayer | Compact AVPlayer-backed audio playback. |
ContentUnavailableView | Native empty/error-state presentation. |
Navigation and presentation
| Type | Purpose |
|---|---|
NavigationStack | Native navigation container. Routes remain defined at project level. |
NavigationLink | Declarative route trigger where useful. |
NavigationTitle | Set a route-local native navigation title. |
Toolbar | Add project-controlled native toolbar items. |
TabView | Main tab-based application navigation. |
Sheet | Present a modal sheet. |
Alert | Native alert. |
ConfirmationDialog | Native action/confirmation dialog. |
Link | Open a URL. |
ShareLink | Native share entry point. |
Shapes and graphics
| Type | Purpose |
|---|---|
Rectangle | Rectangle shape. |
RoundedRectangle | Rounded rectangle shape. |
Circle | Circle shape. |
Capsule | Capsule/pill shape. |
Native framework-backed UI
| Type | Purpose |
|---|---|
Map | Native map UI backed by MapKit. |
WebView | Web content surface backed by WebKit; this is an explicit component, not the renderer for the rest of Apsule. |
CameraPreview | Live native camera preview when Camera permission is granted. |
BarcodeScanner | Live QR/barcode scanner backed by AVCaptureMetadataOutput; emits a scan event with payload/symbology. |
ARView | Basic 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.