Compose Multiplatform UI library for WebAssembly/JS target - declarative framework for sharing UIs across multiple platforms with Kotlin.
—
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.
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") }
}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")
}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")
}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
)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)
}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")
}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()
)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)
)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)
)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)
}
}
}
}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
)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 */ }@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")
}
}@Composable
fun ContentTransition() {
var currentContent by remember { mutableStateOf("A") }
Crossfade(targetState = currentContent) { content ->
when (content) {
"A" -> Text("Content A")
"B" -> Text("Content B")
}
}
}@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 */ }
)Components automatically handle:
DisposableEffect for cleanupInstall with Tessl CLI
npx tessl i tessl/maven-org-jetbrains-compose-ui--ui-wasm-js