A specialized bottom sheet used for long-form instructions, tutorials, and support links. It features Expandable Sections to keep the interface clean while offering deep information.
We use a combination of Card and AnimatedVisibility to create smooth expansion animations.
data class InstructionSection(
val title: String,
val iconRes: Int,
val description: String? = null,
val steps: List<InstructionStep> = emptyList(),
val links: List<Pair<String, String>> = emptyList()
)@Composable
fun ExpandableGuideSection(section: InstructionSection) {
var expanded by remember { mutableStateOf(false) }
val rotation by animateFloatAsState(if (expanded) 180f else 0f)
Card(
modifier = Modifier.clickable { expanded = !expanded },
colors = CardDefaults.cardColors(
containerColor = if (expanded)
MaterialTheme.colorScheme.surfaceBright
else
MaterialTheme.colorScheme.surfaceContainerLow
)
) {
Column(modifier = Modifier.padding(16.dp)) {
// Header Row (Icon + Title + Arrow)
Row(...) {
Icon(painterResource(section.iconRes), ...)
Text(section.title, ...)
Icon(Icons.Rounded.ArrowDropDown, Modifier.rotate(rotation))
}
// Animated Content
AnimatedVisibility(visible = expanded) {
Column(modifier = Modifier.padding(top = 24.dp)) {
if (section.description != null) {
Text(section.description, ...)
}
// Render Steps with Images
section.steps.forEach { step ->
InstructionStepItem(step)
}
}
}
}
}
}To make guides clear, we use a vertical list of instructions followed by a clip and ContentScale.FillWidth image.
@Composable
private fun InstructionStepItem(step: InstructionStep) {
Column(...) {
Text(step.instruction, ...)
Image(
painter = painterResource(step.imageRes),
contentDescription = null,
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(12.dp)),
contentScale = ContentScale.FillWidth
)
}
}At the bottom of the sheet, we use a FlowRow to provide quick access to external resources like GitHub, Telegram, or Email.
FlowRow(
horizontalArrangement = Arrangement.Center,
maxItemsInEachRow = 3
) {
Button(onClick = { openGitHub() }) { ... }
OutlinedButton(onClick = { openTelegram() }) { ... }
}- Group Sections: Use a
RoundedCardContainerto wrap allExpandableGuideSectionitems for a unified look. - Lazy Loading: Since guides can be very long with many images, use
LazyColumnfor the entire sheet content to maintain performance.