Limitations
- Warn the user that this skill is EXPERIMENTAL and requires updating to alpha version of Compose and opting in to the Experimental APIs.
- This skill only supports custom UI components and custom themes.
- This skill does not support Material Design component Styles.
Prerequisites
1. Upgrade dependencies
- The project must use
compileSdk version 37 or higher.
- The project must use
androidx.compose.foundation:foundation version 1.12.0-alpha01 or higher.
- Alternatively, the project must use Compose BOM version
2026.04.01 or higher.
- The API requires this exact package:
import androidx.compose.foundation.style.Style
You must opt-in to the experimental API at the project level. Add the following
block to your module's build.gradle.kts:
Core workflows and guides
Refer to the official documentation to complete specific development tasks:
Step-by-Step Migration Workflow
Step 1: Analyze theme structure
- Locate your central theme file (such as
Theme.kt).
- Identify design tokens. Note references for colors, typography, and shapes (for example,
LocalColorScheme, LocalTypography, or LocalShapes).
- If the project lacks Jetpack Compose dependencies, stop. Instruct the user to migrate to Jetpack Compose first.
- If the project imports
androidx.compose.material.MaterialTheme, recommend migrating to Material 3 before proceeding.
Step 2: Establish ComponentStyles
-
Create a new file named ComponentStyles.kt in your theme directory.
-
Define a top-level data class to hold your component styles, for example, the Jetsnack one is called JetsnackStyles:
-
Expose this class through your custom theme with a static reference, don't
use CompositionLocals here as it's not required.
-
Provide extensions on StyleScope to reference theme tokens directly if
they are exposed using CompositionLocals. For example:
Step 3: Migrate a component to Styles API
For each custom component (for example, CustomButton), complete the following
sequence:
- Establish a visual baseline (If an emulator is available):
- If you CANNOT run an Android emulator: Skip this step entirely and proceed to Step 2.
- If you CAN run an Android emulator: Perform the following to capture a baseline screenshot:
- Option A: Locate and run an existing screenshot test for the component.
- Option B (If no test exists): Create a test using the project's existing testing framework, then run it.
- Option C (If no framework exists): Create a minimal screenshot test using UI Automator or Espresso, then run it.
- Remove individual styling parameters : Remove styling parameters such as
backgroundColor, shape, textStyle, and contentPadding from the signature - anything that StyleScope supports.
- Add the style parameter : Add
style: Style = Style to the function signature. Always ensure the default value is exactly Style (e.g., style: Style = Style) and not a specific style default like ChipStyleDefault or any other value.
- Declare state tracking : If the component is interactable, create a
MutableStyleState using the interaction source. Update state fields (such as isEnabled) inside the Composable to track the state correctly.
- Apply styleable modifier : Replace specific layout modifiers on the root element with
Modifier.styleable().
- Move defaults to ComponentStyles : Move hardcoded values from the component definition to a dedicated
Style instance in ComponentStyles.kt.
- Validate component: Compare the baseline screenshot image taken at the start with the rendered Compose Preview of the new composable. Ignore string content; focus on layout and styling. Iterate on the Compose code until visual parity is achieved. Once verified, write a Compose UI test for the new composable.
Migration example
Before Migration:
After Migration:
Step 4: Validate Changes
- Build the project. Verify that there are no compilation errors.
- Run your module's screenshot tests.
- Compare visual outputs of the whole app between the previous and updated components. Verify that no visual layout regressions occur.