Package-level declarations

Placeholders display skeleton UI whilst content is loading. They occupy the same space as the real content and cross-fade out once data is ready, reducing perceived wait time.

Use placeholders when:

  • Data loads asynchronously and the layout shape is known in advance

  • Multiple items load simultaneously and a consistent loading state is needed

Modifiers

Placeholders are applied as Modifier extensions rather than standalone composables. Each variant targets a specific content type.

Modifier.placeholder

General-purpose skeleton for any layout element. Shape defaults to SparkTheme.shapes.small. Animation is a fade (pulse in/out).

Box(
modifier = Modifier
.fillMaxWidth()
.height(48.dp)
.placeholder(visible = isLoading),
)

To override the shape, apply Modifier.clip before this modifier:

Box(
modifier = Modifier
.size(40.dp)
.clip(CircleShape)
.placeholder(visible = isLoading),
)

Modifier.textPlaceholder

Skeleton for text content. Uses SparkTheme.shapes.full (pill shape) to mirror the rounded profile of text runs. Animation is a fade.

Text(
text = username,
modifier = Modifier.textPlaceholder(visible = isLoading),
)

Apply it to every Text composable independently so each line produces its own skeleton at the correct width.

Modifier.illustrationPlaceholder

Skeleton for images and illustrations. Animation is a shimmer (radial gradient sweeping from top-start to bottom-end). Requires an explicit shape parameter.

AsyncImage(
model = url,
contentDescription = null,
modifier = Modifier
.size(128.dp)
.illustrationPlaceholder(
visible = isLoading,
shape = SparkTheme.shapes.extraLarge,
),
)

Animation modes

ModeModifierBehaviour
Fadeplaceholder, textPlaceholderColour pulses in and out (600 ms, 200 ms delay, reverses)
ShimmerillustrationPlaceholderRadial gradient sweeps across the surface (1700 ms, 200 ms delay, restarts)

All three modifiers apply a cross-fade transition between the skeleton and the real content when visible flips to false.

Full example

@Composable
fun ListingCard(listing: Listing?, isLoading: Boolean) {
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
AsyncImage(
model = listing?.imageUrl,
contentDescription = null,
modifier = Modifier
.fillMaxWidth()
.height(200.dp)
.illustrationPlaceholder(
visible = isLoading,
shape = SparkTheme.shapes.medium,
),
)
Text(
text = listing?.title.orEmpty(),
modifier = Modifier.textPlaceholder(visible = isLoading),
)
Text(
text = listing?.price.orEmpty(),
modifier = Modifier.textPlaceholder(visible = isLoading),
)
}
}

Customising colours

PlaceholderDefaults exposes @Composable functions to produce theme-aware colours for custom highlight implementations:

FunctionUsed byDefault alpha
PlaceholderDefaults.color()Base skeleton fill0.25f
PlaceholderDefaults.fadeHighlightColor()PlaceholderHighlight.fade()0.3f
PlaceholderDefaults.shimmerHighlightColor()PlaceholderHighlight.shimmer()0.3f

All three derive from SparkTheme.colors.surface and accept backgroundColor, contentColor, and alpha overrides.

Types

Link copied to clipboard

Contains default values used by Modifier.placeholder and PlaceholderHighlight.

Link copied to clipboard

A class which provides a brush to paint placeholder based on progress.

Functions

Link copied to clipboard
fun PlaceholderDefaults.color(backgroundColor: Color = SparkTheme.colors.surface, contentColor: Color = contentColorFor(backgroundColor), contentAlpha: Float = 0.25f): Color

Returns the value used as the the color parameter value on Modifier.placeholder.

Link copied to clipboard
fun PlaceholderHighlight.Companion.fade(animationSpec: InfiniteRepeatableSpec<Float> = PlaceholderDefaults.fadeAnimationSpec): PlaceholderHighlight

Creates a PlaceholderHighlight which fades in an appropriate color, using the given animationSpec.

fun PlaceholderHighlight.Companion.fade(highlightColor: Color, animationSpec: InfiniteRepeatableSpec<Float> = PlaceholderDefaults.fadeAnimationSpec): PlaceholderHighlight

Creates a Fade brush with the given initial and target colors.

Link copied to clipboard
fun PlaceholderDefaults.fadeHighlightColor(backgroundColor: Color = SparkTheme.colors.surface, alpha: Float = 0.3f): Color

Returns the value used as the the highlightColor parameter value of PlaceholderHighlight.Companion.fade.

Link copied to clipboard

Draws a skeleton UI for illustrations which is typically used whilst a image is 'loading'.

Link copied to clipboard

Draws some skeleton UI which is typically used whilst content is 'loading'.

Link copied to clipboard
fun PlaceholderHighlight.Companion.shimmer(animationSpec: InfiniteRepeatableSpec<Float> = PlaceholderDefaults.shimmerAnimationSpec, @FloatRange(from = 0.0, to = 1.0) progressForMaxAlpha: Float = 0.6f): PlaceholderHighlight

Creates a PlaceholderHighlight which 'shimmers', using a default color.

fun PlaceholderHighlight.Companion.shimmer(highlightColor: Color, animationSpec: InfiniteRepeatableSpec<Float> = PlaceholderDefaults.shimmerAnimationSpec, @FloatRange(from = 0.0, to = 1.0) progressForMaxAlpha: Float = 0.6f): PlaceholderHighlight

Creates a PlaceholderHighlight which 'shimmers', using the given highlightColor.

Link copied to clipboard
fun PlaceholderDefaults.shimmerHighlightColor(backgroundColor: Color = SparkTheme.colors.surface, alpha: Float = 0.3f): Color

Returns the value used as the the highlightColor parameter value of PlaceholderHighlight.Companion.shimmer.

Link copied to clipboard

Draws some skeleton UI which is typically used whilst content is 'loading'.