README.md

# monks_of_style

[![Package Version](https://img.shields.io/hexpm/v/monks_of_style)](https://hex.pm/packages/monks_of_style)
[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/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](https://github.com/csstree/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

```sh
gleam add monks_of_style@1
```

```gleam
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 `inherit` works 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](/monks_of_style_generator/README.md)

The lengths type in [monks_of_style.gleam](./src/monks_of_style.gleam) are hand-rolled.
I may add more of these later.

## Alternatives

- [Sketch](https://hexdocs.pm/sketch/index.html) is more bespoke devex along
  some dimensions, but doesn't have as much type safety.