A lightweight, reusable UI component built with Jetpack Compose Multiplatform for displaying beautiful and responsive empty states across Android, Desktop, and Web platforms.
- 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.
- 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
- Explore the full UI experience in our Compose UI Showcase App
- Watch the tutorial on YouTube: Compose Multiplatform Empty State Preview
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)
}
}
}
}
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.
Contributions are welcome! Please open an issue or submit a pull request for any improvements or bug fixes.