Skip to content

BoltUIX/compose-multiplatform-empty-state

Repository files navigation

compose-multiplatform-empty-state

Compose Multiplatform Kotlin License

A lightweight, reusable UI component built with Jetpack Compose Multiplatform for displaying beautiful and responsive empty states across Android, Desktop, and Web platforms.

What is an Empty State?

  • An empty state is a UI design pattern used when there's no content to display, such as no internet connection, empty search results, or first-time app usage.
  • It typically includes an illustration, a title, a subtitle explaining the situation, and an optional call-to-action button (e.g., retry).
  • Purpose: Guides users, reduces frustration, and encourages next steps. Improves UX by making "nothing" informative and engaging.

Features

  • Cross-platform support (Android / Desktop / Web)
  • Lightweight and customizable
  • Plug-and-play empty UI screens
  • Responsive design out-of-the-box
  • Optional icon, title, description, and action button

Preview

Empty State Preview

Implementation

For the full source code, check the files in this repository (e.g., NoInternetScreen.kt). You can clone and run the project to test it directly.

Here's a key snippet of the main composable function:

@Composable
fun NoInternetScreen(
    title: String = stringResource(Res.string.no_internet_title),
    subtitle: String = stringResource(Res.string.no_internet_subtitle),
    imageRes: Painter = painterResource(Res.drawable.empty_state_no_internet_red),
    modifier: Modifier = Modifier,
    onRetry: () -> Unit = {}
) {
    val (alphaAnim, scaleAnim) = animateFadeAndScale()

    BoxWithConstraints(
        modifier = modifier
            .fillMaxSize()
            .background(MaterialTheme.colorScheme.background)
            .padding(NoInternetConstants.PADDING)
    ) {
        val isLandscape = maxWidth > maxHeight

        val layoutModifier = Modifier
            .fillMaxSize()
            .alpha(alphaAnim)
            .scale(scaleAnim)

        if (isLandscape) {
            Row(
                modifier = layoutModifier,
                verticalAlignment = Alignment.CenterVertically,
                horizontalArrangement = Arrangement.SpaceEvenly
            ) {
                ImageSection(imageRes)
                TextSection(title, subtitle, onRetry)
            }
        } else {
            Column(
                modifier = layoutModifier,
                horizontalAlignment = Alignment.CenterHorizontally,
                verticalArrangement = Arrangement.Center
            ) {
                ImageSection(imageRes)
                Spacer(modifier = Modifier.height(NoInternetConstants.TEXT_SPACING * 2))
                TextSection(title, subtitle, onRetry)
            }
        }
    }
}

Usage

To use the NoInternetScreen in your project, call the composable function:

NoInternetScreen(
    onRetry = { /* Handle retry action */ }
)

Customize as needed by passing title, subtitle, image, or modifier.

Resources

Contributing

Contributions are welcome! Please open an issue or submit a pull request for any improvements or bug fixes.

Releases

No releases published

Packages

No packages published