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

ui-components.mddocs/

UI Components

Compose Multiplatform for WASM/JS provides the complete set of Compose UI components, offering a declarative approach to building user interfaces. All standard Compose components work seamlessly with WASM targets, providing consistent behavior across platforms.

Layout Components

Column

Arranges children vertically.

@Composable
fun Column(
    modifier: Modifier = Modifier,
    verticalArrangement: Arrangement.Vertical = Arrangement.Top,
    horizontalAlignment: Alignment.Horizontal = Alignment.Start,
    content: @Composable ColumnScope.() -> Unit
)

Usage:

Column(
    modifier = Modifier.fillMaxSize(),
    verticalArrangement = Arrangement.Center,
    horizontalAlignment = Alignment.CenterHorizontally
) {
    Text("First item")
    Text("Second item")
    Button(onClick = {}) { Text("Click me") }
}

Row

Arranges children horizontally.

@Composable
fun Row(
    modifier: Modifier = Modifier,
    horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
    verticalAlignment: Alignment.Vertical = Alignment.Top,
    content: @Composable RowScope.() -> Unit
)

Usage:

Row(
    modifier = Modifier.fillMaxWidth(),
    horizontalArrangement = Arrangement.SpaceBetween,
    verticalAlignment = Alignment.CenterVertically
) {
    Icon(Icons.Default.Menu, contentDescription = "Menu")
    Text("Title")
    Icon(Icons.Default.Settings, contentDescription = "Settings")
}

Box

Stacks children on top of each other.

@Composable
fun Box(
    modifier: Modifier = Modifier,
    contentAlignment: Alignment = Alignment.TopStart,
    propagateMinConstraints: Boolean = false,
    content: @Composable BoxScope.() -> Unit
)

Usage:

Box(
    modifier = Modifier.size(200.dp),
    contentAlignment = Alignment.Center
) {
    Image(painter = backgroundPainter, contentDescription = null)
    Text("Overlay text")
}

Text Components

Text

Displays text with styling options.

@Composable
fun Text(
    text: String,
    modifier: Modifier = Modifier,
    color: Color = Color.Unspecified,
    fontSize: TextUnit = TextUnit.Unspecified,
    fontStyle: FontStyle? = null,
    fontWeight: FontWeight? = null,
    fontFamily: FontFamily? = null,
    letterSpacing: TextUnit = TextUnit.Unspecified,
    textDecoration: TextDecoration? = null,
    textAlign: TextAlign? = null,
    lineHeight: TextUnit = TextUnit.Unspecified,
    overflow: TextOverflow = TextOverflow.Clip,
    softWrap: Boolean = true,
    maxLines: Int = Int.MAX_VALUE,
    style: TextStyle = LocalTextStyle.current
)

Basic Usage:

Text("Hello, World!")

Styled Text:

Text(
    text = "Styled Text",
    fontSize = 24.sp,
    fontWeight = FontWeight.Bold,
    color = MaterialTheme.colors.primary,
    textAlign = TextAlign.Center
)

AnnotatedString Support

For rich text formatting:

@Composable
fun RichText() {
    val annotatedString = buildAnnotatedString {
        withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
            append("Bold text ")
        }
        withStyle(style = SpanStyle(color = Color.Red)) {
            append("red text ")
        }
        append("normal text")
    }
    
    Text(annotatedString)
}

Interactive Components

Button

Clickable button component.

@Composable
fun Button(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    elevation: ButtonElevation? = ButtonDefaults.elevation(),
    shape: Shape = MaterialTheme.shapes.small,
    border: BorderStroke? = null,
    colors: ButtonColors = ButtonDefaults.buttonColors(),
    contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
    content: @Composable RowScope.() -> Unit
)

Usage:

Button(
    onClick = { println("Button clicked!") },
    modifier = Modifier.fillMaxWidth()
) {
    Text("Click Me")
}

Custom Styled Button:

Button(
    onClick = { /* action */ },
    colors = ButtonDefaults.buttonColors(backgroundColor = Color.Red),
    shape = RoundedCornerShape(16.dp)
) {
    Icon(Icons.Default.Add, contentDescription = null)
    Spacer(Modifier.width(8.dp))
    Text("Add Item")
}

TextField

Text input component.

@Composable
fun TextField(
    value: String,
    onValueChange: (String) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    readOnly: Boolean = false,
    textStyle: TextStyle = LocalTextStyle.current,
    label: @Composable (() -> Unit)? = null,
    placeholder: @Composable (() -> Unit)? = null,
    leadingIcon: @Composable (() -> Unit)? = null,
    trailingIcon: @Composable (() -> Unit)? = null,
    isError: Boolean = false,
    visualTransformation: VisualTransformation = VisualTransformation.None,
    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
    keyboardActions: KeyboardActions = KeyboardActions.Default,
    singleLine: Boolean = false,
    maxLines: Int = Int.MAX_VALUE,
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    shape: Shape = MaterialTheme.shapes.small,
    colors: TextFieldColors = TextFieldDefaults.textFieldColors()
)

Usage:

var text by remember { mutableStateOf("") }

TextField(
    value = text,
    onValueChange = { text = it },
    label = { Text("Enter text") },
    placeholder = { Text("Type here...") },
    modifier = Modifier.fillMaxWidth()
)

Image Components

Image

Displays images from various sources.

@Composable
fun Image(
    painter: Painter,
    contentDescription: String?,
    modifier: Modifier = Modifier,
    alignment: Alignment = Alignment.Center,
    contentScale: ContentScale = ContentScale.Fit,
    alpha: Float = DefaultAlpha,
    colorFilter: ColorFilter? = null
)

