Skip to content

Commit 37a99cb

Browse files
committed
Update skip-fuse-ui docs
1 parent c66ae41 commit 37a99cb

1 file changed

Lines changed: 135 additions & 1 deletion

File tree

  • src/content/docs/docs/modules/skip-fuse-ui

src/content/docs/docs/modules/skip-fuse-ui/index.md

Lines changed: 135 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,139 @@ This framework is available at [github.com/skiptools/skip-fuse-ui](https://githu
1010
:::
1111

1212

13-
Bridging between SwiftUI and Jetpack Compose for [Skip Fuse](/docs/modes/) apps. SkipFuseUI uses [SkipUI](/docs/modules/skip-ui/) under the hood to adapt the SwiftUI APIs to Compose. See its documentation for information about SwiftUI-on-Android.
13+
SkipFuseUI provides the SwiftUI API surface for [Skip Fuse](/docs/modes/#fuse) apps on Android. It acts as a thin Swift bridging layer that delegates rendering to [SkipUI](/docs/modules/skip-ui/), which implements SwiftUI views as Jetpack Compose composables. On iOS, `import SwiftUI` resolves to Apple's framework as usual; on Android, it resolves to SkipFuseUI, giving you a single SwiftUI codebase that runs natively on both platforms.
14+
15+
## How It Works
16+
17+
SkipFuseUI sits between your SwiftUI code and SkipUI's Compose implementation. Your Swift views are compiled natively for Android by the Swift Android SDK, and at render time each view produces a Kotlin-side SkipUI counterpart that Compose renders on screen.
18+
19+
```mermaid
20+
flowchart LR
21+
A["Your SwiftUI Code"] --> B["SkipFuseUI\n(Swift on Android)"]
22+
B -->|"Java_view"| C["SkipUI\n(Kotlin/Compose)"]
23+
C --> D["Jetpack Compose\nUI on Screen"]
24+
25+
style A fill:#f5f5f5,stroke:#333,color:#fff
26+
style B fill:#f0e6ff,stroke:#7b2fbe,color:#fff
27+
style C fill:#e6f0ff,stroke:#4a90d9,color:#fff
28+
style D fill:#e6ffe6,stroke:#2d8a2d,color:#fff
29+
```
30+
31+
The key mechanism is the `SkipUIBridging` protocol. Every SkipFuseUI view type conforms to it by exposing a `Java_view` property that returns the equivalent SkipUI Kotlin object. When Compose needs to render your view hierarchy, it walks the tree of `Java_view` references — each one backed by [SkipBridge](/docs/modules/skip-bridge/) JNI calls between Swift and Kotlin.
32+
33+
### Module Relationships
34+
35+
```mermaid
36+
flowchart TB
37+
subgraph "Your App"
38+
APP["App SwiftUI Code"]
39+
end
40+
41+
subgraph "SkipFuseUI Package"
42+
SFUI["SkipFuseUI\n(re-exports SwiftUI\non Android)"]
43+
SSU["SkipSwiftUI\n(Swift view types,\nproperty wrappers,\nmodifiers)"]
44+
end
45+
46+
subgraph "Bridging Infrastructure"
47+
SB["SkipBridge\n(JNI object lifecycle,\ntype conversion)"]
48+
SF["SkipFuse\n(@Observable,\nOSLog, bridging\nsupport)"]
49+
SAB["SkipAndroidBridge\n(Android-specific\nJNI helpers)"]
50+
SJNI["SwiftJNI\n(low-level JNI\nC/Swift wrapper)"]
51+
end
52+
53+
subgraph "Compose Implementation"
54+
SUI["SkipUI\n(SwiftUI → Jetpack\nCompose mapping)"]
55+
SM["SkipModel\n(Compose state\ntracking)"]
56+
end
57+
58+
APP --> SFUI
59+
SFUI --> SSU
60+
SSU --> SB
61+
SSU --> SF
62+
SSU --> SUI
63+
SB --> SAB
64+
SB --> SJNI
65+
SUI --> SM
66+
67+
style APP fill:#f5f5f5,stroke:#333,color:#fff
68+
style SFUI fill:#f0e6ff,stroke:#7b2fbe,color:#fff
69+
style SSU fill:#f0e6ff,stroke:#7b2fbe,color:#fff
70+
style SB fill:#ffe6e6,stroke:#cc3333,color:#fff
71+
style SF fill:#ffe6e6,stroke:#cc3333,color:#fff
72+
style SAB fill:#ffe6e6,stroke:#cc3333,color:#fff
73+
style SJNI fill:#ffe6e6,stroke:#cc3333,color:#fff
74+
style SUI fill:#e6f0ff,stroke:#4a90d9,color:#fff
75+
style SM fill:#e6f0ff,stroke:#4a90d9,color:#fff
76+
```
77+
78+
On iOS, `SkipFuseUI` simply re-exports Apple's `SwiftUI` — the entire SkipSwiftUI layer is compiled away.
79+
80+
### Bridging Pattern
81+
82+
Every SwiftUI type in SkipFuseUI follows the same pattern: a Swift struct or class holds the view's parameters, and its `Java_view` property constructs the Kotlin equivalent on demand.
83+
84+
```mermaid
85+
sequenceDiagram
86+
participant App as Your View (Swift)
87+
participant Fuse as SkipFuseUI VStack (Swift)
88+
participant Bridge as SkipBridge (JNI)
89+
participant UI as SkipUI VStack (Kotlin)
90+
participant Compose as Jetpack Compose
91+
92+
App->>Fuse: VStack { Text("Hello") }
93+
Note over Fuse: Stores alignment,<br/>spacing, content
94+
Compose->>Fuse: Request Java_view
95+
Fuse->>Bridge: Create SkipUI.VStack<br/>with bridged content
96+
Bridge->>UI: JNI call → Kotlin object
97+
UI->>Compose: Emit Column composable
98+
```
99+
100+
Content views are recursively bridged via `Java_viewOrEmpty`, which walks the view tree and converts each Swift view into its Kotlin counterpart.
101+
102+
### State Bridging
103+
104+
SwiftUI property wrappers (`@State`, `@Binding`, `@AppStorage`) are backed by bridge-aware box types that synchronize values between Swift and Compose's reactive state system:
105+
106+
```mermaid
107+
flowchart LR
108+
S["@State var count = 0\n(Swift)"] -->|"BridgedStateBox"| K["StateSupport\n(Kotlin/Compose)"]
109+
K -->|"MutableState"| C["Compose\nRecomposition"]
110+
C -->|"read triggers\naccess()"| S
111+
112+
style S fill:#f0e6ff,stroke:#7b2fbe,color:#fff
113+
style K fill:#e6f0ff,stroke:#4a90d9,color:#fff
114+
style C fill:#e6ffe6,stroke:#2d8a2d,color:#fff
115+
```
116+
117+
When Swift code writes to a `@State` property, the `BridgedStateBox` notifies Compose's `MutableState`, triggering recomposition. When Compose reads the value, it calls back into Swift via the bridge. This two-way sync ensures that SwiftUI's declarative state model works identically on Android.
118+
119+
`@Observable` types require `import SkipFuse` to enable this state tracking. See the [App Development](/docs/app-development/#ui) guide for details.
120+
121+
## What SkipFuseUI Covers
122+
123+
SkipFuseUI mirrors the SwiftUI API surface for iOS 16+, including:
124+
125+
- **Containers**: `VStack`, `HStack`, `ZStack`, `List`, `ScrollView`, `LazyVGrid`, `LazyHGrid`, `NavigationStack`, `TabView`, `Form`, `Section`, `Group`
126+
- **Controls**: `Button`, `Toggle`, `Slider`, `Stepper`, `Picker`, `DatePicker`, `TextField`, `SecureField`, `TextEditor`
127+
- **Components**: `Text`, `Image`, `AsyncImage`, `Label`, `Link`, `ProgressView`, `Divider`, `ShareLink`
128+
- **Graphics**: `Color`, `Gradient`, `Shape` (Circle, Rectangle, Capsule, etc.), `Path`, `Material`
129+
- **Layout**: `GeometryReader`, `Alignment`, `EdgeInsets`, `ViewThatFits`, `Grid`
130+
- **State**: `@State`, `@Binding`, `@Environment`, `@AppStorage`, `@FocusState`
131+
- **Modifiers**: `.padding`, `.frame`, `.background`, `.overlay`, `.opacity`, `.rotation`, `.shadow`, `.clipShape`, `.sheet`, `.alert`, `.onAppear`, `.task`, and many more
132+
- **Navigation**: `NavigationStack`, `NavigationLink`, `NavigationPath`, `.navigationTitle`, `.toolbar`
133+
- **Gestures**: `TapGesture`, `LongPressGesture`, `DragGesture`
134+
- **Animation**: `withAnimation`, `.animation`, `.transition`, `Spring`
135+
- **UIKit compatibility**: `UIApplication`, `UIColor`, `UIImage`, `UIPasteboard`
136+
137+
For the full list of supported SwiftUI components, see the [SkipUI documentation](/docs/modules/skip-ui/#supported-swiftui).
138+
139+
## Related Documentation
140+
141+
- [App Development](/docs/app-development/) — Building dual-platform apps with Skip, including UI and view model coding
142+
- [Skip Modes](/docs/modes/) — Fuse vs. Lite mode and when to use each
143+
- [Bridging Reference](/docs/bridging/) — Supported Swift language features and types for bridging
144+
- [Cross-Platform Topics](/docs/platformcustomization/) — Integrating platform-specific code with `#if SKIP` and `#if os(Android)`
145+
- [SkipUI Module](/docs/modules/skip-ui/) — Supported SwiftUI components and Compose integration topics
146+
- [SkipBridge Module](/docs/modules/skip-bridge/) — The JNI bridging infrastructure that SkipFuseUI depends on
147+
- [SkipFuse Module](/docs/modules/skip-fuse/) — Observable state tracking and Android runtime support
14148

0 commit comments

Comments
 (0)