davesnx/styled-ppx

Compose rules with cx/css

davesnx opened this issue · 1 comments

I keep seeing this pattern, which tries to compose styles:

let headerName = style ([ fontWeight `normal ] @ Font.body)

I was thinking about having a way to do it inside styled-ppx (cx/styled.) like the following:

let font_body_16 = [%css {| font-size: 16px; |}];
let line_height_22 = [%css {|line-height: 22px;|}]

let cellHeader =
  [%cx {|
    $(font_body_16);
    $(line_height_22);
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-bottom: 12px;
    border-bottom: 1px solid $(Color.Border.primary);
  |}]

Interpolation right now works on values (and selectors), adding this would make interpolation possible on properties. I'm assuming only one property but it can be extended to deal with more than one.

Support multiple declarations on [%css ""]

(* Current implementation *)
css: string -> Css.Rule
[%css "display: block"] -> display(`block) (* Css.Rule *)

cx: array(Css.Rule) -> string (* hashed className *)
[%cx [| [%css "display: block"] |]] -> style(. [| display(`block) |])

(* Problem *)
%css can't contain more than one property.
It woudn't met the interface of `string -> Css.Rule`.

Possible solution I

Wrap every [%css] with a style() call, making css a string.
We would need to change cx as well, to make a "merge" of those styles.

Cons

  • More function calls (didn't benchmark performance on any level, but I belive those changes are the ones that can penalize)
  • We lose composability, Css.Rule isn't longer a thing in our users codebase.

Possible solution II

css: string -> Css.Rule
[%css "display: block"]
(* ----- *)
display(`block)

css: string -> array(Css.Rule)
[%css "display: block; width: 100%"]
(* ----- *)
[|display(`block), width(percent(100.))|]

Cons

  • What a silly polymorphism
  • Not sure If it helps in any way tbh.

Possible solution III

Treat all [%css ...] as array.

css: string -> [| Css.Rule |]
[%css "display: block"]
(* ----- *)
[| display(`block) |]

css: string -> array(Css.Rule)
[%css "display: block; width: 100%"]
(* ----- *)
[|display(`block), width(percent(100.))|]

Cons

  • Not sure how well compose with the rest of the syntaxes:
    • [%cx [%css ""]]
    • [%cx ""]