Skeleton Loading¶
Skeleton loading informs users that the data is being loaded. A screen with skeleton loading placeholders can help reduce the perceived wait time and get users ready for the content. We provide skeleton loading placeholders for app teams to create a transition screen during loading.
Using Skeleton Loading¶
There are two steps involved in using skeleton loading:
- Enable the skeleton loading for composable objects
- Develop a triggering or controlling mechanism for the placeholder
Skeleton loading can be used as a modifier on a component level using a modifier or by using a PlaceHolder.
Skeleton Loading Modifiers¶
There are three kinds of modifiers:
- Text
- Square
- Chart
Text Style Modifier¶
A text style modifier is used on single line or multi-line components. The modifier used for this is fioriSkeletonGrayedTextAnimated. The code snippet below shows how to enable the skeleton loading:
Text("My sample text", modifier = Modifier.fioriSkeletonGrayedTextAnimated())
Squared or Shaped Modifier¶
This modifier is fioriSkeletonGrayedSquareAnimated. The code snippet below shows how to create a circle-shaped skeleton indicator. The clip modifier clips the box and provides a shape, then the fioriSkeletonGrayedSquareAnimated modifier applies the skeleton to that shape. The order of these modifiers matters. For example, if there is a clipping shape, apply that modifier before the skeleton loading modifier. We recommend using skeletonloading as the last modifier.
Box(modifier = Modifier.clip(shape = CircleShape)
.width(100.dp)
.height(100.dp)
.fioriSkeletonGrayedSquareAnimated()
)
Chart Style Modifier¶
This modifier is specifically designed to be used for charts. The developer can specify a drawable resource to be placed at the center of the skeleton. If the resource is not specified, a default image of R.drawable.ic_sap_icon_horizontal_combination_chart is used.
The following example shows how to use the chart style modifier:
Box(modifier = Modifier
.width(100.dp)
.height(100.dp)
.fioriSkeletonGrayedSquareAnimated()
).fioriSkeletonGrayedChartAnimated( id = R.drawable.ic_sap_icon_picture)
Skeleton Loading Placeholders¶
If you need to completely replace the composable with a placeholder skeleton, use this approach.
To use a placeholder, enclose your composable unit with a placeholder call : PlacePlaceHolder. This takes the name of a predefined placeholder, of which there are 12, listed below.
For example, the following example replaces the composable code with genericPlaceHolder.
PlacePlaceHolder(genericPlaceHolder) {
//Composable code
}
The following is the list of placeholders.
mobileCardPlaceHolderSmall
The mobile card small placeholder has the following visual aspect:

mobileCardPlaceHolderMedium
The mobile card medium placeholder has the following visual aspect:

mobileCardPlaceHolderLarge
The mobile card large placeholder has the following visual aspect:

objectHeaderPlaceHolder
The object header placeholder has the following visual aspect:

objectCellPlaceHolder
The object cell placeholder has the following visual aspect:

objectCardPlaceHolder
The object card placeholder has the following visual aspect:

genericPlaceHolder
The generic placeholder has the following visual aspect:

dataTablePlaceHolder
The data table placeholder has the following visual aspect:

kpiNumericPlaceHolderSmall
The KPI numeric placeholder (small) has the following visual aspect:

kpiNumericPlaceHolderLarge
The KPI numeric placeholder (large) has the following visual aspect:

kpiProgressPlaceHolderSmall
The KPI progress placeholder (small) has the following visual aspect:

kpiProgressPlaceHolderLarge
The KPI progress placeholder (large) has the following visual aspect:

Triggering Skeleton Loading¶
Skeleton loading is triggered by some event that indicates the readiness of data. For this purpose, the developer needs to implement a triggering mechanism.
This is done by defining an implementation of SkeletonLoading. Developers can customize the subclass and pass the trigger through a composable local provider.
Subclassing Skeleton Loading¶
The following snippet shows how to implement a subclass of skeleton loading. It is not necessary to use LaunchedEffect, but this is used here simply to indicate that this section should not be in a composable thread.
data class SkeletonLoadingInYourProgram(val loading: Boolean) :SkeletonLoading() {
@Composable
override fun loadData() : SkeletonLoading {
isLoading = true
LaunchedEffect (Unit){
//Have your logging to make data ready here
isLoading = false
}
return this
}
}
Providing the Trigger Composables¶
The trigger is provided to your composable using a local composable provider. Enclose your code as shown in the following code snippet:
CompositionLocalProvider(LocalSkeletonLoading provides SkeletonLoadingInYourProgram(loading = false).loadData()) {
//Your composable UI should be enclosed here
}