Reason JSX syntax for BuckleScript-TEA
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
src
test
.gitignore
.ocamlformat
LICENSE
README.md
bsconfig.json
package.json

README.md

ppx-tea-jsx    Version 0.6.0

Reason JSX syntax support for BuckleScript-TEA library.

Installation

  1. Install via npm or Yarn:
yarn add --dev ppx-tea-jsx
  1. Add the PPX to your bsconfig.json:
{
  "ppx-flags": ["ppx-tea-jsx/ppx"]
}

Usage

You can pass JSX expressions to any function that expects Vdom.t.

HTML elements

let view = _model =>
  <div id="root" className="blue">
    <button style=[("width", "20px")] classList=[("active", true)] />
  </div>;
<video controls=true autoplay=false width=250>
  <source src="/media/examples/flower.mp4" type_="video/mp4" />
  "Sorry, your browser doesn't support embedded videos."
</video>

Literals

<a href="https://example.com"> "Addition: " 5 '+' 25.5 </a>

Punning

let id = "fifty";
let className = None;

let _ = <div id ?className />;

Children spread

let buttons_list_fn = () => [<button />, <button />, <button />];

let buttons_fragment = <> <button /> <button /> <button /> </>;

let view = _model =>
  <div>
    <span> ...{buttons_list_fn()} </span>
    <span> ...buttons_fragment </span>
  </div>;

Events

You can trigger messages:

<button accesskey='s' onClick=Increment />

And return option(msg) from callbacks:

<button
  disabled=true
  onClick={
    e => {
      e##preventDefault();
      Some(Reset);
    }
  }
/>
<input onChange={value => Set(int_of_string(value))} />
let view = model => {
  let onChangeOpt = value =>
    try (value->int_of_string->Set->Some) {
    | _ => None
    };
  <input value=model onChangeOpt />;
};

Modules (Capitalized Tag)

<Foo bar="baz"> "Hi" </Foo> is mapped to Foo.view(~bar="baz", [text("Hi")]).

type person = {
  name: string,
  age: option(int),
};

module OnlyChild = {
  let view = children => <div className="border-5"> children </div>;
};

module Person = {
  let view = (~className=?, ~name, ~age=?, children) => {
    open Tea.Html;
    let age =
      age
      ->Belt.Option.mapWithDefault(noNode, x =>
          <span> " (" x->string_of_int->text ")" </span>
        );

    <div ?className> <span> ...children </span> {text(name)} age </div>;
  };
};

let view = model => {
  let img =
    <img
      src="/media/examples/grapefruit-slice-332-332.jpg"
      alt="Grapefruit slice atop a pile of other slices"
    />;

  <div>
    <div> <OnlyChild> ...img </OnlyChild> </div>
    <Person className="user-l" name={model.name} age=?{model.age}>
      <strong> "Hi " </strong>
    </Person>
  </div>;
};