| Symbol | Meaning |
|---|---|
| β | Fully Supported (Common Code). No platform-specific code needed. |
| Supported with Caveats. Experimental or slight behavior differences. | |
| π§ | Work in Progress / Beta. Available but may be unstable (e.g., Wasm). |
| π οΈ | Requires Interop / 3rd Party. No official common component exists yet. |
Most Material 3 UI components are implemented in pure Kotlin and rendered via Skia, making them identical across platforms.
| Component | Android | iOS | Desktop (JVM) | Web (Wasm) |
|---|---|---|---|---|
| Button / FAB | β | β | β | β |
| Card / Surface | β | β | β | β |
| Text / Typography | β | β | β | β |
| TextField (Input) | β | β (Native text actions added recently) | β | β |
| Checkbox / Switch | β | β | β | β |
| Slider / Progress | β | β | β | β |
| Scaffold / AppBars | β | β | β | β |
| Icon / IconButton | β | β | β | β |
| Lazy Lists / Grids | β | β | β | β |
| ModalBottomSheet | β | β | β | β |
| NavigationDrawer | β | β | β | β |
| Snackbar / Toast | β | β | β | β |
| Badge / Chips | β | β | β | β |
| Dialog / Popup | β | β | β (Creates new Window) | β |
| DatePicker | β | β (Experimental) | β (Experimental) | β (Experimental) |
| TimePicker | β | β (Experimental) | β (Experimental) | β (Experimental) |
| PullToRefresh | β | β | β | β |
These components interact with the underlying operating system.
| Component | Android | iOS | Desktop (JVM) | Web (Wasm) |
|---|---|---|---|---|
| Navigation | β (Jetpack Nav 2.8+) | β (Jetpack Nav 2.8+) | β (Jetpack Nav 2.8+) | β (Jetpack Nav 2.8+) |
| Resources (Res) | β (compose-resources) | β (compose-resources) | β (compose-resources) | β (compose-resources) |
| Vector Graphics | β (XML vectors) | β (XML vectors) | β (XML vectors) | β (XML vectors) |
| WindowInsets | β | β (Notch/Keyboard) | β | β |
| Clipboard | β | β | β | |
| Mouse / Hover | β | β | β | |
| Keyboard Shortcuts | β | β (HW Keyboard) | β | β |
| BackHandler | β | β (Gesture/Swipe) | β (N/A) |
These features require distinct implementations because they rely on heavy native APIs that Skia cannot draw directly.
| Component | Status | Recommended Solution |
|---|---|---|
| WebView | π οΈ | compose-webview-multiplatform |
| Google Maps | π οΈ | kmp-maps-compose |
| Camera | π οΈ | Peekaboo |
| Video Player | π οΈ | ComposeMultiplatformMediaPlayer |
| Bluetooth / BLE | π οΈ | Kable |
| Biometrics | π οΈ | Moko-biometry |
| Permissions | π οΈ | Moko-permissions |
| HTML / Markdown | π οΈ | multiplatform-markdown-renderer |
- Rendering: CMP on iOS uses a Skia canvas. It does not translate to UIView.
- Scroll Physics: iOS scroll physics (rubber-banding) are natively supported.
- Selection: Native text selection handles are supported.
- Interop: You can place a UILabel inside Compose using UIKitView, or place Compose inside a SwiftUI view using ComposeViewController.
- Window Management: Has unique APIs (Window, Tray, MenuBar) that don't exist on mobile.
- Dialogs: Dialog and Popup often create a separate undecorated window rather than an overlay.
- Status: Currently in Alpha/Beta.
- Fonts: Must be loaded explicitly as resources; cannot rely on system fonts as easily.
- Multithreading: Limited support (coroutines run on Main thread mostly).
If it is a visual component (Button, Row, Text), it works everywhere. If it is a hardware component (Camera, GPS, Bluetooth), you need a third-party library or expect/actual native implementations.
Compose Multiplatform (CMP) component support and their recommended library solutions for missing native features
| Category | Component / Feature | Android | iOS | Desktop | Web (Wasm) | Recommended Library / Notes |
|---|---|---|---|---|---|---|
| UI Core | Material 3 (Buttons, Cards, etc.) | β | β | β | β | Built-in (Pure Kotlin) |
| UI Core | Text & Typography | β | β | β | β | Built-in |
| UI Core | Lazy Lists & Grids | β | β | β | β | Built-in |
| UI Core | TextField (Input) | β | β | β | β | Built-in |
| Navigation | Navigation Component | β | β | β | β | Jetpack Navigation |
| Resources | Images, Fonts, Strings | β | β | β | β | compose-resources |
| Media | WebView | π οΈ | π οΈ | π οΈ | π οΈ | compose-webview-multiplatform |
| Media | Video Player | π οΈ | π οΈ | π οΈ | π οΈ | ComposeMultiplatformMediaPlayer |
| Hardware | Camera | π οΈ | π οΈ | β | β | Peekaboo |
| Hardware | Google Maps | π οΈ | π οΈ | β | β | kmp-maps-compose |
| Hardware | Bluetooth (BLE) | π οΈ | π οΈ | π οΈ | π οΈ | Kable |
| System | Permissions | π οΈ | π οΈ | β | β | Moko-permissions |
| System | Biometrics | π οΈ | π οΈ | β | β | Moko-biometry |
| Data | Local Database | π οΈ | π οΈ | π οΈ | π οΈ | Room or SQLDelight |
| Data | Markdown Rendering | π οΈ | π οΈ | π οΈ | π οΈ | multiplatform-markdown-renderer |
Because CMP renders via the Skia/Skiko engine, it effectively draws its own UI on a canvas. This is why standard UI components work everywhere, while hardware-dependent features (like the Camera) require "bridges."
- For β
(Green): Simply use the standard
androidx.composeororg.jetbrains.composeimports in yourcommonMainfolder. - For π οΈ (Wrench): Add the library dependency to your
commonMaininbuild.gradle.kts. These libraries useexpect/actualto talk to the underlying OS (e.g., UIKit for iOS and Android Views for Android).