PreviewLab

fun PreviewLab(modifier: Modifier = Modifier, state: PreviewLabState = PreviewLabDefaults.state(), screenSizes: List<ScreenSize> = PreviewLabDefaults.screenSizes(), showScreenSizeField: Boolean = true, isHeaderShow: Boolean = PreviewLabDefaults.isHeaderShow(), inspectorTabs: List<InspectorTab> = PreviewLabDefaults.inspectorTabs(), contentRoot: @Composable (content: @Composable () -> Unit) -> Unit = PreviewLabDefaults.contentRoot(), enable: Boolean = PreviewLabDefaults.enable(), isInPreviewLabGalleryCardBody: Boolean = PreviewLabDefaults.isInPreviewLabGalleryCardBody(), contentGraphicsLayer: GraphicsLayer = PreviewLabDefaults.contentGraphicsLayer(), content: @Composable PreviewLabScope.() -> Unit)

PreviewLab is a powerful preview environment for Compose UI components that enables interactive development and testing. It provides dynamic field controls, event tracking, and multi-device previews to enhance the development experience.

Basic Usage

Use PreviewLab as a wrapper around your preview composables to enable interactive controls:

@Preview
@Composable
private fun MyButtonPreview() = PreviewLab {
val buttonText by fieldState { StringField("Text", "Click Me!") }
val isEnabled by fieldState { BooleanField("Enabled", true) }
val variant by fieldState { EnumField<ButtonVariant>("Variant", ButtonVariant.Primary) }

MyButton(
text = buttonText,
enabled = isEnabled,
variant = variant,
onClick = { onEvent("Button clicked") }
)
}

Key Features

Interactive Fields

  • fieldState: Creates mutable fields for interactive state management

  • fieldValue: Creates read-only fields for parameter configuration

  • Built-in field types: StringField, BooleanField, IntField, EnumField, SelectableField, etc.

Event Tracking

  • onEvent: Records user interactions and displays toast notifications

  • Events are logged in the Events tab for debugging and testing

Multi-Device Preview

  • screenSizes: Test components across different screen sizes simultaneously

  • Built-in presets for smartphones, tablets, and desktop devices

Visual Controls

  • Inspector Panel: Right sidebar with fields, events, and settings

  • Zoom and Pan: Scale and move preview content for detailed inspection

  • Device Frames: Visual device boundaries for accurate sizing

Advanced Usage

Custom PreviewLab Wrapper

Create reusable PreviewLab configurations by wrapping PreviewLab in your own Composable function:

@Composable
fun MyProjectPreviewLab(
modifier: Modifier = Modifier,
content: @Composable PreviewLabScope.() -> Unit,
) = PreviewLab(
modifier = modifier,
state = remember { PreviewLabState() },
screenSizes = ScreenSize.AllPresets,
contentRoot = { c -> MaterialTheme { c() } },
content = content,
)

@Composable
private fun MyComponentPreview() = MyProjectPreviewLab {
MyComponent()
}

Complex Field Combinations

Combine multiple fields for comprehensive testing:

PreviewLab {
val theme by fieldState { EnumField<AppTheme>("Theme", AppTheme.Light) }
val language by fieldState { SelectableField<Locale>("Language") {
choice(Locale.ENGLISH, "English", isDefault = true)
choice(Locale.JAPANESE, "日本語")
}}
val isLoading by fieldState { BooleanField("Loading State", false) }

MyApp(theme = theme, locale = language, isLoading = isLoading)
}

Parameters

Parameters

modifier

Modifier to apply to the PreviewLab container. Can be used to control size, background, padding, or other layout properties of the entire PreviewLab UI.

state

PreviewLabState instance that manages the preview's configuration and field values. Defaults to a saveable state that persists across recompositions. Override to provide custom state management or sharing state between multiple previews.

Usage examples:

// Default behavior - state persists across recompositions
PreviewLab { ... } // Uses rememberSaveable internally

// Non-persistent state - resets on every recomposition
PreviewLab(
state = remember { PreviewLabState() }
) { ... }
screenSizes

List of screen sizes to display in the preview. Controls which device form factors are available for testing. Defaults to ScreenSize.SmartphoneAndDesktops.

Usage examples:

// Default - smartphone and desktop sizes
PreviewLab { ... } // Uses ScreenSize.SmartphoneAndDesktops

// All available presets including tablets
PreviewLab(
screenSizes = ScreenSize.AllPresets
) { ... }

// Only mobile devices for focused testing
PreviewLab(
screenSizes = listOf(ScreenSize.Phone, ScreenSize.Tablet)
) { ... }

// Custom screen sizes for specific requirements
PreviewLab(
screenSizes = listOf(
ScreenSize(360.dp, 640.dp, "Small Phone"),
ScreenSize(1920.dp, 1080.dp, "Full HD Desktop")
)
) { ... }
isHeaderShow

Controls whether the PreviewLab header is visible. When set to false, hides the header controls (scale, inspector panel toggle, etc.) to provide a cleaner preview view. Defaults to true.

Usage examples:

// Default - header is visible
PreviewLab { ... } // Header shown

// Hide header for embedded preview
PreviewLab(
isHeaderShow = false
) {
MyComponent()
}
inspectorTabs

List of tabs to display in the inspector panel. Defaults to InspectorTab.defaults which shows the built-in Fields and Events tabs.

Usage examples:

// Default - Fields and Events tabs only
PreviewLab { ... } // Uses InspectorTab.defaults

// Add custom tabs alongside default tabs
PreviewLab(
inspectorTabs = InspectorTab.defaults + listOf(DebugTab)
) { ... }

