ghivert / sketch

A CSS-in-Gleam package, made to work with frontend, backend, with your favorite framework!
https://hexdocs.pm/sketch/
MIT License
48 stars 6 forks source link

best way to compose styles #8

Open brunoti opened 7 months ago

brunoti commented 7 months ago

Let's say I want to create a custom function called size. The value passed to it should be applied in the same way tailwind does: sets width and height.

I tried to do this:

pub fn size(size: Size) -> Style(a, b) {
  sketch.class([
    sketch.width(size),
    sketch.height(size),
  ])
  |> sketch.compose()
}

But it ended memoizing the function and always returned the same class on lustre.

Returning a list and spreading/appending is also a possible way. But I did it like this:

pub fn size(size: Size) -> Style(a, b) {
  sketch.dynamic("size-" <> size.to_string(size), [
    sketch.width(size),
    sketch.height(size),
  ])
  |> sketch.compose()
}

// Then we can sketch.class([some_style, size(px(10))])

How bad is it? Is there a better way to do it? I think we should have some compose examples on the docs.

ghivert commented 7 months ago

Your second option is the right way to go in your case (if you don't want to change the size of the node in the future)! Unfortunately, due to the fact that I can't patch the lustre renderer (yet? I'm considering this option seriously), a call to class will always compile something static. You should think of class exactly like a class declaration in CSS: immutable. That's why the package exposes a dynamic function, which can render a custom class, which changes every time the render turns, but at the cost of defining an ID, to avoid duplicated classes in the stylesheet.

For your specific problem, I would have define the styles differently:

fn base_style() {
  sketch.class([some_style])
}

pub fn size(size: Size) -> Class {
  sketch.dynamic("size-" <> size.to_string(size), [
    sketch.width(size),
    sketch.height(size),
    sketch.compose(base_style),
  ])
}

// Then you can use html.div([sketch.to_lustre(size(s))], []).
// That will output
// <div class="base_style size"></div>

That way, you inherit from static styling (base_style) and can still modify the size afterwards.

brunoti commented 7 months ago

Thanks for the feedback! Do you want to keep this issue to add something to the docs? Otherwise, my question was answered and you can close it.

ghivert commented 7 months ago

I'll keep it open few days if you're not against it, before doing a meta issue for the documentation