11# Sketch
22
3- Sketch is a small module providing CSS-in-Gleam in its simpler form.
4- Sketch does not try to add complicated API on top of CSS. If you have CSS
5- knowledge, you'll feel right at home, with all the niceties offered by
6- Sketch, i.e. type-checking of sizes and push-to-browser stylesheets of your
7- classes, as well as SSR support.
3+ Sketch is a module providing CSS-in-Gleam in its simpler form. Sketch does not
4+ try to add complicated API on top of CSS. If you have CSS knowledge, you'll feel
5+ right at home, with all the niceties offered by Sketch, i.e. type-checking of
6+ sizes and push-to-browser stylesheets of your classes, as well as SSR support.
87
98Sketch has currently only one run mode: directly in your browser to leverage on
10- all abilities of the JS runtime.
11- It also allows you to build two types of CSS classes: dynamic ones, changing
12- over time , and static ones, compiled once and for all, and reused during the
9+ all abilities of the JS runtime. It also allows you to build three types of CSS
10+ classes: dynamic ones, changing over time, static ones, compiled once at each
11+ render , and memoized ones, compiled once and for all, and reused during the
1312entire lifetime of the application, just like classic CSS stylesheets.
1413
1514Sketch is thought to interact nicely with [ Lustre] ( https://hexdocs.pm/lustre/ ) ,
1615but can also be used directly in your vanilla Gleam application or in your
1716fully-featured application. This should probably only be considered to create
18- custom framework or to integrate Sketch in your favorite framework, because Sketch
19- has its own lifecycle to render styles. More informations can be found in the docs.
17+ custom framework or to integrate Sketch in your favorite framework, because
18+ Sketch has its own lifecycle to render styles. More informations can be found in
19+ the docs.
20+
21+ Sketch targets both the JS and the BEAM ecosystem. You can use it transparently
22+ no matter the target you're using. Sketch works in frontend, backend, SSR, SSG,
23+ with OTP actors or on Node. While sketch tries to be transparent, it does not
24+ compromise with performances, and tries to leverage on every abilities of the
25+ different platforms (and uses a custom renderer both for BEAM and JS, to ensures
26+ sparkling performances in your browser)!
27+
28+ The rest of this README will focus to get you started quickly with a lustre
29+ example, and some details on the available functions. If you want to know more
30+ on how sketch is working, how to use lustre with SSR or SSG, heads up to the
31+ documentation directly! Bonus: if you're using server components, just follow
32+ this guide, everything will be working directly!
2033
2134## Installation
2235
@@ -30,18 +43,23 @@ gleam add sketch
3043## Setup
3144
3245If you're using Lustre (which is strongly recommended), you can just use the
33- [ ` sketch/lustre.setup ` ] ( https://hexdocs.pm/sketch/sketch/lustre.html#setup ) function
34- and [ ` sketch/lustre.compose ` ] ( https://hexdocs.pm/sketch/sketch/lustre.html#compose ) function.
35-
36- Otherwise, you have to follow the lifecycle of Sketch, and use the three low-level
37- functions [ ` create_cache ` ] ( https://hexdocs.pm/sketch/sketch.html#create_cache ) ,
38- [ ` prepare ` ] ( https://hexdocs.pm/sketch/sketch.html#prepare ) and [ ` render ` ] ( https://hexdocs.pm/sketch/sketch.html#render ) .
39- Create the cache with [ ` create_cache ` ] ( https://hexdocs.pm/sketch/sketch.html#create_cache )
40- and before every repaint of your frontend, call [ ` prepare ` ] ( https://hexdocs.pm/sketch/sketch.html#prepare ) .
41- After the repaint, synchronously, call [ ` render ` ] ( https://hexdocs.pm/sketch/sketch.html#render ) ,
42- and let the magic happen in your browser. Heads up in the docs for more details.
43-
44- ## Example with Lustre
46+ [ ` sketch/lustre.setup ` ] ( https://hexdocs.pm/sketch/sketch/lustre.html#setup )
47+ function and
48+ [ ` sketch/lustre.compose ` ] ( https://hexdocs.pm/sketch/sketch/lustre.html#compose )
49+ function.
50+
51+ Otherwise, you have to follow the lifecycle of Sketch, and use the three
52+ low-level functions
53+ [ ` create_cache ` ] ( https://hexdocs.pm/sketch/sketch.html#create_cache ) ,
54+ [ ` prepare ` ] ( https://hexdocs.pm/sketch/sketch.html#prepare ) and
55+ [ ` render ` ] ( https://hexdocs.pm/sketch/sketch.html#render ) . Create the cache with
56+ [ ` create_cache ` ] ( https://hexdocs.pm/sketch/sketch.html#create_cache ) and before
57+ every repaint of your application, call
58+ [ ` prepare ` ] ( https://hexdocs.pm/sketch/sketch.html#prepare ) . After the repaint,
59+ synchronously, call [ ` render ` ] ( https://hexdocs.pm/sketch/sketch.html#render ) ,
60+ and let the magic happen. Heads up in the docs for more details.
61+
62+ ## Example with Lustre — Frontend
4563
4664``` gleam
4765import gleam/int
@@ -126,11 +144,13 @@ fn view(model: Model) {
126144
127145## Compiling static classes
128146
129- Sketch exposes a single function [ ` class ` ] ( https://hexdocs.pm/sketch/sketch.html#class )
130- allowing you to build your class. The first time your function is called, the
131- corresponding styles will be compiled into CSS rules, and pushed in your browser
132- or your SSR stylesheet. Every time you'll call the function in the future, no
133- computation will be done, the class name will be returned, thanks to memoization.
147+ Sketch exposes a single function
148+ [ ` class ` ] ( https://hexdocs.pm/sketch/sketch.html#class ) allowing you to build
149+ your class. The first time your function is called, the corresponding styles
150+ will be compiled into CSS rules, and pushed in your browser or your ` <style> `
151+ stylesheet. Every time you'll call the function during the render, no
152+ computation will be done, the class name will be returned, thanks to virtual
153+ stylesheet.
134154
135155``` gleam
136156import sketch
@@ -146,14 +166,23 @@ fn my_class() -> String {
146166
147167## Compiling dynamic classes
148168
149- Sketch exposes another function [ ` dynamic ` ] ( https://hexdocs.pm/sketch/sketch.html#dynamic )
150- allowing you to build a dynamic class, changing over time. Each time the function
151- is called, the properties in the declaration will be compiled into CSS, the previous
152- class will be wiped from the browser, and the new one will pushed.
153-
154- An ID * should be provided* at the moment, due to a limitation of the runtime, and
155- the limitations of the compilation. Until a workaround is found, be careful to
156- provide a unique id for your dynamic class, to avoid overlap with other classes.
169+ Sketch exposes another function
170+ [ ` dynamic ` ] ( https://hexdocs.pm/sketch/sketch.html#dynamic ) allowing you to build
171+ a dynamic class, changing over time. The first time the function is called, the
172+ properties in the declaration will be compiled into CSS, and a class with the
173+ name of the ID will be pushed in the browser. When a class with the same ID is
174+ found once again during the render, it will be kept, and reused. ` dynamic `
175+ allows you to build different dynamic classes, with different ID. When you're
176+ generating the ID, if it does not exists in the stylesheet, it will be pushed in
177+ it, and kept at least till the next render. While a ` class ` function generates
178+ _ one_ class at every render, a ` dynamic ` function generates _ multiple_ classes
179+ at every render.
180+
181+ An ID _ should be provided_ at the moment, because the runtime is unable to
182+ distinguish between the dynamic classes, or at a high cost during computations:
183+ finding the ID of the new class to generate _ is_ a hard task by itself. While a
184+ solution is awaited to be found, be careful to provide a unique id for your
185+ dynamic class.
157186
158187``` gleam
159188import gleam/bool
@@ -173,11 +202,21 @@ fn my_dynamic_class(is_column: Bool) -> String {
173202}
174203```
175204
205+ ## Memoizing a class
206+
207+ Sketch exposes a way to memoize a class:
208+ [ ` memo ` ] ( https://hexdocs.pm/sketch/sketch.html#memo ) . ` memo ` allows to keep a
209+ generated class _ for ever_ . When called on a class, sketch will preserves the
210+ class for ever, and will includes the class in every render, as long as the
211+ virtual stylesheet exists. This allows to skip all computations work for every
212+ class computations later, and to increase performances render. _ Be careful, a
213+ class marked as ` memo ` will be then considered immutable and can never change._
214+
176215## Using media queries and pseudo-selectors
177216
178- Because we're in CSS-in-Gleam, we can leverage on the full CSS power,
179- contrarily to inline styling. This mean we can use media queries and pseudo-selectors!
180- You only need to call the proper functions, and sketch will take care of the rest.
217+ Because we're in CSS-in-Gleam, we can leverage on the full CSS power, contrarily
218+ to inline styling. This mean we can use media queries and pseudo-selectors! You
219+ only need to call the proper functions, and sketch will take care of the rest.
181220
182221``` gleam
183222import sketch
@@ -230,19 +269,22 @@ The example above will be compiled to the following CSS.
230269## Usage with Lustre — Details
231270
232271[ Lustre] ( https://hexdocs.pm/lustre/ ) is the recommended framework for frontend
233- development in Gleam. Sketch tries to simplify as much the development with Lustre.
234- That's why Sketch exposes a [ ` setup ` ] ( https://hexdocs.pm/sketch/sketch/lustre.html#setup )
235- function. This function creates a cache, and returns it. Another function,
236- [ ` compose ` ] ( https://hexdocs.pm/sketch/sketch/lustre.html#compose ) allows to easily
237- compose the cache with the view function of Lustre.
238- It acts as a "hook" (lustre does not officially supports hooks right now): it setups
239- the cache before the view, and render the stylesheet after the view has executed.
240- It tries to be side-effect free in the ` view ` in order to have a predictable render
241- in Lustre, and stick with the Elm architecture mindset.
242-
243- Once setuped, you can use classes in your Lustre views: [ ` to_lustre() ` ] ( https://hexdocs.pm/sketch/sketch.html#to_lustre ) .
244- Just use it in place of [ ` to_class_name() ` ] ( https://hexdocs.pm/sketch/sketch.html#to_class_name )
245- to get a Lustre attribute and use it in your views.
272+ development in Gleam. Sketch tries to simplify as much the development with
273+ Lustre. That's why Sketch exposes a
274+ [ ` setup ` ] ( https://hexdocs.pm/sketch/sketch/lustre.html#setup ) function. This
275+ function creates a cache, and returns it. Another function,
276+ [ ` compose ` ] ( https://hexdocs.pm/sketch/sketch/lustre.html#compose ) allows to
277+ easily compose the cache with the view function of Lustre. It acts as a "hook"
278+ (lustre does not officially supports hooks right now): it setups the cache
279+ before the view, and render the stylesheet after the view has executed. It tries
280+ to be side-effect free in the ` view ` in order to have a predictable render in
281+ Lustre, and stick with the Elm architecture mindset.
282+
283+ Once setuped, you can use classes in your Lustre views:
284+ [ ` to_lustre() ` ] ( https://hexdocs.pm/sketch/sketch.html#to_lustre ) . Just use it in
285+ place of
286+ [ ` to_class_name() ` ] ( https://hexdocs.pm/sketch/sketch.html#to_class_name ) to get
287+ a Lustre attribute and use it in your views.
246288
247289``` gleam
248290import gleam/list
@@ -275,22 +317,23 @@ fn my_other_view(model: Bool) {
275317## Use with Shadow DOM
276318
277319Sketch can work with a Shadow DOM, in order to hide the compiled styles from the
278- rest of the application. To do it, you can use [ ` plinth ` ] ( https://github.com/CrowdHailer/plinth ) .
279- This allows to create a ` ShadowRoot ` , to use
320+ rest of the application. To do it, you can use
321+ [ ` plinth ` ] ( https://github.com/CrowdHailer/plinth ) . This allows to create a
322+ ` ShadowRoot ` , to use
280323[ ` sketch/options.shadow_root() ` ] ( https://hexdocs.pm/sketch/sketch/options.html#shadow_root ) .
281- In the same way you can initialize the cache to render in document or in a ` style ` node,
282- you can now use a Shadow Root to paint styles in your application!
324+ In the same way you can initialize the cache to render in document or in a
325+ ` style ` node, you can now use a Shadow Root to paint styles in your application!
283326
284327## Some opinions on properties
285328
286- A lot of properties are accessible directly through the ` sketch ` package.
287- But with time, some could be added, and new features for existing features
288- can appear. That's why sketch will never try to be on your way: at any time
289- you can access [ ` property() ` ] ( https://hexdocs.pm/sketch/sketch.html#property ) ,
290- which allows you to push any arbitrary property in a class. Another thing is ç
291- that sketch will always let you access raw, low-level properties. If you're
292- trying to use something like ` sketch.width("auto") ` and the property does not
293- support String, look for a variant with an underscore (` _ ` ), it should fullfill
294- your needs, like ` sketch.width_("auto") ` !
295- In case something is missing or a property does not have its underscore
296- alternative, [ open an issue — or better, a PR — on the repo!] ( https://github.com/ghivert/sketch )
329+ A lot of properties are accessible directly through the ` sketch ` package. But
330+ with time, some could be added, and new features for existing features can
331+ appear. That's why sketch will never try to be on your way: at any time you can
332+ access [ ` property() ` ] ( https://hexdocs.pm/sketch/sketch.html#property ) , which
333+ allows you to push any arbitrary property in a class. Another thing is ç that
334+ sketch will always let you access raw, low-level properties. If you're trying to
335+ use something like ` sketch.width("auto") ` and the property does not support
336+ String, look for a variant with an underscore (` _ ` ), it should fullfill your
337+ needs, like ` sketch.width_("auto") ` ! In case something is missing or a property
338+ does not have its underscore alternative,
339+ [ open an issue — or better, a PR — on the repo!] ( https://github.com/ghivert/sketch )
0 commit comments