Package-level declarations

The image package provides three composables for displaying visual content: Image for remote/async images with managed loading states, Illustration for local static assets, and UserAvatar for circular profile pictures.

Image

Image loads remote or local content asynchronously via Coil and handles all loading states automatically. Unlike the standard Compose Image, it requires bounded dimensions and shows built-in placeholder states.

Image(
model = "https://example.com/photo.jpg",
contentDescription = "Product photo",
modifier = Modifier.size(200.dp),
)

The component requires bounded width and height. Wrap in a size, fillMaxWidth, or other size-constraining modifier; an unbounded Image triggers an exception via the Spark exception handler.

Loading states

Three states are rendered automatically. Each slot accepts a custom composable:

StateDefault behaviourParameter
Empty (null or blank model)Neutral icon on neutralContainer backgroundemptyIcon
LoadingShimmer placeholder animationloadingPlaceholder
Error (URL failed to load)Warning icon on errorContainer backgrounderrorIcon
Image(
model = imageUrl,
contentDescription = "Ad photo",
modifier = Modifier
.size(120.dp)
.clip(SparkTheme.shapes.medium),
emptyIcon = {
// Custom empty state
Icon(sparkIcon = SparkIcons.ImageFill, contentDescription = null)
},
errorIcon = {
// Custom error state
Icon(sparkIcon = SparkIcons.WarningFill, contentDescription = null)
},
)

The emptyIcon slot is also shown when loading fails with a null, blank, or NullRequestData model, distinguishing "no content" from a genuine network failure.

Observing state changes

Use onState to react to loading lifecycle events:

Image(
model = url,
contentDescription = "Photo",
modifier = Modifier.size(100.dp),
onState = { state ->
when (state) {
is State.Success -> analyticsTracker.imageLoaded()
is State.Error -> analyticsTracker.imageFailedToLoad()
else -> Unit
}
},
)

Content scale and alignment

contentScale and alignment mirror the standard Compose parameters and default to ContentScale.Fit / Alignment.Center.

Image(
model = url,
contentDescription = "Banner",
modifier = Modifier
.fillMaxWidth()
.height(200.dp),
contentScale = ContentScale.Crop,
alignment = Alignment.TopCenter,
)

Applying shape

Apply shape via Modifier.clip before passing to the composable:

Image(
model = url,
contentDescription = "Thumbnail",
modifier = Modifier
.size(80.dp)
.clip(SparkTheme.shapes.large),
)

Illustration

Illustration renders static local assets - bitmaps, vectors, drawables, or SparkIcons - without loading states or network access.

// From a drawable resource
Illustration(
drawableRes = R.drawable.il_onboarding,
contentDescription = "Onboarding graphic",
modifier = Modifier.size(240.dp),
)

// From a SparkIcon
Illustration(
sparkIcon = SparkIcons.Store,
contentDescription = "Store",
modifier = Modifier.size(100.dp),
)

// From a Painter
Illustration(
painter = rememberVectorPainter(MyVector),
contentDescription = null, // decorative
)

Use Illustration for design-system illustrations and marketing graphics where content is bundled with the app. Use Image for any content loaded at runtime.

UserAvatar

UserAvatar displays a circular profile picture. It uses Image internally and falls back to a profile or pro icon when no model is provided.

UserAvatar(
model = user.avatarUrl,
style = UserAvatarStyle.MEDIUM,
isPro = user.isProfessional,
isOnline = user.isOnline,
)

Sizes

StyleImage size
UserAvatarStyle.SMALL32dp
UserAvatarStyle.MEDIUM40dp
UserAvatarStyle.LARGE64dp

Online indicator

Set isOnline = true to display a green dot badge at the bottom-right of the avatar. The badge scales with the chosen UserAvatarStyle.

Pro badge

Set isPro = true to swap the fallback icon from a generic profile silhouette to a pro indicator. The pro icon is only visible when no image is loaded (empty or error state).

UserAvatar(
model = null, // shows fallback icon
style = UserAvatarStyle.LARGE,
isPro = true,
color = SparkTheme.colors.mainContainer,
)

The color parameter tints the fallback icon's background surface. Leave as Color.Unspecified to use the default neutral colour.

Types

Link copied to clipboard
Link copied to clipboard
sealed class State

The current state of the Image.

Link copied to clipboard

Functions

Link copied to clipboard
fun Illustration(painter: Painter?, contentDescription: String?, modifier: Modifier = Modifier, alignment: Alignment = Alignment.Center, contentScale: ContentScale = ContentScale.Fit, alpha: Float = DefaultAlpha, colorFilter: ColorFilter? = null)

