```Box { Box { } }``` The inner box has a bunch of...
# compose
z
Copy code
Box { Box { } }
The inner box has a bunch of focusable, scrollable and clickable elements. I want to disable all of those, while still allowing the outer box to be clickable. How do I do that? More details in 🧵
This is what Ive thrown at the outer box modifier, and it almost works, with some edge-cases that I cant figure out: ⚠️ If there are any clickable elements in the inner box, those take predecence over the outer box clickable. This is expected, however.. if I truly block the inner box interactions using
pointerInput(Unit) { .. }
then either: (1) no click events come through at all, and/or (2) if the box duo is part of a LazyColumn, you can no longer scroll the LazyColumn by touching the boxes, which is unexpected in terms of UX. I dont know if it makes sense putting it like this, but Id prefer the blocking of events to only happen downstream from the boxes. That is, you cant interact with their contents (downstream) but you can still use them to scroll a parent container (upstream).
Copy code
@Stable
private fun Modifier.disableFocus() =
    focusProperties {
        canFocus = false
    }.clearAndSetSemantics {
        focused = false
    }

@Stable
private fun Modifier.disableScroll() =
    nestedScroll(
        object : NestedScrollConnection {
            override fun onPreScroll(
                available: Offset,
                source: NestedScrollSource,
            ) = available
        },
    )

@Stable
private fun Modifier.disableInteraction() =
    pointerInput(Unit) { 
        awaitPointerEventScope {
            while (true) {
                awaitPointerEvent().run {
                    changes.forEach(PointerInputChange::consume)
                }
            }
        }
    }
And the full code looks like this:
Copy code
Box {
                    Box(
                        Modifier
                            .blur(config)
                            .clickable(onClick)
//                            .disableInteraction()
                            .disableScroll()
                            .disableFocus(),
                    ) {
                        content()
                    }

                    Box(Modifier.align(alignment)) {
                        teaser()
                    }
                }
Got it working by adding an overlay between the content & teaser w/ a clickable. I havent fully tested this on all devices, but this seems to properly block descendants (in content) from focus, scroll & clicks. Which is exactly what I wanted!
Copy code
Box {
    Box(
        modifier = Modifier.blur(config).disableScroll().disableFocus(),
        content = { content() },
    )

    Box(Modifier.matchParentSize().clickable(onClick))

    Box(
        modifier = Modifier.align(alignment),
        content = { teaser() },
    )
}