CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-jetbrains-compose-ui--ui-wasm-js

Compose Multiplatform UI library for WebAssembly/JS target - declarative framework for sharing UIs across multiple platforms with Kotlin.

Pending
Overview
Eval results
Files

window-management.mddocs/

Window Management

Window management in Compose Multiplatform for WASM/JS centers around the CanvasBasedWindow function, which creates the main application window that renders to an HTML5 Canvas element. This approach provides full control over the rendering surface while integrating seamlessly with web browsers.

Core Window Management

CanvasBasedWindow

The primary function for creating WASM/JS applications.

@OptIn(ExperimentalComposeUiApi::class)
fun CanvasBasedWindow(
    canvasElementId: String? = null,
    title: String = "Compose Application",
    content: @Composable () -> Unit
)

Parameters:

  • canvasElementId: ID of the HTML canvas element to render into. If null, uses default "ComposeTarget"
  • title: Window title (affects browser tab title)
  • content: Composable content to display in the window

Usage:

@OptIn(ExperimentalComposeUiApi::class)
fun main() {
    CanvasBasedWindow("MyCanvas") {
        MaterialTheme {
            Text("Hello WASM!")
        }
    }
}

Canvas Element Setup

The HTML document must contain a canvas element with the specified ID:

<!DOCTYPE html>
<html>
<head>
    <title>My Compose App</title>
    <meta charset="UTF-8">
</head>
<body>
    <canvas id="MyCanvas"></canvas>
    <script src="your-app.js"></script>
</body>
</html>

Application Lifecycle

Initialization Sequence

  1. WASM Module Loading: Browser loads and initializes the WASM module
  2. Canvas Acquisition: Application locates and binds to the canvas element
  3. Compose Runtime Setup: Initializes the Compose runtime system
  4. Content Rendering: Begins rendering the composable content

Main Function Pattern

@OptIn(ExperimentalComposeUiApi::class)
fun main() {
    // Optional: Configure resources before window creation
    configureWebResources {
        resourcePathMapping { path -> "./$path" }
    }
    
    // Create the main application window
    CanvasBasedWindow(
        canvasElementId = "ComposeTarget",
        title = "My Application"
    ) {
        // Your application content
        App()
    }
}

Window Configuration

Canvas Element Targeting

Default Behavior:

CanvasBasedWindow("ComposeTarget") { /* content */ }

Custom Canvas ID:

CanvasBasedWindow("myCustomCanvas") { /* content */ }

Auto-Detection (null ID):

CanvasBasedWindow(canvasElementId = null) { /* content */ }
// Uses default "ComposeTarget" ID

Title Management

The title parameter affects:

  • Browser tab title
  • Window identification in browser developer tools
  • Accessibility tools
CanvasBasedWindow(
    canvasElementId = "app",
    title = "My WASM Application - ${BuildConfig.VERSION}"
) {
    // Application content
}

Experimental APIs

ExperimentalComposeUiApi

All window management functions require the experimental API opt-in:

@file:OptIn(ExperimentalComposeUiApi::class)

import androidx.compose.ui.ExperimentalComposeUiApi

This annotation indicates that WASM support is experimental and APIs may change.

Canvas Integration

Canvas Properties

The canvas element receives these properties:

  • Full event handling: Mouse, keyboard, touch events
  • Automatic sizing: Canvas resizes with browser window
  • High DPI support: Automatic pixel density detection
  • Focus management: Keyboard focus and tab navigation

CSS Styling

Style the canvas element for proper display:

#ComposeTarget {
    width: 100vw;
    height: 100vh;
    display: block;
    margin: 0;
    padding: 0;
}

body {
    margin: 0;
    padding: 0;
    overflow: hidden;
}

Error Handling

Common Issues

Canvas Not Found:

Error: Canvas element with ID 'ComposeTarget' not found
  • Ensure canvas element exists in HTML
  • Verify ID matches exactly (case-sensitive)
  • Check that script loads after canvas element

WASM Initialization Failure:

Error: Failed to instantiate WebAssembly module
  • Verify browser supports WASM GC
  • Check MIME type configuration
  • Ensure WASM file is served correctly

Resource Loading Issues:

Error: Failed to load application resources
  • Configure web resources before window creation
  • Check resource path mappings
  • Verify CORS configuration

Debug Strategies

Canvas Detection:

// Check if canvas exists before creating window
val canvas = document.getElementById("ComposeTarget")
if (canvas == null) {
    console.error("Canvas element not found!")
    return
}

CanvasBasedWindow("ComposeTarget") { /* content */ }

Console Logging:

fun main() {
    console.log("Starting WASM application...")
    
    CanvasBasedWindow("ComposeTarget") {
        console.log("Window content initialized")
        App()
    }
}

Performance Considerations

Rendering Optimization

  • Canvas sizing: Use CSS for responsive sizing, avoid frequent resize operations
  • Event handling: Minimize event listener overhead
  • Animation: Use Compose animation APIs for optimal performance

Memory Management

  • Canvas cleanup: Browser automatically manages canvas memory
  • Event listeners: Automatically cleaned up when window closes
  • Resource cleanup: Use DisposableEffect for manual cleanup
@Composable
fun App() {
    DisposableEffect(Unit) {
        val cleanup = { /* cleanup code */ }
        onDispose { cleanup() }
    }
    
    // App content
}

Integration with Web Platform

Browser Events

Canvas automatically receives and translates:

  • Mouse events: Click, move, wheel
  • Keyboard events: Key press, release, modifiers
  • Touch events: Touch start, move, end
  • Focus events: Focus in, focus out

Accessibility

  • Screen reader support: Canvas content is accessible
  • Keyboard navigation: Full tab navigation support
  • High contrast: Automatic high contrast mode detection
  • Zoom support: Responds to browser zoom settings

Browser API Access

Access browser APIs from window content:

@Composable
fun BrowserIntegration() {
    LaunchedEffect(Unit) {
        // Access browser window
        val title = window.document.title
        
        // Modify browser state
        window.history.pushState(null, "", "/new-route")
        
        // Use browser APIs
        val userLanguage = window.navigator.language
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-org-jetbrains-compose-ui--ui-wasm-js

docs

browser-integration.md

index.md

material-design.md

resource-management.md

state-management.md

ui-components.md

window-management.md

tile.json