| name | compose-preview |
| description | Generate Jetpack Compose `@Preview` functions and `PreviewParameterProvider` classes. Use whenever the user wants to add previews to a `@Composable`, set up multi-config previews (light/dark, screen sizes, font scale, locale, dynamic color), or needs a `PreviewParameterProvider` for composables that take complex parameters. Triggers include phrases like "ํ๋ฆฌ๋ทฐ ์ถ๊ฐ", "preview ๋ง๋ค์ด์ค", "@Preview", "PreviewParameterProvider", "๋คํฌ๋ชจ๋ ํ๋ฆฌ๋ทฐ", "multi preview". |
compose-preview
Generates production-quality @Preview setups for Jetpack Compose.
When to use
Activate when the user is working with a @Composable and asks for any of:
- A preview function for a composable.
- Light/dark, screen size, font scale, locale, or dynamic color variants.
- A
PreviewParameterProvider for a composable whose parameters are non-trivial (data classes, sealed UI states, lists).
- A reusable multi-preview annotation for the project.
Configuration
Read project preferences from .claude/android-skills.json at the git repo root:
{
"compose": {
"themeName": "AppTheme",
"themePackage": "com.example.app.ui.theme",
"previewLocation": "co-located",
"defaultMultiPreview": "PreviewLightDark"
}
}
| Field | Values | Notes |
|---|
themeName | AppTheme, MyAppTheme, โฆ | Composable used to wrap previews. |
themePackage | FQN of the package containing the theme | Used when the preview file needs an import. |
previewLocation | co-located, separate-file | co-located appends to the composable's file; separate-file creates <Name>Preview.kt next to it. Default: co-located. |
defaultMultiPreview | none, PreviewLightDark, DevicePreviews, โฆ | Annotation applied by default unless the user asks for something else. |
Theme resolution order
- If
compose.themeName exists in the config โ use it.
- Else, search the codebase for a theme composable:
grep -rEn 'fun [A-Z][A-Za-z0-9]*Theme\s*\(' --include='*.kt' app/src/main/java
Filter to files under ui/theme/, theme/, or presentation/theme/. The function whose body invokes MaterialTheme is the project theme.
- If exactly one match โ use it. Offer to save it to the config so the next run skips this step.
- If multiple matches โ ask the user which one. Save the answer to the config.
- If no matches โ fall back to
MaterialTheme and warn the user. Do not write to the config.
Onboarding (run once)
If .claude/android-skills.json is missing or has no compose.themeName AND theme resolution step 2 found nothing, ask the user:
- "์ด ํ๋ก์ ํธ์ Compose ํ
๋ง ์ด๋ฆ์ ์๋ ค์ฃผ์ธ์ (์:
AppTheme)."
- "ํ
๋ง๊ฐ ๋ค์ด์๋ ํจํค์ง๋? (์:
com.example.app.ui.theme)"
Save to .claude/android-skills.json (merge with existing config). Mention the file is committable so the team shares the convention.
Operating rules
- Wrap previews in the project theme resolved per the steps above. Fall back to
MaterialTheme only when nothing exists.
- Co-locate. Put preview functions in the same file as the composable they preview, below the composable. Annotate with
@Preview and prefix the function name with Preview (e.g. PreviewLoginScreen).
- Mark as private when the preview is file-local. Public preview functions are only for shared sample data.
- Always include
showBackground = true on the base preview so the surface is visible.
- Prefer official multi-preview annotations from
androidx.compose.ui.tooling.preview when available (@PreviewLightDark, @PreviewScreenSizes, @PreviewFontScale, @PreviewDynamicColors). Only define a custom multi-preview annotation when the user asks for a combination not covered by the built-ins.
- For parameterized composables generate a
PreviewParameterProvider<T> next to the preview rather than hard-coding sample data inline. Use sequenceOf(...) for the values property.
- Do not invent state. If the composable consumes a
UiState sealed class or similar, read the actual definition from the codebase before fabricating sample values.
Patterns
1. Basic preview
@Preview(showBackground = true)
@Composable
private fun PreviewGreeting() {
AppTheme {
Greeting(name = "Android")
}
}
2. Light + dark in one shot
Use the built-in annotation โ do not roll your own:
@PreviewLightDark
@Composable
private fun PreviewGreeting() {
AppTheme {
Surface { Greeting(name = "Android") }
}
}
@PreviewLightDark already sets uiMode for both modes; wrapping with Surface ensures the theme background renders.
3. Multi-config (size + font scale)
@PreviewScreenSizes
@PreviewFontScale
@Composable
private fun PreviewLoginScreen() {
AppTheme {
LoginScreen(state = LoginUiState.Idle, onSubmit = {})
}
}
4. Custom multi-preview annotation
Only create this when the built-ins do not cover the combination the user wants. Place it in ui/preview/Previews.kt:
@Preview(name = "Phone", device = "spec:width=411dp,height=891dp")
@Preview(name = "Foldable", device = "spec:width=673dp,height=841dp")
@Preview(name = "Tablet", device = "spec:width=1280dp,height=800dp")
annotation class DevicePreviews
Then apply: @DevicePreviews on the preview function.
5. PreviewParameterProvider
For composables that take a state object, generate a provider rather than crafting sample data inline:
class LoginUiStateProvider : PreviewParameterProvider<LoginUiState> {
override val values: Sequence<LoginUiState> = sequenceOf(
LoginUiState.Idle,
LoginUiState.Loading,
LoginUiState.Error(message = "Invalid credentials"),
LoginUiState.Success(userId = "u_123"),
)
}
@PreviewLightDark
@Composable
private fun PreviewLoginScreen(
@PreviewParameter(LoginUiStateProvider::class) state: LoginUiState,
) {
AppTheme {
Surface { LoginScreen(state = state, onSubmit = {}) }
}
}
6. Locale preview
@Preview(name = "ko", locale = "ko")
@Preview(name = "en", locale = "en")
@Composable
private fun PreviewWelcome() {
AppTheme { WelcomeScreen() }
}
Required dependencies
If the project does not already have them, add via the version catalog:
[libraries]
androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
dependencies {
implementation(libs.androidx.compose.ui.tooling.preview)
debugImplementation(libs.androidx.compose.ui.tooling)
}
ui-tooling must be debugImplementation only โ shipping it in release bloats the APK and exposes preview infrastructure.
Workflow
- Run
git rev-parse --show-toplevel to find the repo root, then read <root>/.claude/android-skills.json.
- Resolve the theme via the order in Configuration โ Theme resolution order. Onboard if needed.
- Read the target composable file. Identify parameters and any
UiState types it consumes.
- Pick the smallest pattern that satisfies the request:
- No parameters or trivial ones โ Pattern 1 / 2 (or
compose.defaultMultiPreview from config).
- Multiple visual configs requested โ Pattern 3 (built-ins) or Pattern 4 (custom).
- Non-trivial parameter (sealed UI state, data class, list) โ Pattern 5.
- Localization-sensitive UI โ Pattern 6.
- Place the preview based on
compose.previewLocation:
co-located (default) โ append to the composable's file, below the composable.
separate-file โ create <ComposableName>Preview.kt in the same directory.
- If
ui-tooling / ui-tooling-preview are missing from dependencies, add them.
- If the theme was discovered (not from config) and the user agreed to save it, write to
.claude/android-skills.json.
Anti-patterns to avoid
- โ Putting
ui-tooling in implementation instead of debugImplementation.
- โ Calling a
ViewModel() from inside a @Preview โ previews must not depend on DI or runtime state. Pass UI state directly.
- โ Hard-coding sample lists inline when there are 3+ variants โ use
PreviewParameterProvider instead.
- โ Re-creating
@PreviewLightDark etc. by hand when the official annotation already exists.
- โ Forgetting to wrap in the project's theme โ previews without theme do not reflect real rendering.