Giter Club home page Giter Club logo

bs-typed-glamor's Introduction

Glamor. Typed.

bs-typed-glamor provides a strongly typed interface to glamor based on the types of glennsl/bs-typed-css-core.

Dependencies Issues Last Commit

Installation

Run npm install --save glennsl/bs-typed-glamor and add bs-typed-glamor to the bs-dependencies in bsconfig.json.

Annotated Example

(* The OCaml syntax is recommended with this DSL for improved readability, and will be shown here.
   Reason users can use a separate .ml file alongside each component file, for eaxample if the
   component is in `Foo.re`, you could have a `FooStyles.ml` alongside it and then refer to 
   `FooStyles.myStyle` in the component *)
   
open TypedGlamor

(* A basic style definition *)
let box = css [
  display block;
  color red;
]

(* triangle *)
let cube = css [
  (* style definitions can have labels which will be included in the generated classnames to aid debugging *)
  label "thing";
  
  (* multi-argument properties are suffixed with the number of arguments they take, and are labeled when there's confusion *)
  padding2 ~v:(em 0.75) ~h:(em 1.5);
  
  (* single-argument properties are not *)
  padding zero;
  
  (* properties that can take any number of arguments are pluralized and take a list *)
  transitions [
    (AnimatableProperty.opacity, ms 500, linear, ms 0);
    (AnimatableProperty.height, ms 300, linear, ms 200);
  ];
  
  (* they'll still have a non-pluralized variant which can take a single argument however,
      and which will still override the pluralzied variant *)
  transition unset;
  
  (* if a value and property name conflict by having the same name, the property name is "mangled" *)
  display flex;
  flex_ (int 1);

  (* `select`, given a css selector where `&` is substituted with the current element,
      will apply the given styles to the sub selection *)
  select "& > .title" [
    fontSize larger;
  ];
  
  (* `&` is implied at the start *)
  select "> .subtitle" [
    fontSize smaller;
  ];
  
  (* `:hover` and other pseudo-classes are all available statically typed  *)
  hover [
    background plum;
  ];
  
  (* media queries are not statically typed (yet), but can be stringly typed in a `select` *)
  select "@media (max-width: 600px)" [
    select "& > .subtitle" [
      display none;
    ];
  ];
]

(* Conditionals

   Since this is all just plain OCaml/Reason code and everytng is an exporession, you can just
   use all the conditional constructs you already know and love pretty much anywhere. Below are some
   examples to serve as inspiration *)
let root = fun ~isPublished ~style -> css [

  select "> div" (
    if not isPublished then [
      textDecoration lineThrough
  ] else []);

  backgroundColor (
    if isFocused then
      hsl (num 6.9) 90 90
    else
      white
  );

  if isFlagged then add [
    opacity 0.5;
  ] else add [
    boxShadows [shadow ~x:(ex 1.) ~y:(ex 1.) ~blur:(em 1.) (rgba 0 0 0 0.1)];
    backgroundColor whitesmoke;
  ];

  select "> *" [
    opacity (if isFlagged && not isFocused then 0.5 else 1.);
  ];
  
  color
    (match style with
    | `Heavy -> white
    | `Light -> whitesmoke
    | `Black -> black);
]

(* Global style declarations are supported through `global`.  *)
let _global = begin
  global "html" [
    fontSize (px 15);
    lineHeight (em 1.25);
  ];

  global "html, body" [
    backgroundColor white;
    minHeight (pct 100.);
  ];
end

(* The optional `extend` argument to `css` can be used to extend an existing style *)
let readme = css ~extend:CommonStyles.html [
  backgroundColor white;
  padding2 ~v:(em 2.) ~h:(em 4.);

  select "@media (max-width: 900px)" [
    padding2 ~v:(em 1.) ~h:(em 2.);
  ]
]

To use with ReasonReact:

module Box = {
  let component = ReasonReact.statelessComponent("Box");
  let make = _children => {
    ...component,

    render: (_self) =>
      <div className=(Styles.box |> TypedGlamor.toString) />
  }
};

Documentation

The supported CSS properties and values are listed in bs-typed-css-core/CssCore.re, while the Glamor-specific parts are in TypedGlamor.rei.

bs-typed-glamor's People

Contributors

emmenko avatar glennsl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

emmenko

bs-typed-glamor's Issues

Transform the labelled functions into unlabelled to ease their consumption from PPX

I'm using bs-typed-glamor together with https://github.com/astrada/ppx_bs_css, which honestly provides a pretty amazing dev exp. Huge thanks to both @glennsl and @astrada :)

I found that when defining a property like padding: 2px 4px 3px 1px it gets translated by the ppx to padding4(px(2), px(4), px(3), px(1)), which compiles fine, but you get the warning labels were omitted in the application of this function.

I wonder if there would be a chance to update these labelled functions to not use labels (breaking change, I know) and, if there's a will to keep the labelled functions, rename them to some alternate name, like padding4L.

I'd be willing to work on this if the proposal makes sense.

Shorthand for "TypedGlamor.toString"?

Another nitpick: I found myself writing TypedGlamor.toString every time I need to pass a class to a React element. Even though I open TypedGlamor; on top of the module, I find it a bit confusing of simply writing toString.

Therefore, I was wondering if we can provide another alias or something to make this shorter, for example cs (for class or class string), so you can write Styles.header |> cs.

WDYT?

Think about using a monorepo for the different packages?

Sorry for throwing all those questions at you ๐Ÿ˜…

As I did a bugfix yesterday, I had to create two PRs in two different repos. Personally, that's a bit annoying.

Would you consider instead having a single repo with all the different packages in one place? It makes contributing and managing released much much easier ๐Ÿ™

Of course it's up to you to decide what you prefer ๐Ÿ˜‡

Ignore *.bs.js files?

This is more of a nitpick, but I noticed that the *.bs.js files are in version control. Is it on purpose or should we ignore them?

selector specificity?

it would be nice to be able to specify "!important" as an escape hatch where styles are not applied due to selector specificity issues.

are there any workarounds for this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.