Closed Norlock closed 1 week ago
Hi!
The API is very much in progress at the time of writing, and I'm looking for the best we can find. Currently, I adopted the idea of placing the styles in first argument, explaining the need for sketch.class
. I went from different use cases.
Earlier versions had a to_lustre
function, allowing you to write things like
pub fn my_styles() {
sketch.class([sketch.background("red")])
|> sketch.to_lustre
}
pub fn my_elem() {
html.div([my_styles()], children])
}
It was great, but side-effectful. It's not the Lustre way. After huge discussions with the rest of the community, the decision to drop side-effects to provide a more reliable and simpler codebase has been taken.
I went to an API with styles injected at the end, like
fn my_component(attrs, children) {
sketch_html.div(attrs, children, [
sketch.background("red"),
])
}
fn my_elem() {
my_component([], children)
}
It was rather pretty, but inlining styles was not always happy, and especially, it break the implicit rule of both Lustre and Gleam to put the main argument in first position, to support chaining with pipes.
Currently we have that very gleam-ish API, to chain function calls like
fn my_component(attrs, children) {
sketch.class([sketch.background("red")])
|> sketch_html.div(attrs, children)
}
fn my_elem() {
my_component([], children)
}
Because you'll probably write the styles directly in the class, and pipe it (because it's really better formatted like that in my opinion), adding sketch.class
is not so much of a burden. It allows to have nice type-checking, and to define code like
fn red_background() -> sketch.Class {
sketch.class([sketch.background("red")])
}
fn my_component(attrs, children) {
red_background()
|> sketch_html.div(attrs, children)
}
fn my_elem() {
my_component([], children)
}
So you can easily reuse the class by leveraging on sketch.compose
. You don't need to manage the merging of styles yourself. CSS does it for you by composing classes directly. That's an API I rather like. Choosing between generating the styles, or reusing common classes is a matter of situations.
For example, you can think of defining buttons with composition for instance:
fn button_base() {
sketch.class([
sketch.appearance("none"),
sketch.border("none"),
sketch.font("sans-serif"),
])
}
fn button_primary() {
sketch.class([
sketch.compose(button_base()),
sketch.background("red"),
sketch.color("white"),
])
}
fn button_secondary() {
sketch.class([
sketch.compose(button_base()),
sketch.background("green"),
sketch.color("white"),
])
}
pub type Variant {
Primary
Secondary
}
pub fn button(variant: Variant, text: String) {
case variant {
Primary -> button_primary()
Secondary -> button_secondary()
}
|> html.button([], [html.text(text)])
}
html.div_
is more a hack than anything else. Sometimes you want to drop an item which is present only for the DOM, and you don't want to style it. It's more a try than anything else.
I don't receive that many feedbacks: I think I'm my main user of the package currently. We're using it daily in our apps, so I'm often trying to improve the code styling. As of now I'm rather happy with the state of the API and the package, but for v4, I'm wondering how to define the API, and if I should even keep sketch.compose
for example. With more users, more use cases, and more adoption, we could see different way to write styles, and find the best one.
I also see that way of writing sketch.class
a simple way to interact with the rest of the ecosystem. If you want to share your styles across nakai
, redraw
, lustre
or even plain CSS, you can by simply writing classes.
By the way, it's simple to write the function how you want, you can just write your own your_package/sketch/lustre/element/html
and steal function from sketch_lustre
, position the styles where you want, and you're good to go. They're just functions, you can do whatever you want. sketch_lustre
is more a try to standardise its usage on Lustre, and provide an out-of-the-box usable package. I'd see absolutely no problem to vendor the package and modify the modules, or write your own module if you dislike the API or if you want to explore new ways to define API. Exploration is really valuable, and I'd like to see how people experiment with Sketch!
Closing this issue because of inactivity. Feel free to answer to continue the discussion, I'll reopen the issue.
Isn't it better to just ask for a list of styles and wrap those inside a sketch.class inside the library? In that case also the html.div([], .... ) can just check if the list is empty and not add the class so you don't need to use both html.div and html.div_.
Keep up the good work