Usage with Resources:

Image(
    painter = painterResource(Res.drawable.logo),
    contentDescription = "App logo",
    modifier = Modifier.size(100.dp)
)

Usage with Custom Painter:

Image(
    painter = rememberImagePainter("https://example.com/image.jpg"),
    contentDescription = "Remote image",
    contentScale = ContentScale.Crop,
    modifier = Modifier.fillMaxWidth().height(200.dp)
)

Icon

Displays vector icons.

@Composable
fun Icon(
    imageVector: ImageVector,
    contentDescription: String?,
    modifier: Modifier = Modifier,
    tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
)

Usage:

Icon(
    imageVector = Icons.Default.Favorite,
    contentDescription = "Favorite",
    tint = Color.Red,
    modifier = Modifier.size(24.dp)
)

List Components

LazyColumn

Efficiently displays large lists with lazy loading.

@Composable
fun LazyColumn(
    modifier: Modifier = Modifier,
    state: LazyListState = rememberLazyListState(),
    contentPadding: PaddingValues = PaddingValues(0.dp),
    reverseLayout: Boolean = false,
    verticalArrangement: Arrangement.Vertical = if (!reverseLayout) Arrangement.Top else Arrangement.Bottom,
    horizontalAlignment: Alignment.Horizontal = Alignment.Start,
    flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(),
    userScrollEnabled: Boolean = true,
    content: LazyListScope.() -> Unit
)

Usage:

val items = remember { List(1000) { "Item $it" } }

LazyColumn {
    items(items) { item ->
        Text(
            text = item,
            modifier = Modifier.padding(16.dp)
        )
    }
}

Complex List Items:

LazyColumn {
    items(users) { user ->
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .clickable { onUserClick(user) }
                .padding(16.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            Image(
                painter = painterResource(user.avatar),
                contentDescription = null,
                modifier = Modifier.size(40.dp).clip(CircleShape)
            )
            Spacer(Modifier.width(16.dp))
            Column {
                Text(user.name, fontWeight = FontWeight.Bold)
                Text(user.email, style = MaterialTheme.typography.caption)
            }
        }
    }
}

LazyRow

Horizontal lazy list.

@Composable
fun LazyRow(
    modifier: Modifier = Modifier,
    state: LazyListState = rememberLazyListState(),
    contentPadding: PaddingValues = PaddingValues(0.dp),
    reverseLayout: Boolean = false,
    horizontalArrangement: Arrangement.Horizontal = if (!reverseLayout) Arrangement.Start else Arrangement.End,
    verticalAlignment: Alignment.Vertical = Alignment.Top,
    flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(),
    userScrollEnabled: Boolean = true,
    content: LazyListScope.() -> Unit
)

Modifier System

Common Modifiers

Size and Layout:

Modifier
    .size(100.dp)
    .width(200.dp)
    .height(50.dp)
    .fillMaxSize()
    .fillMaxWidth()
    .fillMaxHeight()
    .wrapContentSize()

Padding and Margins:

Modifier
    .padding(16.dp)
    .padding(horizontal = 24.dp, vertical = 12.dp)
    .padding(start = 16.dp, end = 8.dp)

Visual Styling:

Modifier
    .background(Color.Blue)
    .clip(RoundedCornerShape(8.dp))
    .border(1.dp, Color.Gray, RoundedCornerShape(4.dp))
    .shadow(elevation = 4.dp)

Interaction:

Modifier
    .clickable { /* click action */ }
    .selectable(selected = isSelected) { /* selection change */ }
    .toggleable(value = isToggled) { /* toggle action */ }

Animation Support

Animated Visibility

@Composable
fun AnimatedContent() {
    var visible by remember { mutableStateOf(true) }
    
    AnimatedVisibility(visible = visible) {
        Text("This content animates in and out")
    }
    
    Button(onClick = { visible = !visible }) {
        Text("Toggle")
    }
}

Content Transitions

@Composable
fun ContentTransition() {
    var currentContent by remember { mutableStateOf("A") }
    
    Crossfade(targetState = currentContent) { content ->
        when (content) {
            "A" -> Text("Content A")
            "B" -> Text("Content B")
        }
    }
}

Custom Components

Creating Custom Components

@Composable
fun CustomCard(
    title: String,
    content: String,
    modifier: Modifier = Modifier,
    onClick: (() -> Unit)? = null
) {
    Card(
        modifier = modifier.then(
            if (onClick != null) Modifier.clickable { onClick() }
            else Modifier
        ),
        elevation = 4.dp
    ) {
        Column(
            modifier = Modifier.padding(16.dp)
        ) {
            Text(
                text = title,
                style = MaterialTheme.typography.h6,
                fontWeight = FontWeight.Bold
            )
            Spacer(Modifier.height(8.dp))
            Text(
                text = content,
                style = MaterialTheme.typography.body2
            )
        }
    }
}

Usage:

CustomCard(
    title = "Card Title",
    content = "This is the card content that provides additional information.",
    onClick = { /* handle click */ }
)

WASM-Specific Considerations

Performance Optimizations

  • Lazy loading: Use LazyColumn/LazyRow for large datasets
  • State management: Minimize recomposition with proper state design
  • Image loading: Use async image loading for better performance

Browser Integration

Components automatically handle:

  • Touch events: Full touch gesture support
  • Keyboard navigation: Tab navigation and accessibility
  • High DPI displays: Automatic pixel density scaling
  • Responsive layout: Window resize handling

Memory Management

  • Component cleanup: Use DisposableEffect for cleanup
  • State persistence: State survives browser navigation
  • Resource management: Automatic cleanup of UI resources

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