Compose Multiplatform UI library for iOS Simulator ARM64 target providing declarative UI framework based on Jetpack Compose for multiplatform development
—
Platform-specific window management and integration capabilities for Desktop, iOS, Android, and Web platforms, providing native-like application experiences across all supported targets.
Comprehensive window management system for desktop applications with support for multiple windows, window states, and native platform integration.
/**
* Creates a single window application.
*/
@Composable
fun singleWindowApplication(
state: WindowState = rememberWindowState(),
visible: Boolean = true,
title: String = "Untitled",
icon: Painter? = null,
undecorated: Boolean = false,
transparent: Boolean = false,
resizable: Boolean = true,
enabled: Boolean = true,
focusable: Boolean = true,
alwaysOnTop: Boolean = false,
onPreviewKeyEvent: (KeyEvent) -> Boolean = { false },
onKeyEvent: (KeyEvent) -> Boolean = { false },
content: @Composable WindowScope.() -> Unit
)
/**
* Creates a window application with multiple windows.
*/
@Composable
fun application(
exitProcessOnExit: Boolean = true,
content: @Composable ApplicationScope.() -> Unit
)
/**
* Creates a window within an application.
*/
@Composable
fun ApplicationScope.Window(
onCloseRequest: () -> Unit,
state: WindowState = rememberWindowState(),
visible: Boolean = true,
title: String = "Untitled",
icon: Painter? = null,
undecorated: Boolean = false,
transparent: Boolean = false,
resizable: Boolean = true,
enabled: Boolean = true,
focusable: Boolean = true,
alwaysOnTop: Boolean = false,
onPreviewKeyEvent: (KeyEvent) -> Boolean = { false },
onKeyEvent: (KeyEvent) -> Boolean = { false },
content: @Composable WindowScope.() -> Unit
)
/**
* State holder for window properties.
*/
@Stable
class WindowState(
placement: WindowPlacement = WindowPlacement.Floating,
isMinimized: Boolean = false,
position: WindowPosition = WindowPosition.PlatformDefault,
size: DpSize = DpSize.Unspecified
) {
/**
* Current window placement mode.
*/
var placement: WindowPlacement by mutableStateOf(placement)
/**
* Whether the window is minimized.
*/
var isMinimized: Boolean by mutableStateOf(isMinimized)
/**
* Current window position.
*/
var position: WindowPosition by mutableStateOf(position)
/**
* Current window size.
*/
var size: DpSize by mutableStateOf(size)
}
/**
* Remember a WindowState across recompositions.
*/
@Composable
fun rememberWindowState(
placement: WindowPlacement = WindowPlacement.Floating,
isMinimized: Boolean = false,
position: WindowPosition = WindowPosition.PlatformDefault,
size: DpSize = DpSize.Unspecified
): WindowState
/**
* Window placement modes.
*/
enum class WindowPlacement {
Floating, Maximized, Fullscreen
}
/**
* Window position specification.
*/
sealed class WindowPosition {
object PlatformDefault : WindowPosition()
data class Absolute(val x: Dp, val y: Dp) : WindowPosition()
data class Aligned(val alignment: Alignment) : WindowPosition()
}
/**
* Size specification for windows.
*/
@Immutable
data class DpSize(
val width: Dp,
val height: Dp
) {
companion object {
val Unspecified: DpSize = DpSize(Dp.Unspecified, Dp.Unspecified)
val Zero: DpSize = DpSize(0.dp, 0.dp)
}
}
/**
* Scope for window content.
*/
interface WindowScope {
/**
* The current window state.
*/
val window: ComposeWindow
}
/**
* Scope for application content.
*/
interface ApplicationScope {
/**
* Exit the application.
*/
fun exitApplication()
}Usage Examples:
// Single window application
fun main() = singleWindowApplication(
title = "My Desktop App",
state = rememberWindowState(
placement = WindowPlacement.Floating,
size = DpSize(800.dp, 600.dp),
position = WindowPosition.Aligned(Alignment.Center)
),
resizable = true,
icon = painterResource("app_icon.png")
) {
Column(
modifier = Modifier.fillMaxSize().padding(16.dp)
) {
Text("Desktop Application")
Button(onClick = {
window.close()
}) {
Text("Close Window")
}
}
}
// Multi-window application
fun main() = application {
var isSecondWindowVisible by remember { mutableStateOf(false) }
Window(
onCloseRequest = ::exitApplication,
title = "Main Window",
state = rememberWindowState(size = DpSize(600.dp, 400.dp))
) {
Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
Text("Main Window")
Button(onClick = { isSecondWindowVisible = true }) {
Text("Open Second Window")
}
}
}
if (isSecondWindowVisible) {
Window(
onCloseRequest = { isSecondWindowVisible = false },
title = "Second Window",
state = rememberWindowState(
position = WindowPosition.Absolute(100.dp, 100.dp),
size = DpSize(400.dp, 300.dp)
)
) {
Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
Text("Second Window")
Button(onClick = { isSecondWindowVisible = false }) {
Text("Close")
}
}
}
}
}
// Window with custom properties
fun main() = singleWindowApplication(
title = "Custom Window",
undecorated = true,
transparent = true,
alwaysOnTop = true,
state = rememberWindowState(
placement = WindowPlacement.Floating,
size = DpSize(300.dp, 200.dp)
)
) {
Box(
modifier = Modifier
.fillMaxSize()
.background(
Color.Black.copy(alpha = 0.8f),
RoundedCornerShape(8.dp)
)
) {
Text(
text = "Custom Window",
color = Color.White,
modifier = Modifier.align(Alignment.Center)
)
}
}Integration layer for iOS applications using UIKit interoperability and native iOS features.
/**
* Creates a UIViewController that hosts Compose content.
*/
fun ComposeUIViewController(
configure: ComposeUIViewControllerConfiguration = ComposeUIViewControllerConfiguration(),
content: @Composable () -> Unit
): UIViewController
/**
* Configuration for Compose UIViewController.
*/
class ComposeUIViewControllerConfiguration {
/**
* Whether the view controller should automatically adjust for safe areas.
*/
var automaticallyAdjustForSafeArea: Boolean = true
/**
* Background color for the view controller.
*/
var backgroundColor: UIColor? = null
/**
* Whether to use system gestures.
*/
var systemGestures: Boolean = true
/**
* Status bar style preference.
*/
var statusBarStyle: UIStatusBarStyle? = null
}
/**
* Access to iOS-specific platform features.
*/
object IOSPlatform {
/**
* Get the current safe area insets.
*/
val safeAreaInsets: EdgeInsets
/**
* Whether the device is in dark mode.
*/
val isDarkMode: Boolean
/**
* Current device orientation.
*/
val deviceOrientation: DeviceOrientation
/**
* Show/hide the status bar.
*/
fun setStatusBarHidden(hidden: Boolean, animated: Boolean = true)
/**
* Present a native iOS alert.
*/
suspend fun showAlert(
title: String,
message: String,
primaryButton: String = "OK",
secondaryButton: String? = null
): Boolean
}
/**
* Device orientation states.
*/
enum class DeviceOrientation {
Portrait, PortraitUpsideDown, LandscapeLeft, LandscapeRight, Unknown
}
/**
* Edge insets for safe areas.
*/
@Immutable
data class EdgeInsets(
val top: Dp,
val leading: Dp,
val bottom: Dp,
val trailing: Dp
)
/**
* CompositionLocal for accessing iOS platform features.
*/
val LocalIOSPlatform: ProvidableCompositionLocal<IOSPlatform>Usage Examples:
// Basic iOS integration
fun createMainViewController() = ComposeUIViewController(
configure = ComposeUIViewControllerConfiguration().apply {
automaticallyAdjustForSafeArea = true
backgroundColor = UIColor.systemBackgroundColor
statusBarStyle = UIStatusBarStyle.UIStatusBarStyleDefault
}
) {
IOSApp()
}
@Composable
fun IOSApp() {
val platform = LocalIOSPlatform.current
val safeAreaInsets = platform.safeAreaInsets
Column(
modifier = Modifier
.fillMaxSize()
.padding(
top = safeAreaInsets.top,
bottom = safeAreaInsets.bottom,
start = safeAreaInsets.leading,
end = safeAreaInsets.trailing
)
) {
Text("iOS Application")
Button(onClick = {
// Show native iOS alert
coroutineScope.launch {
val result = platform.showAlert(
title = "Confirmation",
message = "Are you sure?",
primaryButton = "Yes",
secondaryButton = "No"
)
if (result) {
// User tapped "Yes"
}
}
}) {
Text("Show Alert")
}
Text("Dark mode: ${platform.isDarkMode}")
Text("Orientation: ${platform.deviceOrientation}")
}
}
// Custom iOS view controller integration
class CustomIOSViewController : UIViewController {
private val composeView = ComposeUIViewController {
MyComposeContent()
}
override fun viewDidLoad() {
super.viewDidLoad()
// Add Compose content as child view controller
addChild(composeView)
view.addSubview(composeView.view)
composeView.didMove(toParent = this)
// Setup constraints
composeView.view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate(listOf(
composeView.view.topAnchor.constraint(equalTo = view.safeAreaLayoutGuide.topAnchor),
composeView.view.leadingAnchor.constraint(equalTo = view.leadingAnchor),
composeView.view.trailingAnchor.constraint(equalTo = view.trailingAnchor),
composeView.view.bottomAnchor.constraint(equalTo = view.safeAreaLayoutGuide.bottomAnchor)
))
}
}Web-specific window and platform features for Compose Multiplatform web applications.
/**
* Creates a Compose application for the web platform.
*/
fun CanvasBasedWindow(
canvasElementId: String? = null,
title: String = "Compose Application",
content: @Composable () -> Unit
)
/**
* Access to web-specific platform features.
*/
object WebPlatform {
/**
* The current browser window.
*/
val window: Window
/**
* The current document.
*/
val document: Document
/**
* Current viewport size.
*/
val viewportSize: IntSize
/**
* Whether the page is loaded via HTTPS.
*/
val isSecure: Boolean
/**
* Current page URL.
*/
val currentUrl: String
/**
* Navigate to a new URL.
*/
fun navigateTo(url: String)
/**
* Show a browser alert dialog.
*/
fun alert(message: String)
/**
* Show a browser confirmation dialog.
*/
fun confirm(message: String): Boolean
/**
* Download a file.
*/
fun downloadFile(data: ByteArray, fileName: String, mimeType: String = "application/octet-stream")
/**
* Copy text to clipboard.
*/
suspend fun copyToClipboard(text: String): Boolean
/**
* Read text from clipboard.
*/
suspend fun readFromClipboard(): String?
}
/**
* Browser storage access.
*/
object WebStorage {
/**
* Local storage operations.
*/
object Local {
fun setItem(key: String, value: String)
fun getItem(key: String): String?
fun removeItem(key: String)
fun clear()
val length: Int
}
/**
* Session storage operations.
*/
object Session {
fun setItem(key: String, value: String)
fun getItem(key: String): String?
fun removeItem(key: String)
fun clear()
val length: Int
}
}
/**
* CompositionLocal for accessing web platform features.
*/
val LocalWebPlatform: ProvidableCompositionLocal<WebPlatform>Usage Examples:
// Web application setup
fun main() {
CanvasBasedWindow(
canvasElementId = "ComposeTarget",
title = "My Web App"
) {
WebApp()
}
}
@Composable
fun WebApp() {
val platform = LocalWebPlatform.current
var viewportSize by remember { mutableStateOf(platform.viewportSize) }
var clipboardContent by remember { mutableStateOf("") }
// Update viewport size on window resize
LaunchedEffect(Unit) {
// Listen for window resize events
platform.window.addEventListener("resize") {
viewportSize = platform.viewportSize
}
}
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
) {
Text("Web Application")
Text("Viewport: ${viewportSize.width} x ${viewportSize.height}")
Text("URL: ${platform.currentUrl}")
Text("Secure: ${platform.isSecure}")
Spacer(modifier = Modifier.height(16.dp))
Row {
Button(onClick = {
platform.alert("Hello from Compose!")
}) {
Text("Show Alert")
}
Spacer(modifier = Modifier.width(8.dp))
Button(onClick = {
val confirmed = platform.confirm("Are you sure?")
if (confirmed) {
platform.alert("Confirmed!")
}
}) {
Text("Show Confirm")
}
}
Spacer(modifier = Modifier.height(16.dp))
// Clipboard operations
TextField(
value = clipboardContent,
onValueChange = { clipboardContent = it },
label = { Text("Clipboard content") },
modifier = Modifier.fillMaxWidth()
)
Row {
Button(onClick = {
coroutineScope.launch {
platform.copyToClipboard(clipboardContent)
}
}) {
Text("Copy to Clipboard")
}
Spacer(modifier = Modifier.width(8.dp))
Button(onClick = {
coroutineScope.launch {
val content = platform.readFromClipboard()
if (content != null) {
clipboardContent = content
}
}
}) {
Text("Read from Clipboard")
}
}
Spacer(modifier = Modifier.height(16.dp))
// File download
Button(onClick = {
val data = "Hello, World!".toByteArray()
platform.downloadFile(data, "hello.txt", "text/plain")
}) {
Text("Download File")
}
// Local storage operations
Button(onClick = {
WebStorage.Local.setItem("myKey", clipboardContent)
platform.alert("Saved to local storage!")
}) {
Text("Save to Local Storage")
}
Button(onClick = {
val stored = WebStorage.Local.getItem("myKey")
if (stored != null) {
clipboardContent = stored
}
}) {
Text("Load from Local Storage")
}
}
}Cross-platform dialog and modal window management for user interactions and confirmations.
/**
* A modal dialog window.
*/
@Composable
fun Dialog(
onDismissRequest: () -> Unit,
properties: DialogProperties = DialogProperties(),
content: @Composable () -> Unit
)
/**
* Properties for configuring dialog behavior.
*/
@Immutable
data class DialogProperties(
val dismissOnBackPress: Boolean = true,
val dismissOnClickOutside: Boolean = true,
val securePolicy: SecureFlagPolicy = SecureFlagPolicy.Inherit,
val usePlatformDefaultWidth: Boolean = true,
val decorFitsSystemWindows: Boolean = true
)
/**
* Security policies for dialog windows.
*/
enum class SecureFlagPolicy {
Inherit, SecureOn, SecureOff
}
/**
* A popup window positioned relative to its parent.
*/
@Composable
fun Popup(
alignment: Alignment = Alignment.TopStart,
offset: IntOffset = IntOffset.Zero,
onDismissRequest: (() -> Unit)? = null,
properties: PopupProperties = PopupProperties(),
content: @Composable () -> Unit
)
/**
* Properties for configuring popup behavior.
*/
@Immutable
data class PopupProperties(
val focusable: Boolean = false,
val dismissOnBackPress: Boolean = true,
val dismissOnClickOutside: Boolean = true,
val securePolicy: SecureFlagPolicy = SecureFlagPolicy.Inherit,
val excludeFromSystemGesture: Boolean = true,
val clippingEnabled: Boolean = true,
val usePlatformDefaultWidth: Boolean = false
)
/**
* Desktop-specific file dialogs.
*/
object FileDialog {
/**
* Show a file chooser dialog.
*/
suspend fun openFileDialog(
title: String = "Open File",
allowedExtensions: List<String> = emptyList(),
allowMultiSelection: Boolean = false,
initialDirectory: String? = null
): List<String>?
/**
* Show a save file dialog.
*/
suspend fun saveFileDialog(
title: String = "Save File",
allowedExtensions: List<String> = emptyList(),
initialFileName: String? = null,
initialDirectory: String? = null
): String?
/**
* Show a directory chooser dialog.
*/
suspend fun openDirectoryDialog(
title: String = "Choose Directory",
initialDirectory: String? = null
): String?
}Usage Examples:
// Basic dialog usage
@Composable
fun DialogExample() {
var showDialog by remember { mutableStateOf(false) }
Column {
Button(onClick = { showDialog = true }) {
Text("Show Dialog")
}
if (showDialog) {
Dialog(
onDismissRequest = { showDialog = false },
properties = DialogProperties(
dismissOnBackPress = true,
dismissOnClickOutside = true
)
) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
shape = RoundedCornerShape(16.dp)
) {
Column(
modifier = Modifier.padding(24.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
Text(
text = "Dialog Title",
style = MaterialTheme.typography.h6
)
Text("This is the dialog content.")
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.End
) {
TextButton(onClick = { showDialog = false }) {
Text("Cancel")
}
TextButton(onClick = { showDialog = false }) {
Text("OK")
}
}
}
}
}
}
}
}
// Popup window example
@Composable
fun PopupExample() {
var showPopup by remember { mutableStateOf(false) }
Box {
Button(onClick = { showPopup = !showPopup }) {
Text("Toggle Popup")
}
if (showPopup) {
Popup(
alignment = Alignment.TopEnd,
offset = IntOffset(0, 40),
onDismissRequest = { showPopup = false }
) {
Card(
modifier = Modifier.size(200.dp, 150.dp),
elevation = 8.dp
) {
Column(
modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
Text("Popup Content")
Text("Click outside to dismiss")
Button(onClick = { showPopup = false }) {
Text("Close")
}
}
}
}
}
}
}
// File dialog example (Desktop)
@Composable
fun FileDialogExample() {
var selectedFiles by remember { mutableStateOf<List<String>>(emptyList()) }
var saveLocation by remember { mutableStateOf<String?>(null) }
val coroutineScope = rememberCoroutineScope()
Column(verticalArrangement = Arrangement.spacedBy(16.dp)) {
Button(onClick = {
coroutineScope.launch {
val files = FileDialog.openFileDialog(
title = "Select Images",
allowedExtensions = listOf("jpg", "png", "gif"),
allowMultiSelection = true
)
if (files != null) {
selectedFiles = files
}
}
}) {
Text("Open Files")
}
if (selectedFiles.isNotEmpty()) {
Text("Selected files:")
selectedFiles.forEach { file ->
Text("• $file", style = MaterialTheme.typography.body2)
}
}
Button(onClick = {
coroutineScope.launch {
val location = FileDialog.saveFileDialog(
title = "Save Document",
allowedExtensions = listOf("txt", "md"),
initialFileName = "document.txt"
)
saveLocation = location
}
}) {
Text("Save File")
}
saveLocation?.let { location ->
Text("Save location: $location")
}
Button(onClick = {
coroutineScope.launch {
val directory = FileDialog.openDirectoryDialog(
title = "Choose Output Directory"
)
if (directory != null) {
// Handle directory selection
}
}
}) {
Text("Choose Directory")
}
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-jetbrains-compose-ui--ui-uikitsimarm64