Skip to content

Commit e5f1230

Browse files
committed
Render Form and Section as grouped lists
1 parent 7b0ebf1 commit e5f1230

1 file changed

Lines changed: 51 additions & 0 deletions

File tree

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

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

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ import androidx.compose.material3.DropdownMenu
3434
import androidx.compose.material3.DropdownMenuItem
3535
import androidx.compose.material3.HorizontalDivider
3636
import androidx.compose.material3.LinearProgressIndicator
37+
import androidx.compose.material3.MaterialTheme
38+
import androidx.compose.material3.Surface
3739
import androidx.compose.material3.ExperimentalMaterial3Api
3840
import androidx.compose.material3.Icon
3941
import androidx.compose.material3.IconButton
@@ -240,6 +242,10 @@ fun Render(node: ViewNode) {
240242

241243
"TabView" -> RenderTabView(node)
242244

245+
"Form" -> RenderForm(node)
246+
247+
"Section" -> RenderSection(node)
248+
243249
"List" -> RenderList(node)
244250

245251
"LazyVGrid" -> RenderGrid(node, vertical = true)
@@ -313,6 +319,51 @@ private fun RenderStepper(node: ViewNode) {
313319
}
314320
}
315321

322+
// A Form scrolls its Sections; non-Section children still render, ungrouped.
323+
@Composable
324+
private fun RenderForm(node: ViewNode) {
325+
val state = rememberScrollState()
326+
Column(modifier = node.composeModifiers().fillMaxSize().verticalScroll(state).padding(vertical = 8.dp)) {
327+
RenderChildren(node)
328+
}
329+
}
330+
331+
// An inset, rounded group: uppercase header, rows separated by dividers, footer.
332+
@Composable
333+
private fun RenderSection(node: ViewNode) {
334+
Column(modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp, vertical = 8.dp)) {
335+
node.string("header")?.let {
336+
Text(
337+
it.uppercase(),
338+
fontSize = 13.sp,
339+
color = MaterialTheme.colorScheme.onSurfaceVariant,
340+
modifier = Modifier.padding(start = 4.dp, bottom = 6.dp),
341+
)
342+
}
343+
Surface(
344+
color = MaterialTheme.colorScheme.surfaceVariant,
345+
shape = RoundedCornerShape(10.dp),
346+
modifier = Modifier.fillMaxWidth(),
347+
) {
348+
Column {
349+
val rows = node.children.filter { !it.isPresentation() }
350+
rows.forEachIndexed { index, row ->
351+
if (index > 0) HorizontalDivider()
352+
Box(modifier = Modifier.padding(horizontal = 12.dp, vertical = 10.dp)) { Render(row) }
353+
}
354+
}
355+
}
356+
node.string("footer")?.let {
357+
Text(
358+
it,
359+
fontSize = 12.sp,
360+
color = MaterialTheme.colorScheme.onSurfaceVariant,
361+
modifier = Modifier.padding(start = 4.dp, top = 6.dp),
362+
)
363+
}
364+
}
365+
}
366+
316367
// A trigger button opening a dropdown; each child Button becomes a menu item
317368
// firing its own tap callback.
318369
@Composable

0 commit comments

Comments
 (0)