@@ -103,6 +103,8 @@ import androidx.compose.material3.TextButton
103103import androidx.compose.material3.TopAppBar
104104import androidx.compose.material.icons.Icons
105105import androidx.compose.material.icons.automirrored.filled.ArrowBack
106+ import androidx.compose.material.icons.filled.KeyboardArrowDown
107+ import androidx.compose.material.icons.filled.KeyboardArrowUp
106108import androidx.compose.material.icons.filled.Add
107109import androidx.compose.material.icons.filled.Check
108110import androidx.compose.material.icons.filled.Close
@@ -351,6 +353,8 @@ private fun RenderResolved(node: ViewNode) {
351353 }
352354 }
353355
356+ " DisclosureGroup" -> RenderDisclosureGroup (node)
357+
354358 " Label" -> RenderLabel (node)
355359
356360 " Link" -> RenderLink (node)
@@ -629,6 +633,42 @@ private fun RenderLabel(node: ViewNode) {
629633 }
630634}
631635
636+ // A tappable header (label + chevron) over collapsible content. Expansion is
637+ // interpreter-local unless a binding is present, in which case the tap
638+ // round-trips through Swift like any other control.
639+ @Composable
640+ private fun RenderDisclosureGroup (node : ViewNode ) {
641+ val labelCount = node.long(" labelCount" )?.toInt() ? : 0
642+ val onToggle = node.long(" onToggle" )
643+ val bound = node.props.containsKey(" isExpanded" )
644+
645+ var localExpanded by remember(node.id) { mutableStateOf(false ) }
646+ val expanded = if (bound) node.string(" isExpanded" ) == " true" else localExpanded
647+
648+ Column (modifier = node.composeModifiers().fillMaxWidth()) {
649+ Row (
650+ verticalAlignment = Alignment .CenterVertically ,
651+ modifier = Modifier .fillMaxWidth().clickable {
652+ if (bound) onToggle?.let { SwiftBridge .sink.invokeBool(it, ! expanded) }
653+ else localExpanded = ! localExpanded
654+ }.padding(vertical = 6 .dp),
655+ ) {
656+ Row (modifier = Modifier .weight(1f )) {
657+ node.children.take(labelCount).forEach { RenderChild (it) }
658+ }
659+ Icon (
660+ imageVector = if (expanded) Icons .Filled .KeyboardArrowUp else Icons .Filled .KeyboardArrowDown ,
661+ contentDescription = if (expanded) " Collapse" else " Expand" ,
662+ )
663+ }
664+ if (expanded) {
665+ Column (modifier = Modifier .fillMaxWidth().padding(start = 12 .dp)) {
666+ node.children.drop(labelCount).forEach { RenderChild (it) }
667+ }
668+ }
669+ }
670+ }
671+
632672private fun ViewNode.isPresentation (): Boolean =
633673 type == " Sheet" || type == " Alert" || type == " ConfirmationDialog" || type == " ToolbarItem"
634674
0 commit comments