JetBrains / compose-multiplatform

Compose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.
https://jetbrains.com/lp/compose-multiplatform
Apache License 2.0
16.2k stars 1.17k forks source link

Popup event handling, tooltip shouldn't intercepts clicks #1545

Closed igordmn closed 1 month ago

igordmn commented 2 years ago

Compose 1.0.0

Tooltip exists for only one purpose - to give the hint (or additional information) about the element.

If tooltip overlays the element, it should still allow to click the element, and don't intercept mouse event itself

import androidx.compose.foundation.TooltipArea
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application

fun main() = application {
    Window(onCloseRequest = ::exitApplication) {
        Box(Modifier.fillMaxSize(), contentAlignment = Alignment.BottomEnd) {
            TooltipArea(
                tooltip = {
                    Text("Button", modifier = Modifier.background(Color.LightGray).padding(8.dp))
                }
            ) {
                Button(onClick = {}) {
                    Text("Button")
                }
            }
        }
    }
}

https://user-images.githubusercontent.com/5963351/144711029-96d0df97-b5cd-4b13-8190-64b6e0553018.mp4

On the video we see that when the cursor is over the tooltip, we can't press on Button.

With current Popup's it is impossible to implement, because we can't create Popup's which pass events to the underlying content.

Introducing something like hoverable: Boolean isn't the right approach to fix the issue, because we would only fix one issue, and make Popup behavior more complex. Popup can have non-hoverable parts and hoverable parts. See for example context menu in Chrome, it doesn't intercept clicks, when we click on this part of the popup (red dot): image

Also, we probably should deprecate focusable: Boolean property, because it have narrow application, and have some unexpected behavior. The initial purpose of it was to allow to popup components to take focus (like TextField). But why, for example, this property also decides how popup should be closed with the mouse. Instead, focusability should be enabled by default, and shouldn't affect how pointer events passes down to the component tree.

Instead of focusable/hoverable we should probably route all events based on component Modifier's. I.e. by default, it passes down all events (for all passes of PointerEventPass), and only if Popup contains some component that consumes event (like clickable), it shouldn't pass event further.

During the redesign, we should keep in mind that we need to maintain backward compatibility.

okushnikov commented 2 months ago

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.