brainstorming
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or planning anything new, in software or out of it (a talk, a business, a renovation).
wear-compose-m3Guidance for Wear OS Compose Material3 (Wear Compose Material 3 / Wear Compose Material3) watch and wearable apps. Covers creating, updating, and migrating projects (Material 2.5 and Horologist migration) using androidx.wear.compose.material3, androidx.wear.compose.foundation, and androidx.wear.compose.navigation3, including AppScaffold, ScreenScaffold, Tra…
Independent GitHub snapshot · Automated classification · Original documentation governs
name: wear-compose-m3 description: Guidance for Wear OS Compose Material3 (Wear Compose Material 3 / Wear Compose Material3) watch and wearable apps. Covers creating, updating, and migrating projects (Material 2.5 and Horologist migration) using androidx.wear.compose.material3, androidx.wear.compose.foundation, and androidx.wear.compose.navigation3, including AppScaffold, ScreenScaffold, TransformingLazyColumn, ambient mode, and previews. license: Complete terms in LICENSE.txt metadata: author: Google LLC last-updated: '2026-09-24' keywords:
gradle/libs.versions.toml or build.gradle.kts directly. Don't run ./gradlew dependencies or other shell commands to resolve versions.{VERSION} of androidx.wear.compose:compose-material3, use that tool.
{VERSION} (highest number, ignoring -alpha, -beta, or -rc).org.jetbrains.kotlin.plugin.compose Gradle plugin.minSdk is at least 25.compileSdk and AGP meet the library's AAR metadata floors (compileSdk >= 35 and AGP >= 8.6.0 for 1.6.x; compileSdk >= 37 and AGP >= 9.1.0 for 1.7.x).libs.versions.toml or build.gradle.kts, perform a Gradle sync (or ./gradlew assembleDebug) before refactoring, and run ./gradlew assembleDebug after refactoring to verify the build.Use this guidance when migrating from an older version of Wear OS Compose or Horologist, updating an existing Wear Compose Material3 project, or adding features.
{VERSION} (superseding any literal version strings in the migration guide).Chip -> Button), check the parameter names, slot types, and "Expressive" design tokens.AppScaffold -> M3 AppScaffold, ScreenScaffold -> M3 ScreenScaffold, ScalingLazyColumn -> TransformingLazyColumn, ResponsiveListHeader -> ListHeader, PagerScreen -> HorizontalPagerScaffold, Chip -> Button, Confirmation -> ConfirmationDialog).Use this table of reference to find canonical samples for Wear Compose components. When working with a Wear Compose component, you must use the samples linked from the table to ensure you know how to correctly use it.
Important: Symbols marked with [alpha], [beta], or [rc] are only
available in that pre-release track and are not in stable {VERSION}. Do
not use them unless the project explicitly targets that pre-release version.
androidx.wear.compose.material3.*androidx.wear.compose.foundation.*androidx.wear.compose.navigation3.*| Component / Symbol | Reference Samples |
|---|---|
rememberSwipeDismissableSceneStrategy | SwipeDismissableSceneStrategySample |
Mandatory: Use this capability as a checklist against any component use. It provides more holistic guidance on how to use each component in practice, beyond the component syntax.
AppScaffold and ScreenScaffold
AppScaffold as the outer container, with ScreenScaffold children.AppScaffold and any number of ScreenScaffold.ScalingLazyColumn - Use TransformingLazyColumn instead.
TransformingLazyColumn - You will need the following imports:
import androidx.wear.compose.foundation.lazy.TransformingLazyColumn
import androidx.wear.compose.foundation.lazy.TransformingLazyColumnDefaults
import androidx.wear.compose.foundation.lazy.rememberTransformingLazyColumnState
// ...
import androidx.wear.compose.material3.lazy.rememberTransformationSpec
import androidx.wear.compose.material3.lazy.transformedHeight
Canonical example:
val columnState = rememberTransformingLazyColumnState()
val transformationSpec = rememberTransformationSpec()
ScreenScaffold(
scrollState = columnState
) { contentPadding ->
TransformingLazyColumn(
state = columnState,
contentPadding = contentPadding
) {
item {
ListHeader(
modifier = Modifier
.fillMaxWidth()
.transformedHeight(this, transformationSpec)
.minimumVerticalContentPadding(ListHeaderDefaults.minimumTopListContentPadding),
transformation = SurfaceTransformation(transformationSpec)
) {
Text(text = "Header")
}
}
// ... other items
item {
Button(
modifier = Modifier
.fillMaxWidth()
.transformedHeight(this, transformationSpec)
.minimumVerticalContentPadding(ButtonDefaults.minimumVerticalListContentPadding),
transformation = SurfaceTransformation(transformationSpec),
onClick = { /* ... */ },
icon = {
Icon(
imageVector = Icons.Default.Build,
contentDescription = "build",
)
},
) {
Text(
text = "Build",
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
}
}
}
TransformingLazyColumn instead of ScalingLazyColumn.contentPadding parameter from ScreenScaffold to the TransformingLazyColumn.minimumVerticalContentPadding modifier to achieve required padding top and bottom.
ButtonDefaults, CardDefaults, ListHeaderDefaults.TransformingLazyColumnItemScope.TransformingLazyColumn, not the list itself):
Modifier.transformedHeight(this, transformationSpec).transformation = SurfaceTransformation(transformationSpec).flingBehavior and rotaryScrollableBehavior together:val columnState = rememberTransformingLazyColumnState()
ScreenScaffold(scrollState = columnState) { contentPadding ->
TransformingLazyColumn(
state = columnState,
flingBehavior = TransformingLazyColumnDefaults.snapFlingBehavior(columnState),
rotaryScrollableBehavior = RotaryScrollableDefaults.snapBehavior(columnState)
) {
// ...
// ...
}
}
ScreenScaffold
scrollIndicator with !LocalScrollCaptureInProgress.current (androidx.compose.ui.platform).EdgeButton
TransformingLazyColumn. Instead, use the slot in ScreenScaffold.TransformingLazyColumn, add the required overscroll behavior:val columnState = rememberTransformingLazyColumnState()
ScreenScaffold(
scrollState = columnState,
edgeButton = {
EdgeButton(
onClick = { /* TODO */ },
modifier = Modifier.scrollable(
columnState,
orientation = Orientation.Vertical,
reverseDirection = true,
// Apply overscroll to the EdgeButton for proper scrolling behavior.
overscrollEffect = rememberOverscrollEffect(),
)
) {
Text("More")
}
}
) { contentPadding ->
TransformingLazyColumn(
contentPadding = contentPadding,
state = columnState,
) {
// ...
// ...
}
}
Column
ScreenScaffold if the screen will never scroll, even with the largest system font.TransformingLazyColumn instead for all other cases.Styles
typography from MaterialTheme.colorScheme from MaterialTheme.Use component defaults:
Button have a corresponding ButtonDefaults object.*Defaults object for any component when working with padding and styling values, in preference to hard-coded values.Use Wear-specific preview annotations
(androidx.wear.compose.ui.tooling.preview):
@WearPreviewDevices@WearPreviewFontScalesandroidx.wear.compose:compose-ui-tooling dependency is included.Ambient mode
LocalAmbientModeManager (provided by CompositionLocalProvider and rememberAmbientModeManager()) instead of AmbientLifecycleObserver.Navigation
androidx.wear.compose:compose-navigation3).rememberSwipeDismissableSceneStrategy() / SwipeDismissableSceneStrategy (androidx.wear.compose.navigation3).Comments
HorizontalPager or VerticalPager
AppScaffold, HorizontalPagerScaffold, HorizontalPager, AnimatedPage, ScreenScaffold. Or similarly for VerticalPager.