You can use AnimatedContent composable to achieve this. Simply it holds more than one state and you can give different layouts to each state.

Here is a sample code.
data class BottomNavItem(
val title: String,
val icon: ImageVector
)
private val navItems = listOf(
BottomNavItem(
"Dashboard",
Icons.Outlined.Info
),
BottomNavItem(
"Browse",
Icons.Outlined.Search
),
BottomNavItem(
"Profile",
Icons.Outlined.Person
)
)
@OptIn(ExperimentalAnimationApi::class)
@Composable
fun AnimatedContentChange() {
var selectedItemIndex by rememberSaveable { mutableStateOf(0) }
NavigationBar(modifier = Modifier.fillMaxWidth()) {
navItems.forEachIndexed { index, item ->
Box(
modifier = Modifier
.weight(1F)
.fillMaxHeight()
.clickable {
selectedItemIndex = index
}, contentAlignment = Alignment.Center
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterVertically)
) {
val selected = selectedItemIndex == index
AnimatedContent(selected, transitionSpec = {
slideInVertically { if (selected) -it else it } with slideOutVertically { if (selected) it else -it }
}) { isSelected ->
Box(
modifier = Modifier
.padding(vertical = 2.dp)
.size(36.dp)
.clip(RoundedCornerShape(8.dp))
.background(if (isSelected) Color.Blue else Color.LightGray),
contentAlignment = Alignment.Center
) {
Icon(
imageVector = item.icon,
contentDescription = null,
tint = if (isSelected) Color.White else Color.Blue,
modifier = Modifier.fillMaxSize(.5F)
)
}
}
Text(text = item.title)
}
}
}
}
}