Open andyburris opened 1 year ago
Hey Andy, thanks for using Kobweb and taking the time to think about and draft this!
I'll send back a quick response now but just to let you know I'll keep thinking about this. Apologies if I miss some nuance in my fast reply.
By the way, your timing is great -- we are actively thinking about the "inline styles required to support sizes" problem. One thing we are thinking about is integrating KSP into Kobweb's compile time pipeline (this wasn't available when I started Kobweb, see also this old ass bug). This could give us more power that will enable us to do more clever things that the current Gradle plugins approach alone cannot.
Here are a few of my high level thoughts (given the current state of Kobweb):
by SilkThemeStyle.base
idea you are proposing here)All that said, I can see if you're just working on your own site that having access to breakpoints and color modes from within the same component style can be great for quick prototyping.
Supporting custom tokens is, as far as I can tell, not possible yet. I think the first pass would be to figure out and integrate KSP, which is something that I'm actively thinking about right now. Maybe it will enable something like this, but even if not, it should still help the project compile faster, in theory, while giving us the power to resolve types at compile time.
P.S. I'll also read through the Panda CSS docs to get a better feel of the full feature-set that they support. P.P.S. If you're not in the Discord, feel free to join if you want to hash ideas out in there as well.
(Apologies for the close / reopen, that was a misclick)
To add to what @bitspittle said about StyleVariables, there is currently a 3rd option for a defined set of breakpoint-reliant sizes:
val SizeVar by StyleVariable<CSSLengthValue>()
val ThemeStyle by ComponentStyle {
base {
Modifier.setVariable(SizeVar, 8.px)
}
Breakpoint.SM {
Modifier.setVariable(SizeVar, 10.px)
}
Breakpoint.MD {
Modifier.setVariable(SizeVar, 12.px)
}
}
val DemoStyle by ComponentStyle.base {
Modifier.size(SizeVar.value())
}
// in @App (or any other composable)
Surface(
ThemeStyle.toModifier()//...
)
That said, this approach still has its limits:
val DemoStyle by ComponentStyle.base {
Modifier.color(if (colorMode.isDark) Colors.Black else Colors.White)
}
Sizes(sm = 8.px, md = 12.px, /*...*/)
.Speaking more broadly however, I do like the idea of some sort of token system, for the reasons you mentioned as well as potentially easier customization of Silk-provided components/styles/sizes. As mentioned, this would likely require some internal changes (KSP), but I think something similar to what CSS-in-JS libraries offer is possible and worth pursuing.
Thank you for the responses! I'm going to try to bullet point my thoughts in approximately the order they appear:
Modifier
, so that if a token based off of colorMode
was used in one Modifier
, and a token based off breakpoint
was used in another Modifier
that they'd be generated as separate styles.
palette
and tokens
corresponding to colorMode
and breakpoint
--would force that orthogonality? Though then that would break the shadows example where the user really does want both parameters in one token. StyleVariable
option, which seems interesting, though as y'all explained there are definitely some negative considerations also.
Modifier.padding(theme.padding.sm)
, and the large variant might have a Modifier.padding(theme.padding.md)
. Then both would be able for use on both platforms, with responsive styles. On the other hand, if a user wanted two static switch sizes (and to generally use the large variant on desktop and the small one on mobile but not always), that would be a task for rememberBreakpoint()
+ hardcoded variants (without tokens).colorMode
.I'm going to keep playing around with these options to see if I come up with any new ideas, and will be interested to see how the KSP exploration turns out. Thank you guys for your thoughts on this!
As a quick aside, it may be useful to look at the generated code to demystify what Kobweb is doing.
In your project, where I'm assuming your Kobweb stuff lives under a site
folder:
../gradlew :site:kobwebGen
build/generated/kobweb/src/jsMain/kotlin/main.kt
In order to generate that code, Kobweb needs to scan your codebase and find the right lines to put in there, which it currently does by searching your code using fairly limited parsed information.
With KSP, we should have a lot more power to identify the appropriate lines of code to collect and register in your final generated main file.
Really glad to have you thinking about this. We'll definitely be in touch about the KSP stuff. I'm pretty sure it's something we'll be tackling in the near future.
We just got a huge KSP refactoring in, so we plan to revisit this issue. We set it to 1.0 because if we get it working before then, we'll also be able to apply it to our own widget code in a bunch of places. But this might be a soft 1.0, that could potentially slip if it had to.
Hi! I've been using Kobweb on a project of mine, and have run into some annoyances while creating styles that I think could be solved by a token API similar to the one that exists in Panda CSS (and many other CSS-in-JS libraries). First I'll outline a draft for what this kind of API could look like, then what the problems it solves are.
Draft API
The first (and could be only in a minimal implementation) step would be to include the current
breakpoint
inside aComponentStyle
block much like the currentcolorMode
. With that, a theme object could be constructed in each style, and the tokens could be used in the styles:(This wouldn't replace the traditional method of using breakpoints in styles, but would be an alternative.)
The next step would be to create a wrapper around
CustomStyle
so that the user doesn't have to create the theme object each time. This could be done by default for aSilkTheme
, which the user could then copy if they wanted to make their own version:The base
SilkTheme
could include sensible defaults for spacing, font sizes, etc. (and those should be customizable in@InitSilk
just like thepalette
), but it should be clear that a custom theme object could include colors, spacing, radii, sizes, font sizes, shadows, and anything else the user wants.What it solves
Currently, if the user wants to have a defined set of breakpoint-reliant sizes (or font sizes, radii, etc.), they have two options. One is to use
rememberBreakpoint()
and only ever include their sizes in inline styles, and the other is to manually deal with the breakpoints on every style:Neither of these are super convenient, and they create an entirely separate method for thinking about theming since the methods for using the
SilkPalette
are quite different. So, putting all of that data into one central theme definition would help streamline the entire theming process. Finally, this is a first draft of the API, so I'd love to hear any thoughts/changes people would like to see.