Skip to content

Commit 9bd6c35

Browse files
committed
Lift toolbar items into the navigation bar
1 parent 943f25e commit 9bd6c35

1 file changed

Lines changed: 40 additions & 6 deletions

File tree

  • Demo/swiftui/src/commonMain/kotlin/com/pureswift/swiftui

Demo/swiftui/src/commonMain/kotlin/com/pureswift/swiftui/Render.kt

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import androidx.compose.foundation.lazy.LazyColumn
5757
import androidx.compose.foundation.lazy.grid.GridCells
5858
import androidx.compose.foundation.lazy.grid.LazyHorizontalGrid
5959
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
60+
import androidx.compose.material3.BottomAppBar
6061
import androidx.compose.material3.AlertDialog
6162
import androidx.compose.material3.Button
6263
import androidx.compose.material3.ButtonDefaults
@@ -419,7 +420,7 @@ private fun RenderResolved(node: ViewNode) {
419420
// Sheets and alerts ride as hidden children; the presentation layer shows
420421
// them, so the normal child loop skips them.
421422
private fun ViewNode.isPresentation(): Boolean =
422-
type == "Sheet" || type == "Alert" || type == "ConfirmationDialog"
423+
type == "Sheet" || type == "Alert" || type == "ConfirmationDialog" || type == "ToolbarItem"
423424

424425
@Composable
425426
private fun RenderChildren(node: ViewNode) {
@@ -1308,22 +1309,49 @@ private fun RenderNavStack(node: ViewNode) {
13081309
val depth = node.children.size
13091310
// cache rendered screens by index so a popped screen can animate out
13101311
val topIndex = depth - 1
1312+
val screen = node.children.getOrNull(topIndex)
1313+
val toolbar = screen?.children?.filter { it.type == "ToolbarItem" }.orEmpty()
1314+
fun placed(vararg names: String) = toolbar.filter { (it.string("placement") ?: "automatic") in names }
1315+
val leading = placed("navigationBarLeading")
1316+
// an unplaced item goes to the trailing side, as it does on iOS
1317+
val trailing = placed("navigationBarTrailing", "automatic")
1318+
val principal = placed("principal")
1319+
val bottom = placed("bottomBar")
1320+
13111321
Scaffold(
13121322
topBar = {
13131323
val title = titles.getOrNull(topIndex).orEmpty()
1314-
if (title.isNotEmpty() || depth > 1) {
1324+
if (title.isNotEmpty() || depth > 1 || toolbar.isNotEmpty()) {
13151325
TopAppBar(
1316-
title = { Text(title) },
1326+
title = {
1327+
// a principal item replaces the title outright
1328+
if (principal.isNotEmpty()) principal.forEach { RenderToolbarItem(it) }
1329+
else Text(title)
1330+
},
13171331
navigationIcon = {
1318-
if (depth > 1) {
1319-
IconButton(onClick = { onPop?.let { SwiftBridge.sink.invokeVoid(it) } }) {
1320-
Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back")
1332+
Row(verticalAlignment = Alignment.CenterVertically) {
1333+
if (depth > 1) {
1334+
IconButton(onClick = { onPop?.let { SwiftBridge.sink.invokeVoid(it) } }) {
1335+
Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back")
1336+
}
13211337
}
1338+
leading.forEach { RenderToolbarItem(it) }
13221339
}
13231340
},
1341+
actions = { trailing.forEach { RenderToolbarItem(it) } },
13241342
)
13251343
}
13261344
},
1345+
bottomBar = {
1346+
if (bottom.isNotEmpty()) {
1347+
BottomAppBar {
1348+
Row(
1349+
verticalAlignment = Alignment.CenterVertically,
1350+
modifier = Modifier.fillMaxWidth().padding(horizontal = 12.dp),
1351+
) { bottom.forEach { RenderToolbarItem(it) } }
1352+
}
1353+
}
1354+
},
13271355
) { padding ->
13281356
AnimatedContent(
13291357
targetState = topIndex,
@@ -1420,6 +1448,12 @@ private fun RenderTabView(node: ViewNode) {
14201448
}
14211449
}
14221450

1451+
// A toolbar item's content, lifted out of the screen body into the bar.
1452+
@Composable
1453+
private fun RenderToolbarItem(item: ViewNode) {
1454+
item.children.forEach { RenderChild(it) }
1455+
}
1456+
14231457
// Sheets and alerts ride as hidden children of a screen node; present them
14241458
// when the screen carries the corresponding flag.
14251459
@OptIn(ExperimentalMaterial3Api::class)

0 commit comments

Comments
 (0)