// Only custom tabs (no default Fields/Events)
PreviewLab(
inspectorTabs = listOf(CustomTab1, CustomTab2)
) { ... }

// No tabs at all
PreviewLab(
inspectorTabs = emptyList()
) { ... }
contentRoot

Wrapper composable that surrounds the entire PreviewLab UI. Useful for providing custom themes, composition locals, or other global configuration.

Usage examples:

// Default - no wrapper, uses PreviewLabTheme only
PreviewLab { ... } // Uses { it() }

// Apply custom Material3 theme
PreviewLab(
contentRoot = { content ->
MaterialTheme(
colorScheme = lightColorScheme(
primary = Color.Red,
onPrimary = Color.Yellow
)
) {
content()
}
}
) { ... }

// Provide composition locals for your design system
PreviewLab(
contentRoot = { content ->
MyDesignSystem {
CompositionLocalProvider(
LocalCustomTypography provides customTypography,
LocalBranding provides myBranding
) {
content()
}
}
}
) { ... }
enable

Controls whether PreviewLab UI is enabled. When set to false, only the content is rendered without the PreviewLab wrapper (header, inspector panel, screen size controls, etc.). Defaults to !LocalInspectionMode.current, which means PreviewLab UI is disabled during Android Studio preview and enabled during normal runtime.

Usage examples:

// Default - disabled in Android Studio preview, enabled at runtime
PreviewLab { ... }

// Always enable PreviewLab UI
PreviewLab(
enable = true
) { ... }

// Always disable PreviewLab UI (only content is shown)
PreviewLab(
enable = false
) { ... }
content

Preview content lambda with PreviewLabScope receiver. Within this scope you have access to:

  • fieldState { ... }: Create mutable state fields

  • fieldValue { ... }: Create read-only parameter fields

  • onEvent(title, description?): Log events for tracking and debugging

The content will be rendered within the selected screen size constraints and can use layout modifiers like fillMaxSize() which will be bounded by the selected screen size.

contentGraphicsLayer

GraphicsLayer for capturing screenshots. Defaults to rememberGraphicsLayer().

See also

State management and persistence

Scope providing field and event functions

Device screen size definitions and presets

Throws

if screenSizes is empty


fun PreviewLab(maxWidth: Dp, maxHeight: Dp, modifier: Modifier = Modifier, state: PreviewLabState = PreviewLabDefaults.state(), showScreenSizeField: Boolean = true, isHeaderShow: Boolean = PreviewLabDefaults.isHeaderShow(), inspectorTabs: List<InspectorTab> = PreviewLabDefaults.inspectorTabs(), contentRoot: @Composable (content: @Composable () -> Unit) -> Unit = PreviewLabDefaults.contentRoot(), enable: Boolean = PreviewLabDefaults.enable(), isInPreviewLabGalleryCardBody: Boolean = PreviewLabDefaults.isInPreviewLabGalleryCardBody(), contentGraphicsLayer: GraphicsLayer = PreviewLabDefaults.contentGraphicsLayer(), content: @Composable PreviewLabScope.() -> Unit)

Convenience overload for single screen size preview.

Use this when you want to test with a specific screen dimension instead of multiple sizes. This is equivalent to calling the main PreviewLab function with a single-item screenSizes list.

@Preview
@Composable
private fun TabletPreview() = PreviewLab(
maxWidth = 1024.dp,
maxHeight = 768.dp
) {
MyResponsiveComponent()
}

Parameters

maxWidth

Maximum width constraint for the preview content

maxHeight

Maximum height constraint for the preview content

modifier

Modifier to apply to the PreviewLab container

state

PreviewLabState instance to use for this preview

isHeaderShow

Controls whether the PreviewLab header is visible

inspectorTabs

List of tabs to display in the inspector panel

contentRoot

Wrapper composable for custom themes or composition locals

enable

Controls whether PreviewLab UI is enabled. Defaults to !LocalInspectionMode.current

content

Preview content within PreviewLabScope

See also

Main PreviewLab function with multiple screen size support


fun PreviewLab(screenSize: ScreenSize, modifier: Modifier = Modifier, state: PreviewLabState = PreviewLabDefaults.state(), showScreenSizeField: Boolean = true, isHeaderShow: Boolean = PreviewLabDefaults.isHeaderShow(), inspectorTabs: List<InspectorTab> = PreviewLabDefaults.inspectorTabs(), contentRoot: @Composable (content: @Composable () -> Unit) -> Unit = PreviewLabDefaults.contentRoot(), enable: Boolean = PreviewLabDefaults.enable(), isInPreviewLabGalleryCardBody: Boolean = PreviewLabDefaults.isInPreviewLabGalleryCardBody(), contentGraphicsLayer: GraphicsLayer = PreviewLabDefaults.contentGraphicsLayer(), content: @Composable PreviewLabScope.() -> Unit)

Convenience overload for single screen size preview using a ScreenSize object.

Use this when you want to test with a specific screen size preset instead of multiple sizes. This is equivalent to calling the main PreviewLab function with a single-item screenSizes list.

@Preview
@Composable
private fun PhonePreview() = PreviewLab(
screenSize = ScreenSize.Phone
) {
MyResponsiveComponent()
}

Parameters

screenSize

The screen size to use for the preview

modifier

Modifier to apply to the PreviewLab container

state

PreviewLabState instance to use for this preview

isHeaderShow

Controls whether the PreviewLab header is visible

inspectorTabs

List of tabs to display in the inspector panel

contentRoot

Wrapper composable for custom themes or composition locals

enable

Controls whether PreviewLab UI is enabled. Defaults to !LocalInspectionMode.current

content

Preview content within PreviewLabScope

See also

Main PreviewLab function with multiple screen size support

Device screen size definitions and presets