monks_of_style
Overview
Typesafe CSS in Gleam with an eye for usage with Lustre’s List(#(String, String) styles attribute.
All types and values are generated by parsing the csstree grammar. All credit goes to the maintainers of that project. Mistakes are probably mine. So long as that project is maintained, this one can stay up to date with the spec with minimal maintenance.
Features
– minimally verbose styles in your code – typesafe keys and values (when possible) – Raw string escape hatch for every property – CSS variable functions for every property – integrate with LSP completions – docstrings scraped from MDN for LSP help – No external adapter or shimming needed to work with lustre.
Install and Use
gleam add monks_of_style@1
import lustre
import lustre/attribute
import lustre/element/html
import monks_of_style.{Percent, Rem}
import monks/background_color
import monks/color
import monks/display
import monks/flex_direction
import monks/margin
import monks/padding
import monks/width
pub fn main() {
let app =
lustre.element(html.div(
[
attribute.styles([
// Standard lustre tuple attributes when you need max control
#("--override-color", "cyan"),
// raw strings when you need custom values for typesafe keys
background_color.raw("maroon"),
// css design token variables on any prop
color.var("override-color"),
// typesafe key value pairs
display.flex,
flex_direction.column,
margin.auto_,
// typesafe lengths and sizes
width.length(Percent(50.0)),
padding.length(Rem(2.0)),
]),
],
[
html.text("hello world"),
],
))
let assert Ok(_) = lustre.start(app, "#app", Nil)
Nil
}
Further documentation can be found at https://hexdocs.pm/monks_of_style.
Drawbacks
- I gennerally like the devex, but having to import every property from a
separate module drives me nuts. The reason I did it like this is codegen; I
didn’t want to deal with property values conflicting between multiple types.
E.g. the value
inheritworks with everything. Open to suggestion for improving this but only if it doesn’t make the usage syntax works. - Aggregate properties that can take multiple keywords (e.g.
background,border) don’t really make sense in this model, but the generator attempts to generate keywords for them anyway. I may remove these altogether or try to figure out how to generate wrapper functions that accept multiple values.
Development
Most of the code in this project is generated, so development happens in the monks_of_style_generator
The lengths type in monks_of_style.gleam are hand-rolled. I may add more of these later.
Alternatives
- Sketch is more bespoke devex along some dimensions, but doesn’t have as much type safety.