varabyte / kobweb

A modern framework for full stack web apps in Kotlin, built upon Compose HTML
https://kobweb.varabyte.com
Apache License 2.0
1.41k stars 64 forks source link

Add a way to nest style in ComponentStyle #529

Open XibalbaM opened 2 months ago

XibalbaM commented 2 months ago

Allowing to nest style in ComponentStyle, with a syntax like :

val SomeStyle by ComponentStyle {
    base {
        ...
    }
    hover {
        ...
    }
    "button" {
        ...
        hover {
            ...
        }
    }
}

Giving

.someStyle {...}
.someStyle:hover {...}
.someStyle > button {...}
.someStyle > button:hover {...}

It would allow having only a single ComponentStyle for a whole component, making it easier to make variants of it. It would also make it possible to put all the styles in one place, instead of creating a lot of variables or inlining everything. The devs that come from CSS would be less lost and the new learners would have much ease to go to “normal” HTML-CSS web dev.

Actually, there is no equivalent. The cssRule function is always interpreted as a top level call, for example :

val SomeStyle by ComponentStyle {
    cssRule("button") {
        cssRule(".active") {
            Modifier
        }
        Modifier
    }
}
// is the same as
val SomeStyle by ComponentStyle {
    cssRule("button") {
        Modifier
    }
    cssRule(".active") {
        Modifier
    }
}

In summary, this feature would allow a cleaner code style, with a clear delimitation between the content and the style, closest to the habitual web dev standards, while still offering the power of Kotlin with, for example, the extension functions.

bitspittle commented 2 months ago

Actually, there is no equivalent. The cssRule function is always interpreted as a top level call, for example :

I believe this is wrong. Based on what you want to do, the CSS rule should be cssRule("> button") and cssRule("> button:hover")

Did you try that and it didn't work?

XibalbaM commented 2 months ago

Even if it works, it's not the same thing at all. That's the entire purpose of scss : allow nesting instead of re-writing everything each time. The functionality that I'm asking is just a way to make this solution viable, by making it a lot easier to write. It doesn't allow anything new theoretically, but in fact it makes this kind of syntax usable.

bitspittle commented 2 months ago

Even if it works, it's not the same thing at all.

Sorry I don't follow. It is exactly the same thing as

.someStyle {...}
.someStyle:hover {...}
.someStyle > button {...}
.someStyle > button:hover {...}

Note that there are multiple ways to declare interesting selector relationships...

Why should we go through so much trouble to add support for only one of those selector operators? What happens if a user wants to refactor their code from direct descendent to indirect descendent?

XibalbaM commented 2 months ago

I mean it gives the same result, but the coding experience isn't the same at all. That's what I meant when I talked about scss. One of the most important purposes of scss is to bring this nested syntax instead of the vanilla one.

bitspittle commented 2 months ago

Sure, but I mentioned on the discord that SCSS is working with limitations in CSS because CSS isn't code. With Compose HTML / Kobweb, we can lean on Kotlin code for extra support, in many ways obsoleting most of the need for SCSS.

You didn't answer my question btw:

Why should we go through so much trouble to add support for only one of those selector operators? What happens if a user wants to refactor their code from direct descendent to indirect descendent?

XibalbaM commented 2 months ago

For your question we can just imagine that it uses > by default but if another operator is specified it is used. Exactly like scss The current syntax is near to CSS syntax, that's why I compare it with scss. Kobweb styling is actually exactly the same thing as normal HTML+CSS+Tailwind. We don't take advantage of kotlin functionalities. For the moment it's just harder to do anything. Implementing this and the other issue I opened would take the coding experience at the same level as normal web development, and then we will be able to take advantage of kotlin's power. For the moment it's just Tailwind with a more verbose syntax and without the additions brought by scss or postcss

bitspittle commented 2 months ago

Implementing this and the other issue I opened would take the coding experience at the same level as normal web development, and then we will be able to take advantage of kotlin's power.

This is a bold statement but you're yet to convince me of it. Maybe you can share more examples. Your original example claimed there was no cssRule equivalent to what you wanted to do, but I pointed out that was wrong.

If you really want to convince me that I'm missing something, you need to show really clear before & after code.

Keep in mind, it's not free to add the feature you're suggesting. It, like any feature, would add complexity to the codebase and API. It would take time to implement and test. You have to worry about a bunch of cases -- base support, color mode, legacy codebases. You'll have to update a ton of APIs in the codebase to support it. It's more code to maintain moving forward.

So I'd really like to understand why we would be doing it. I'm not shutting you down but it's not effective to just say stuff you believe with more intensity.

You may think I'm closing my ears to what you are saying, but I'm not. I'm open to there being a code example that will convince me that supporting nesting syntax is a clear win, and I'm not completely against the idea of nesting fundamentally. But I'm at the moment doubtful that you'll find a case that's really worth prioritizing for.

We don't take advantage of kotlin functionalities.

I'm sorry but I have to point out this is factually incorrect. There's a lot of ways that Kobweb styles lean on Kotlin-specific functionalities (all of the psuedo-element selectors, for example, and breakpoint support, and just a bunch of crazy type tricks behind the scenes you're unaware of; for example, look at CssRule.kt).

There are ways to structure your Kobweb code taking full advantage of shared modifier variables as well. You're not doing it but other codebases are.


I could be missing something! You have to show me that.

From my current point of view, you strike me as someone who is really fixated on doing something one way because you're familiar with it and not willing to do it a different way because of that. (I would bet you think the same about me).

Sometimes the same concept expresses itself differently in different environments. As a random example, at first I hated that Kotlin needed to do run { ... } to introduce a scope when Java just used { ... }. However, I have since learned why Kotlin needed to make this decision, and I am fine with it due to the constraints of the language (which here is debatably a negative but as a feature overall it is a clear win).

You may be frustrated that I'm pushing back like this, but I guarantee you, getting good at what I'm asking you to do here should benefit you in your career a lot. It certainly was a useful skill for me to learn.

bitspittle commented 1 month ago

Are you still there @XibalbaM ? I assume what I said may have been frustrating, but I didn't mean to shut you down. I'm not sure if you're planning to continue this conversation or not after my last comment.

XibalbaM commented 1 month ago

Sorry, I wanted to write something clean, but I didn't find the time. I'll probably do it in the next days.

bitspittle commented 1 month ago

No worries and no rush. Glad you're still there!

bitspittle commented 1 month ago

BTW I have been playing around with styles more as I prepare for my Droidcon talk, and I was thinking about this bug in the back of my mind. I think being able to deeply nest cssRules if technically possible could be a pretty nice feature. I will look into it after the talk.

XibalbaM commented 1 month ago

Any update ?

bitspittle commented 1 month ago

Don't expect any update on this bug for weeks. The droidcon talk is next Thursday and after that I'll be taking a bit of a break -- the amount of crunch work done in preparation for this talk is off the charts. (The talk itself is a lot of work, but the huge push to get 0.18.0 done in time for it was itself many weeks of non-stop work)

After that point, we'd very much like to explore this, and definitely would like this in 1.0, but if it runs into technical hurdles, it is not a priority, since there are workarounds and since no one else has asked for it yet.