Sketch Lustre

In case you’re here and don’t know Sketch, take a look at sketch package!

This readme is a carbon-copy of the Sketch Lustre section in sketch readme.

Setup

Sketch focuses on the concept of generating CSS in a performant way. To do it, Sketch needs to use a cache. The cache allows to avoid repeating unneeded computations, and ensure consistency across repaints. Because the browser likes static CSS, using a cache make sure the browser will not undergo unneeded computations to recompute styles at every repaint.

If you’re using Lustre (which is strongly recommended), sketch_lustre got you. sketch_lustre exposes one entrypoint, sketch/lustre, containing everything needed to get started.

// main.gleam
import lustre
import sketch
import sketch/lustre as sketch_lustre

pub fn main() {
  // Initialise the cache. Two strategies can be used in browser, only one
  // on server-side.
  let assert Ok(cache) = sketch.cache(strategy: sketch.Ephemeral)
  // Select the output of the generated stylesheet.
  sketch_lustre.node()
  // Add the sketch CSS generation "view middleware".
  |> sketch_lustre.compose(view, cache)
  // Give the new view function to lustre runtime!
  |> lustre.simple(init, update, _)
  // And voilà!
  |> lustre.start("#app", Nil)
}

Usage

sketch_lustre exposes two modules to help you build your site, similarly to Lustre: sketch/lustre/element and sketch/lustre/element/html. The first one let you use raw element generation and exposes the Sketch Lustre Element(msg) type, that can be used (almost) interchangeably with Lustre, and element helpers, i.e. element, fragment, or even keyed.

Because a sketch_lustre view function expects an sketch/lustre/element.Element(msg) to paint, you should now write all your view functions to return Sketch elements. All Sketch elements can be instanciated with element, or with the corresponding sketch/lustre/element/html.element. An element accepts the same thing as a Lustre element, but includes a sketch.Class value as first argument. That class will be applied to the final generated element.

NB: all elements can be generated using the correct function, or using its “underscored” version. In the second case, Sketch Lustre behaves exactly like Lustre, and will not add another class. This is helpful when you want to use a simple node, without any class linked on it.

import sketch
import sketch/lustre/element
import sketch/lustre/element/html
import sketch/size.{px}

fn main_style() {
  sketch.class([
    sketch.background("red"),
    sketch.font_size(px(16)),
  ])
}

fn view(model: Int) {
  html.div(main_style(), [], [
    html.div_([], [h.text(int.to_string(model)]),
  ])
}

And you’re done! Enjoy your Lustre app, Sketch-enhanced!

Final notes

On Sketch Lustre Element

A Sketch Element(msg) is extremely similar to a Lustre Element(msg), excepted it carries styles information on top. Going from a sketch/lustre/element.Element(msg) to a lustre/element.Element(msg) is straightforward, by using sketch/lustre/element.unstyled. The opposite (going from a Lustre element to a Sketch Lustre element) is also possible by using sketch/lustre/element.styled!

Usage with Shadow DOM

In browser, Sketch can work with a Shadow DOM, in order to hide the compiled styles from the rest of the application. To do it, you can use plinth. This allows to create a ShadowRoot, to use sketch/options.shadow_root(). In the same way you can initialize the cache to render in document or in a style node, you can now use a Shadow Root to paint styles in your application!

Search Document