Creates a composable that lays out and draws a given Painter. This will attempt to size the composable according to the Painter's intrinsic size. However, an optional Modifier parameter can be provided to adjust sizing or draw additional content (ex. background)

fun Illustration(imageVector: ImageVector, contentDescription: String?, modifier: Modifier = Modifier, alignment: Alignment = Alignment.Center, contentScale: ContentScale = ContentScale.Fit, alpha: Float = DefaultAlpha, colorFilter: ColorFilter? = null)

A composable that lays out and draws a given ImageVector. This will attempt to size the composable according to the ImageVector's given width and height. However, an optional Modifier parameter can be provided to adjust sizing or draw additional content (ex. background). Any unspecified dimension will leverage the ImageVector's size as a minimum constraint.

fun Illustration(sparkIcon: SparkIcon, contentDescription: String?, modifier: Modifier = Modifier, alignment: Alignment = Alignment.Center, contentScale: ContentScale = ContentScale.Fit, alpha: Float = DefaultAlpha, colorFilter: ColorFilter? = null)

Creates a composable that lays out and draws a given SparkIcon. This will attempt to size the composable according to the SparkIcon's intrinsic size (should be already normalized but some exception may still exist). However, an optional Modifier parameter can be provided to adjust sizing or draw additional content (ex. background)

fun Illustration(@DrawableRes drawableRes: Int, contentDescription: String?, modifier: Modifier = Modifier, alignment: Alignment = Alignment.Center, contentScale: ContentScale = ContentScale.Fit, alpha: Float = DefaultAlpha, colorFilter: ColorFilter? = null)

Creates a composable that lays out and draws a given android.graphics.drawable.Drawable. This will attempt to size the composable according to the android.graphics.drawable.Drawable's intrinsic size. However, an optional Modifier parameter can be provided to adjust sizing or draw additional content (ex. background)

fun Illustration(bitmap: ImageBitmap, contentDescription: String?, modifier: Modifier = Modifier, alignment: Alignment = Alignment.Center, contentScale: ContentScale = ContentScale.Fit, alpha: Float = DefaultAlpha, colorFilter: ColorFilter? = null, filterQuality: FilterQuality = DrawScope.DefaultFilterQuality)

A composable that lays out and draws a given ImageBitmap. This will attempt to size the composable according to the ImageBitmap's given width and height. However, an optional Modifier parameter can be provided to adjust sizing or draw additional content (ex. background). Any unspecified dimension will leverage the ImageBitmap's size as a minimum constraint.

Link copied to clipboard
fun Image(model: Any?, contentDescription: String?, modifier: Modifier = Modifier, onState: (State) -> Unit? = null, emptyIcon: @Composable () -> Unit = { ImageIconState(LeboncoinIcons.StrokeImage) }, errorIcon: @Composable () -> Unit = { ImageIconState( sparkIcon = LeboncoinIcons.WarningImage, color = SparkTheme.colors.errorContainer, ) }, alignment: Alignment = Alignment.Center, contentScale: ContentScale = ContentScale.Fit, alpha: Float = DefaultAlpha, colorFilter: ColorFilter? = null, filterQuality: FilterQuality = DrawScope.DefaultFilterQuality, loadingPlaceholder: @Composable () -> Unit = ImageDefaults.placeholder)

A composable that lays out and draws a given Image. This will attempt to size the composable according to the Image's given width and height. However, an optional Modifier parameter can be provided to adjust sizing or draw additional content (ex. background). Any unspecified dimension will leverage the Image's size as a minimum constraint.

Link copied to clipboard
fun SparkImage(model: Any?, contentDescription: String?, modifier: Modifier = Modifier, transform: (AsyncImagePainter.State) -> AsyncImagePainter.State = AsyncImagePainter.DefaultTransform, onState: (State) -> Unit? = null, emptyIcon: @Composable () -> Unit = { ImageIconState(LeboncoinIcons.StrokeImage) }, errorIcon: @Composable () -> Unit = { ImageIconState( sparkIcon = LeboncoinIcons.WarningImage, color = SparkTheme.colors.errorContainer, ) }, loadingPlaceholder: @Composable () -> Unit = ImageDefaults.placeholder, alignment: Alignment = Alignment.Center, contentScale: ContentScale = ContentScale.Fit, alpha: Float = DefaultAlpha, colorFilter: ColorFilter? = null, filterQuality: FilterQuality = DrawScope.DefaultFilterQuality, blurEdges: Boolean = false)
Link copied to clipboard
fun UserAvatar(modifier: Modifier = Modifier, style: UserAvatarStyle = UserAvatarStyle.SMALL, fillParentSize: Boolean = false, model: Any? = null, color: Color = Color.Unspecified, isPro: Boolean = false, isOnline: Boolean = false)