@@ -416,6 +416,8 @@ private fun RenderResolved(node: ViewNode) {
416416
417417 " Stepper" -> RenderStepper (node)
418418
419+ " ContextMenu" -> RenderContextMenu (node)
420+
419421 " Menu" -> RenderMenu (node)
420422
421423 " DatePicker" -> RenderDatePicker (node)
@@ -894,6 +896,38 @@ private fun formatDateMillis(millis: Long): String {
894896 return format.format(java.util.Date (millis))
895897}
896898
899+ // Long-press the content to reveal a dropdown of the menu items. children are
900+ // [content..., menuItem...]; contentCount splits them.
901+ @OptIn(ExperimentalFoundationApi ::class )
902+ @Composable
903+ private fun RenderContextMenu (node : ViewNode ) {
904+ val contentCount = node.long(" contentCount" )?.toInt() ? : 0
905+ var expanded by remember { mutableStateOf(false ) }
906+ Box {
907+ Column (
908+ modifier = node.composeModifiers().combinedClickable(
909+ onClick = {},
910+ onLongClick = { expanded = true },
911+ )
912+ ) {
913+ node.children.take(contentCount).forEach { RenderChild (it) }
914+ }
915+ DropdownMenu (expanded = expanded, onDismissRequest = { expanded = false }) {
916+ for (child in node.children.drop(contentCount)) {
917+ if (child.isPresentation()) continue
918+ val onTap = child.long(" onTap" )
919+ DropdownMenuItem (
920+ text = { Text (pickerLabel(child)) },
921+ onClick = {
922+ expanded = false
923+ onTap?.let { SwiftBridge .sink.invokeVoid(it) }
924+ },
925+ )
926+ }
927+ }
928+ }
929+ }
930+
897931// A trigger button opening a dropdown; each child Button becomes a menu item
898932// firing its own tap callback.
899933@Composable
0 commit comments