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

Inline CSS variables are not properly applied #2702

Closed MM2-0 closed 1 week ago

MM2-0 commented 1 year ago

Have a look at the following example:

@Composable
fun Demo() {
    Style(DemoStyles)
    Div({
        classes(DemoStyles.container)
        style {
            DemoStyles.color(Color.red)
        }
    }) {
        Text("Hello World")
    }
}

object DemoStyles : StyleSheet() {
    val color by variable<CSSColorValue>()

    val container by style {
        backgroundColor(color.value())
    }
}

This produces the following markup:

<div class="DemoStyles-container" style="color: red;">Hello World</div>

The expected output is:

<div class="DemoStyles-container" style="--color: red;">Hello World</div>

As you can see, the -- is missing, which turns the variable into a standard CSS property. When I move the DemoStyles.color(Color.red) down to the stylesheet, everything works as expected, so the issue only occurs in inline styles.

Workaround:

        property("--${DemoStyles.color.name}", Color.red)
bitspittle commented 1 year ago

Just throwing in my own 2 cents, as a +1 to this bug.

I finally just started looking into supporting variables in my own project, and I thought it was my fault at first that inline variables weren't working.

Here's an even simpler example that I believe should work:

Div(attrs = {
   style {
      variable("testvar", 10.px)
   }
})

This should generate the element:

<div style="--testvar: 10px" />

but it drops the variable in this case, generating just:

<div />

See also: https://ishadeed.com/article/css-variables-inline-styles/

waveduke commented 1 year ago

Same here

Expected: After applying a variable color, when getting the variable it should return that color (Background should be blue) Actual: The variable returns nothing or the default value even if you applied another color before (Background is red)

fun main() {
    renderComposableInBody {
        SomeComposable()
    }
}

@Composable
fun SomeComposable() {
    Style(MyStyle)

    Div({
        classes(MyStyle.myDiv)
    }) {
        Text("SomeComposable")
    }
}

private object MyVariables {
    val contentBackground by variable<CSSColorValue>()
}

private object MyStyle : StyleSheet() {
    val myDiv by style {
        MyVariables.contentBackground.value(Color.blue)
        backgroundColor(MyVariables.contentBackground.value(Color.red))
    }
}
Screenshot 2023-05-05 at 12 11 03
bitspittle commented 1 year ago

I ended up reimplementing keyframe styling logic in my own project. I can confirm that the first comment's workaround works, just use property("--$name", ...) instead of the documented method for specifying variable values.

If your project isn't that far into using Compose HTML, you might consider taking a look at my project Kobweb, since it seems like Compose HTML isn't receiving fixes very quickly, and by being a layer on top of theirs I can fix things before they do: https://github.com/varabyte/kobweb#css-variables

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.