PM-29870: Add explicit traversal order for scaffold (#6580)

This commit is contained in:
David Perez
2026-02-25 12:08:20 -06:00
committed by GitHub
parent fd6d32ec09
commit 64a79ff108

View File

@@ -34,8 +34,10 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
import androidx.compose.ui.semantics.isTraversalGroup
import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTagsAsResourceId import androidx.compose.ui.semantics.testTagsAsResourceId
import androidx.compose.ui.semantics.traversalIndex
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex import androidx.compose.ui.zIndex
import com.bitwarden.ui.platform.base.util.toDp import com.bitwarden.ui.platform.base.util.toDp
@@ -49,6 +51,14 @@ import com.bitwarden.ui.platform.model.WindowSize
import com.bitwarden.ui.platform.theme.BitwardenTheme import com.bitwarden.ui.platform.theme.BitwardenTheme
import com.bitwarden.ui.platform.util.rememberWindowSize import com.bitwarden.ui.platform.util.rememberWindowSize
private const val TRAVERSAL_INDEX_TOP_APP_BAR: Float = 0f
private const val TRAVERSAL_INDEX_CONTENT: Float = 1f
private const val TRAVERSAL_INDEX_CONTENT_MAIN: Float = 0f
private const val TRAVERSAL_INDEX_CONTENT_NAVIGATION_RAIL: Float = 1f
private const val TRAVERSAL_INDEX_SNACK_BAR: Float = 2f
private const val TRAVERSAL_INDEX_FLOATING_ACTION_BUTTON: Float = 3f
private const val TRAVERSAL_INDEX_BOTTOM_APP_BAR: Float = 4f
/** /**
* Direct passthrough to [Scaffold] but contains a few specific override values. Everything is * Direct passthrough to [Scaffold] but contains a few specific override values. Everything is
* still overridable if necessary. * still overridable if necessary.
@@ -86,18 +96,49 @@ fun BitwardenScaffold(
modifier = Modifier modifier = Modifier
.semantics { testTagsAsResourceId = true } .semantics { testTagsAsResourceId = true }
.then(other = modifier), .then(other = modifier),
topBar = topBar, topBar = {
Box(
modifier = Modifier.semantics {
isTraversalGroup = true
traversalIndex = TRAVERSAL_INDEX_TOP_APP_BAR
},
) {
topBar()
}
},
bottomBar = { bottomBar = {
if (isNavigationBarVisible) { if (isNavigationBarVisible) {
ScaffoldBottomAppBar(navigationData = navigationData) ScaffoldBottomAppBar(
navigationData = navigationData,
modifier = Modifier.semantics {
isTraversalGroup = true
traversalIndex = TRAVERSAL_INDEX_BOTTOM_APP_BAR
},
)
} }
}, },
snackbarHost = { snackbarHost = {
Box(modifier = Modifier.imePadding()) { Box(
modifier = Modifier
.semantics {
isTraversalGroup = true
traversalIndex = TRAVERSAL_INDEX_SNACK_BAR
}
.imePadding(),
) {
snackbarHost() snackbarHost()
} }
}, },
floatingActionButton = floatingActionButton, floatingActionButton = {
Box(
modifier = Modifier.semantics {
isTraversalGroup = true
traversalIndex = TRAVERSAL_INDEX_FLOATING_ACTION_BUTTON
},
) {
floatingActionButton()
}
},
floatingActionButtonPosition = floatingActionButtonPosition, floatingActionButtonPosition = floatingActionButtonPosition,
containerColor = containerColor, containerColor = containerColor,
contentColor = contentColor, contentColor = contentColor,
@@ -107,25 +148,31 @@ fun BitwardenScaffold(
modifier = Modifier modifier = Modifier
.padding(paddingValues = paddingValues) .padding(paddingValues = paddingValues)
.consumeWindowInsets(paddingValues = paddingValues) .consumeWindowInsets(paddingValues = paddingValues)
.imePadding(), .imePadding()
.semantics {
isTraversalGroup = true
traversalIndex = TRAVERSAL_INDEX_CONTENT
},
) { ) {
if (isNavigationRailVisible) { if (isNavigationRailVisible) {
ScaffoldNavigationRail(navigationData = navigationData) ScaffoldNavigationRail(
navigationData = navigationData,
modifier = Modifier.semantics {
isTraversalGroup = true
traversalIndex = TRAVERSAL_INDEX_CONTENT_NAVIGATION_RAIL
},
)
} }
Box( Box(
modifier = Modifier.run { modifier = Modifier
if (isNavigationRailVisible) { .semantics {
consumeWindowInsets( isTraversalGroup = true
insets = WindowInsets.displayCutout.only(WindowInsetsSides.Start), traversalIndex = TRAVERSAL_INDEX_CONTENT_MAIN
)
} else if (isNavigationBarVisible) {
consumeWindowInsets(
insets = WindowInsets.navigationBars.only(WindowInsetsSides.Bottom),
)
} else {
this
} }
}, .consumeWindowInsetsForMainContent(
isNavigationRailVisible = isNavigationRailVisible,
isNavigationBarVisible = isNavigationBarVisible,
),
) { ) {
Column { Column {
utilityBar() utilityBar()
@@ -220,3 +267,16 @@ private fun ScaffoldNavigationRail(
) )
} }
} }
@Composable
private fun Modifier.consumeWindowInsetsForMainContent(
isNavigationRailVisible: Boolean,
isNavigationBarVisible: Boolean,
): Modifier =
if (isNavigationRailVisible) {
consumeWindowInsets(WindowInsets.displayCutout.only(WindowInsetsSides.Start))
} else if (isNavigationBarVisible) {
consumeWindowInsets(WindowInsets.navigationBars.only(WindowInsetsSides.Bottom))
} else {
this
}