
Enhances interactive previews by collecting `@Preview` annotations and creating a playground for UI components, allowing value manipulation, event visualization, and layout exploration.
[FIXME WIP DOCUMENTATION]
English | 日本語 | Sample | Documentation | DeepWiki
[!IMPORTANT] This project is still a work in progress, and its API is unstable and may change without any notice. Using this plugin for a hobby project is fine, but we do not recommend using it for production projects yet.
Compose Preview Lab turns @Preview into an interactive Component Playground. You can pass parameters to components, enabling more than just static snapshots—making manual testing easier and helping new developers understand components faster. Compose Multiplatform is supported.
The easiest way to get started. The starter module bundles all core modules (core, field, ui, preview-lab, gallery) into a
single dependency.
plugins {
// ⭐️ Add KSP for collect `@Preview`
id("com.google.devtools.ksp") version "<ksp-version>"
// ⭐️ Add Compose Preview Lab Gradle plugin
id("me.tbsten.compose.preview.lab") version "<compose-preview-lab-version>"
}
kotlin {
sourceSets {
commonMain.dependencies {
// ⭐️ Add Compose Preview Lab starter (includes all core modules)
implementation("me.tbsten.compose.preview.lab:starter:<compose-preview-lab-version>")
}
}
}
dependencies {
// ⭐️ Add Compose Preview Lab KSP plugin
val composePreviewLabKspPlugin =
"me.tbsten.compose.preview.lab:ksp-plugin:<compose-preview-lab-version>"
add("kspCommonMainMetadata", composePreviewLabKspPlugin)
// each platform
add("kspAndroid", composePreviewLabKspPlugin)
add("kspJvm", composePreviewLabKspPlugin)
add("kspJs", composePreviewLabKspPlugin)
add("kspWasmJs", composePreviewLabKspPlugin)
// iOS targets (if needed)
// add("kspIosX64", composePreviewLabKspPlugin)
// add("kspIosArm64", composePreviewLabKspPlugin)
// add("kspIosSimulatorArm64", composePreviewLabKspPlugin)
}If you need fine-grained control over dependencies, you can add individual modules instead of the starter.
plugins {
// ⭐️ Add KSP for collect `@Preview`
id("com.google.devtools.ksp") version "<ksp-version>"
// ⭐️ Add Compose Preview Lab Gradle plugin
id("me.tbsten.compose.preview.lab") version "<compose-preview-lab-version>"
}
kotlin {
sourceSets {
commonMain.dependencies {
// ⭐️ Add individual modules as needed
implementation("me.tbsten.compose.preview.lab:starter:<compose-preview-lab-version>")
}
}
}
dependencies {
// ⭐️ Add Compose Preview Lab KSP plugin
val composePreviewLabKspPlugin =
"me.tbsten.compose.preview.lab:ksp-plugin:<compose-preview-lab-version>"
add("kspCommonMainMetadata", composePreviewLabKspPlugin)
// each platform
add("kspAndroid", composePreviewLabKspPlugin)
add("kspJvm", composePreviewLabKspPlugin)
add("kspJs", composePreviewLabKspPlugin)
add("kspWasmJs", composePreviewLabKspPlugin)
// iOS targets (if needed)
// add("kspIosX64", composePreviewLabKspPlugin)
// add("kspIosArm64", composePreviewLabKspPlugin)
// add("kspIosSimulatorArm64", composePreviewLabKspPlugin)
}Available modules:
| Module | Description |
|---|---|
core |
Core types and interfaces (CollectedPreview, PreviewLabPreview, etc.) |
field |
Field API for interactive parameter editing (StringField, IntField, etc.) |
ui |
Common UI components used by PreviewLab |
preview-lab |
PreviewLab Composable with Field and Event integration |
gallery |
PreviewLabGallery for displaying preview lists |
🚨 WARNING
Pure Android projects (projects that do not use the Kotlin Multiplatform) can also use the Compose Preview Lab, but their functionality is severely limited, such as not being able to browse on the web, and it may be difficult to see the benefits of the Compose Preview Lab. However, the Consider using Compose Multiplatform even if your project is Android-only. I believe that this concept is not limited to Compose Preview Lab, but should be the norm for all projects using Compose in the future.
plugins {
// ⭐️ add ksp for collect `@Preview`
id("com.google.devtools.ksp") version "<ksp-version>"
// ⭐️ Add Compose Preview Lab Gradle plugin
id("me.tbsten.compose.preview.lab") version "<compose-preview-lab-version>"
}
dependencies {
// ⭐️ Use starter for simple setup (or individual modules if needed)
implementation("me.tbsten.compose.preview.lab:starter:<compose-preview-lab-version>")
ksp("me.tbsten.compose.preview.lab:ksp-plugin:<compose-preview-lab-version>")
}Use PreviewLab Composable and functions such as ***Field() onEvent() to enhance Preview's
Interactive mode.
You can collect @Preview
and create an interactive Playground
like Figma's Component Playground.
@Preview
@Composable
private fun MyButtonPreview() = PreviewLab {
MyButton(
text = fieldValue { StringField("Click Me") },
onClick = { onEvent("MyButton.onClick") },
)
}| Field | Event |
|---|---|
fieldValue { ***Field(defaultValue) } Allows you to manually change values in the Preview. This allows you to say goodbye to the problem of PreviewParameterProvider displaying a large number of Previews and increasing the cognitive load. |
When an event occurs in Preview (common examples: Button#onClick, HomeScreen#onIntent), call onEvent() to visualize the occurrence of the event. |
| TODO image | TODO image |
A solution similar to Compose Preview Lab is Storytale from Jetbrains. The table below shows the differences between the two.
(The following information is current as of 28.6.2025)
| Compose Preview Lab | Storytale | |
|---|---|---|
| Cataloging UI Component | ✅ | ✅ |
| View source code | ❌ Future support is under consideration. |
✅ |
| Ease of preparing the Composable catalog | ✅ Just enclose @Preview in PreviewLab { }. |
You must have the code in the ***Stories source set. Existing code with @Preview must be migrated. |
| Parameter of your own type | ✅ By implementing a custom Field, you can freely customize the UI, including the operation UI. (see). It also provides useful utilities such as SelectableField. |
❌ Not supported. Following the source code shows that there is a non-zero chance of support in the future. |
[FIXME WIP DOCUMENTATION]
English | 日本語 | Sample | Documentation | DeepWiki
[!IMPORTANT] This project is still a work in progress, and its API is unstable and may change without any notice. Using this plugin for a hobby project is fine, but we do not recommend using it for production projects yet.
Compose Preview Lab turns @Preview into an interactive Component Playground. You can pass parameters to components, enabling more than just static snapshots—making manual testing easier and helping new developers understand components faster. Compose Multiplatform is supported.
The easiest way to get started. The starter module bundles all core modules (core, field, ui, preview-lab, gallery) into a
single dependency.
plugins {
// ⭐️ Add KSP for collect `@Preview`
id("com.google.devtools.ksp") version "<ksp-version>"
// ⭐️ Add Compose Preview Lab Gradle plugin
id("me.tbsten.compose.preview.lab") version "<compose-preview-lab-version>"
}
kotlin {
sourceSets {
commonMain.dependencies {
// ⭐️ Add Compose Preview Lab starter (includes all core modules)
implementation("me.tbsten.compose.preview.lab:starter:<compose-preview-lab-version>")
}
}
}
dependencies {
// ⭐️ Add Compose Preview Lab KSP plugin
val composePreviewLabKspPlugin =
"me.tbsten.compose.preview.lab:ksp-plugin:<compose-preview-lab-version>"
add("kspCommonMainMetadata", composePreviewLabKspPlugin)
// each platform
add("kspAndroid", composePreviewLabKspPlugin)
add("kspJvm", composePreviewLabKspPlugin)
add("kspJs", composePreviewLabKspPlugin)
add("kspWasmJs", composePreviewLabKspPlugin)
// iOS targets (if needed)
// add("kspIosX64", composePreviewLabKspPlugin)
// add("kspIosArm64", composePreviewLabKspPlugin)
// add("kspIosSimulatorArm64", composePreviewLabKspPlugin)
}If you need fine-grained control over dependencies, you can add individual modules instead of the starter.
plugins {
// ⭐️ Add KSP for collect `@Preview`
id("com.google.devtools.ksp") version "<ksp-version>"
// ⭐️ Add Compose Preview Lab Gradle plugin
id("me.tbsten.compose.preview.lab") version "<compose-preview-lab-version>"
}
kotlin {
sourceSets {
commonMain.dependencies {
// ⭐️ Add individual modules as needed
implementation("me.tbsten.compose.preview.lab:starter:<compose-preview-lab-version>")
}
}
}
dependencies {
// ⭐️ Add Compose Preview Lab KSP plugin
val composePreviewLabKspPlugin =
"me.tbsten.compose.preview.lab:ksp-plugin:<compose-preview-lab-version>"
add("kspCommonMainMetadata", composePreviewLabKspPlugin)
// each platform
add("kspAndroid", composePreviewLabKspPlugin)
add("kspJvm", composePreviewLabKspPlugin)
add("kspJs", composePreviewLabKspPlugin)
add("kspWasmJs", composePreviewLabKspPlugin)
// iOS targets (if needed)
// add("kspIosX64", composePreviewLabKspPlugin)
// add("kspIosArm64", composePreviewLabKspPlugin)
// add("kspIosSimulatorArm64", composePreviewLabKspPlugin)
}Available modules:
| Module | Description |
|---|---|
core |
Core types and interfaces (CollectedPreview, PreviewLabPreview, etc.) |
field |
Field API for interactive parameter editing (StringField, IntField, etc.) |
ui |
Common UI components used by PreviewLab |
preview-lab |
PreviewLab Composable with Field and Event integration |
gallery |
PreviewLabGallery for displaying preview lists |
🚨 WARNING
Pure Android projects (projects that do not use the Kotlin Multiplatform) can also use the Compose Preview Lab, but their functionality is severely limited, such as not being able to browse on the web, and it may be difficult to see the benefits of the Compose Preview Lab. However, the Consider using Compose Multiplatform even if your project is Android-only. I believe that this concept is not limited to Compose Preview Lab, but should be the norm for all projects using Compose in the future.
plugins {
// ⭐️ add ksp for collect `@Preview`
id("com.google.devtools.ksp") version "<ksp-version>"
// ⭐️ Add Compose Preview Lab Gradle plugin
id("me.tbsten.compose.preview.lab") version "<compose-preview-lab-version>"
}
dependencies {
// ⭐️ Use starter for simple setup (or individual modules if needed)
implementation("me.tbsten.compose.preview.lab:starter:<compose-preview-lab-version>")
ksp("me.tbsten.compose.preview.lab:ksp-plugin:<compose-preview-lab-version>")
}Use PreviewLab Composable and functions such as ***Field() onEvent() to enhance Preview's
Interactive mode.
You can collect @Preview
and create an interactive Playground
like Figma's Component Playground.
@Preview
@Composable
private fun MyButtonPreview() = PreviewLab {
MyButton(
text = fieldValue { StringField("Click Me") },
onClick = { onEvent("MyButton.onClick") },
)
}| Field | Event |
|---|---|
fieldValue { ***Field(defaultValue) } Allows you to manually change values in the Preview. This allows you to say goodbye to the problem of PreviewParameterProvider displaying a large number of Previews and increasing the cognitive load. |
When an event occurs in Preview (common examples: Button#onClick, HomeScreen#onIntent), call onEvent() to visualize the occurrence of the event. |
| TODO image | TODO image |
A solution similar to Compose Preview Lab is Storytale from Jetbrains. The table below shows the differences between the two.
(The following information is current as of 28.6.2025)
| Compose Preview Lab | Storytale | |
|---|---|---|
| Cataloging UI Component | ✅ | ✅ |
| View source code | ❌ Future support is under consideration. |
✅ |
| Ease of preparing the Composable catalog | ✅ Just enclose @Preview in PreviewLab { }. |
You must have the code in the ***Stories source set. Existing code with @Preview must be migrated. |
| Parameter of your own type | ✅ By implementing a custom Field, you can freely customize the UI, including the operation UI. (see). It also provides useful utilities such as SelectableField. |
❌ Not supported. Following the source code shows that there is a non-zero chance of support in the future. |