revery-ui / revery

:zap: Native, high-performance, cross-platform desktop apps - built with Reason!
https://www.outrunlabs.com/revery/
MIT License
8.07k stars 196 forks source link

Documentation: Add documentation for creating a custom component #118

Open bryphe opened 5 years ago

bryphe commented 5 years ago

We currently support custom components (with hooks even!) - some examples in the code: https://github.com/bryphe/revery/blob/711a90a0b19af2f39dd984cb1570a1231e745365/examples/Bin.re#L50 https://github.com/bryphe/revery/blob/711a90a0b19af2f39dd984cb1570a1231e745365/examples/Bin.re#L6

However, our documentation just says TODO. We should put a simple example there and detail the 'anatomy' of a custom component, so that it is more accessible.

idkjs commented 5 years ago

Starting from the oldest "help wanted/good first issue" item.

So to demonstrate a custom component, I removed module Logo from examples/Hello.re and put it in examples/Logo.re.

open Revery.Math;
open Revery.UI;

module Logo = (
  val component((render, ~children, ()) =>
        render(
          () => {
            let (opacity, setOpacity) = useState(1.0);

            let onMouseDown = _ => setOpacity(0.5);
            let onMouseUp = _ => setOpacity(1.0);

            let rotation =
              useAnimation(
                Animated.floatValue(0.),
                {
                  toValue: 6.28,
                  duration: Seconds(8.),
                  delay: Seconds(1.0),
                  repeat: true,
                  easing: Animated.linear,
                },
              );

            let rotationY =
              useAnimation(
                Animated.floatValue(0.),
                {
                  toValue: 6.28,
                  duration: Seconds(4.),
                  delay: Seconds(0.5),
                  repeat: true,
                  easing: Animated.linear,
                },
              );

            <view onMouseDown onMouseUp>
              <image
                src="outrun-logo.png"
                style={Style.make(
                  ~width=512,
                  ~height=256,
                  ~opacity,
                  ~transform=[
                    RotateY(Angle.from_radians(rotationY)),
                    RotateX(Angle.from_radians(rotation)),
                  ],
                  (),
                )}
              />
            </view>;
          },
          ~children,
        )
  )
);

I then call it in Hello.re like so: This doesn't compile either Logo1 or Logo calls. Does calling a module work differently than usual?

module Logo1 = Logo.Logo;

let init = app => {
  let win = App.createWindow(app, "Welcome to Revery!");

  let render = () =>
    <view
      style={Style.make(
        ~position=LayoutTypes.Absolute,
        ~justifyContent=LayoutTypes.JustifyCenter,
        ~alignItems=LayoutTypes.AlignCenter,
        ~bottom=0,
        ~top=0,
        ~left=0,
        ~right=0,
        (),
      )}>
      <Logo1 />
      <Logo />
      <view
        ref={r => print_endline("View internal id:" ++ string_of_int(r#getInternalId()))}
        style={Style.make(~flexDirection=Row, ~alignItems=AlignFlexEnd, ())}>
        <AnimatedText delay=0.0 textContent="Welcome" />
        <AnimatedText delay=0.5 textContent="to" />
        <AnimatedText delay=1. textContent="Revery" />
      </view>
      <SimpleButton />
    </view>;

  UI.start(win, render);
};

App.start(init);

screen shot 2019-01-04 at 8 02 58 pm

bryphe commented 5 years ago

Thanks @idkjs for looking at this!

Hmm, as long as Logo.re was in the same directory as Hello.re - it should work. (either <Logo /> with open Logo; at the top, or <Logo1 /> with module Logo1 = Logo.Logo should be fine).

Looking at the code above - Logo depends on the AnimatedText component - did you move that to a separate module, too? Or include it in the Logo.re? Perhaps there is a compilation error impacting Logo.re.

bryphe commented 5 years ago

I created a branch that compiles for me that might be helpful: bryphe/test-component-extraction - relevant commit is this one: https://github.com/revery-ui/revery/commit/e529b76336ceb9efcdbdf53b8f3484e3283d6d9b

I showed two ways of including a module:

Hope that helps!

idkjs commented 5 years ago

No Joy. I cp'd your example into the project on local machine. These are the files:https://gist.github.com/idkjs/266d19f2286cdfdf026d58714fef3b76.

I get the same error on Logo.Logo. Feels like a set up thing. Incidentally, what is the equivalent of bsb -run-world -w in this context?

Of note, Clock.re, line 8(let ui = UI.create(w);) is not compiling though i didn' t touch it. screen shot 2019-01-05 at 12 19 52 pm

idkjs commented 5 years ago

Logo is unbound whether I do open Logo; or module Logo = Logo.Logo. Same happens with open AnimatedText;

I redownloaded repo, esy install, esy build, esy x Hello2.re on this repo https://github.com/idkjs/ReveryTest. Getting the same errors.

OhadRau commented 5 years ago

Ah when using esy x you just say the name of the final executable. So to execute Hello.re, we do esy x Hello. However this requires us to add it in examples/dune. If you add Hello2 into that file then this should work. Let me know if you need any help still.

albertorestifo commented 5 years ago

Is anyone working on a PR for this?

idkjs commented 5 years ago

Got away from me. Do we still need this? I will do it, if so.

bryphe commented 5 years ago

Hey @albertorestifo @idkjs ! Thanks for your help with this. I don't think anyone has started this yet - just don't want you to both duplicate the work 👍

Note that the syntax has changed a bit (we just updated to the latest brisk) - a good example of lots of custom components are in the Calculator example, if that helps: https://github.com/revery-ui/revery/blob/b6048e2d97687d5eefe940eda0d1f8a085b05259/examples/Calculator.re#L8