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
15.9k stars 1.16k forks source link

@Preview panel background in the IntelliJ plugin not respecting light/dark system setting #3898

Open alexfacciorusso opened 10 months ago

alexfacciorusso commented 10 months ago

Describe the bug

The @Preview annotated function seems to be rendered by the androidx.compose.desktop.ui.tooling.preview.runtime.NonInteractivePreviewFacade respecting the system's dark/light setting.

The IntelliJ plugin, adds a white background underneath the resulting image. See org.jetbrains.compose.desktop.ide.preview.ui.PreviewPanel#paintComponent function:

  override fun paintComponent(g: Graphics) {
      super.paintComponent(g)

      when (val state = myState.get()) {
          is PreviewPanelState.Image -> {
              val (image, dimension) = state
              val w = dimension.width
              val h = dimension.height
              g.color = Color.WHITE // <------------ here
              g.fillRect(0, 0, w, h)
              g.drawImage(image, 0, 0, w, h, null)
          }
          is PreviewPanelState.Error -> {
              myStatusText.paint(this, g)
          }
      }
  }

The result is that if my system is in dark mode, the Composable gets rendered in dark mode, but the Panel in IntelliJ shows it over a white background, making it potentially not visible/not legible and in general, rendering the Preview unuseful.

Currently, the @Preview annotation for desktop does not allow forcing dark or light mode, and, to add to the whole, LocalInspectionMode is also not usable to work around the issue (see bug https://github.com/JetBrains/compose-multiplatform/issues/2852).

Affected platforms Select one of the platforms below:

If the bug is Android-only, report it in the Jetpack Compose tracker

Versions

To Reproduce

  1. Create a Kotlin Desktop JVM project and only include the following code:
@Composable
@Preview
fun Preview() {
    Text(if (isSystemInDarkTheme()) "System is Dark" else "System is Light")
}
  1. Switch the Windows theme to Dark mode.
  2. Render the preview (via the Gutter button or otherwise)
  3. the background of the preview will be white and the text will say "System is Dark"
  4. Switch the Windows theme to Light mode
  5. Render the preview (via the Gutter button or otherwise)
  6. the background of the preview will be still white and the text will say "System is Light"

Expected behavior

TBD. Maybe if the system's dark mode is detected the background should be dark/black otherwise white. Or the @Preview annotation should be able to override dark mode. To be discussed.

Screenshots

image image

Additional context

alexfacciorusso commented 10 months ago

A workaround could be to manually put a coloured box or surface underneath the previewed content, but I believe that should be handled by the Preview itself.

eymar commented 10 months ago

a possible workaround:

import org.jetbrains.skiko.currentSystemTheme

@Preview
@Composable
fun Abc() {
    Text(currentSystemTheme.name)
}

It didn't work for me on Ubuntu though. it printed - UKNOWN. Perhaps, it works on Windows.

alexfacciorusso commented 10 months ago

In case it may be of any help to whoever comes here for this bug, I have created this library as a workaround: https://github.com/alexfacciorusso/compose-previewer

In future, I might think of writing a wrapper of the IntelliJ Preview plugin to use it via an annotation.

okushnikov commented 2 weeks ago

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