koenbok / Framer

Framer - Design Everything
https://framer.com
MIT License
5.85k stars 477 forks source link

React based Framer #158

Closed koenbok closed 7 years ago

koenbok commented 9 years ago

Maybe we can leverage the virtual dom from react to get:

1) Closer to production 2) Offload more advanced memory management (dom/events) 3) Get performance improvements

koenbok commented 9 years ago

I played around with this today. I built the most bare bones version of Framer on top of React (Context, Layer, Tween, Render). You can find it here: http://cl.ly/1M0X241G1X2y and to run it you need http://cactusformac.com.

First of all, I am no react/virtualdom expert so I might be doing things wrong. That is one of the reasons to post it here :-) This is a work in progress.

Next up: event system.

iamralpht commented 9 years ago

Sweet! Last time I seriously used React (8 months ago) I needed to set style directly to get perf for pan/pinch gestures. I did this by creating a mixin FastStyleMixin which added a dictionary for style properties and a setStyleProperty method. Internally it just called getDOMNode() and assigned all of the styles. It listened for the lifecycle hooks componentDidMount and componentDidUpdate and re-applied all of its styles in there, too.

I actually really liked this because I still had the robust encapsulation that's so nice about React, and I hadn't completely violated its model to get the performance I wanted (i.e.: there were no sharp edges exposed by my hack, so it was pretty nicely contained). It's good to have nice escape hatches :).

koenbok commented 9 years ago

That sounds like a great approach for take two! Thanks!

koenbok commented 9 years ago

Note to self: so a simpler version of this: https://github.com/elierotenberg/react-animate/blob/master/AnimateMixin.js [update: hmm not really]

irvinebroque commented 9 years ago

@koenbok - React-tween-state is also worth looking into for handling tweening and requestAnimationFrame

https://github.com/chenglou/react-tween-state

koenbok commented 9 years ago

Ha, I was just looking at that. Thanks!

cleercode commented 9 years ago

Very interesting. The thing about the virtual DOM being good for DOM manipulation and not just style updates seems accurate and is an important insight. This got me thinking a lot more about why a Framer/React hybrid would be interesting. In retrospect, I suspect that a virtual DOM-based method can't offer any benefits over Framer's current method.

I think actually the most interesting part about React is not the virtual DOM as an implementation method but the user-facing API, allowing people to reason statically and declaratively about the state of an application rather than in a series of manipulations of the original state. Here's an article about this. The virtual DOM is an implementation detail that makes declarative programming able to be relatively performant (but probably not as performant as imperative DOM manipulations, style changes, etc.).

So I think there may be some interesting thought around whether that'd be a useful way to think about the Framer API. It seems like the Tween part of your demo is an example of this: the layer.x = layer.tweenA.next() API instead of `layer.animate properties: layer.x: ..."

The approach I think I'd be interested in is starting with an API: what would a more declarative Framer API look like? Would it even be significantly different than the Framer of today? Would it be more useful or make more sense to prototypers? It's unclear to me; the declarative model of reasoning makes a lot of sense for states but might not be useful for things like animations and gestures. React is notoriously unclear on how to implement animations, probably because you can conceptualize them fitting in with the React model in many different ways. And given that Framer mostly needs to make style changes, not DOM changes, the declarative model of reasoning about states isn't as necessary; it's relatively easy to implement that sort of system for style changes (Framer's state system is already basically like this) but difficult for the DOM.

koenbok commented 9 years ago

@cleercode I hear you on the declarative api. I'd love to read more ideas on this. I know that more people like https://twitter.com/ianh_ are working on this: https://twitter.com/andy_matuschak/status/557282393212878849

In terms of the Framer React port I'm still optimistic that dom alterations performance and (presumably) better memory/event handling could be wins for Framer. So if I can make something work like @iamralpht suggests we could have both.

One thing that for example could be cool, but I'm not sure of, is that our TableComponent won't have to include logic (or maybe only partial) for re-using layers for performance while you scroll. React would re-use dom elements behind the screens. If this turns out to be true, that would be amazing.

koenbok commented 9 years ago

I think we just got one more good reason for a react based framer: native. I guess we'll have to see how it works.

subtleGradient commented 9 years ago

FWIW, I tried to convince you to do this forever ago ;)

koenbok commented 9 years ago

Ok I tried @iamralpht approach and I have a nice version that only uses dom diffing for structure but sets the style directly on the elements in an animation look. As expected, performance is equal to the current Framer.

I just don't know for sure if I did the React part right, I pass that layer as a prop to the component and then set the dom element after mount on the layer. I feel like @iamralpht had a cleaner way.

http://cl.ly/3d303o1e3Y34

iamralpht commented 9 years ago

I'm going to be bridging Slalom and React soon, so I'll have a go and doing what I said cleanly for that :). I'll post a link when it's up.

bengotow commented 9 years ago

Hey gang—this is really, really interesting stuff. My team is building a mail client on top of React (which will actually ship as a desktop app inside of Atom Shell), and I'd love to be able to use FramerJS to drive animations. I know "production-facing animation framework" isn't the intention of Framer, but Atom Shell means we only target the latest Chromium! In a perfect world, our designer would be able to save an animation in Framer Studio and see the change in the running app.

For what it's worth, it would be amazing if ReactLayer was actually a React Mixin that could be applied to any component. This Drag and Drop library for React is a great example of a Mixin that extends a React component with new styles, event hooks, etc: https://github.com/gaearon/react-dnd. It's also very nice React, imo!

The really cool bit is this: <div {...this.dropTargetFor(ItemTypes.IMAGE)}>

In your render function, you add this bit of code, and it allows the mixin to add styles, event handlers, etc. to the div. It would be totally incredible if something like this allowed Framer to add children to the element, styles in preparation for animation, etc. (Though I agree with the conversation here that tweening should not invoke the render cycle. That would be especially important if the render method included external code.)

tehfailsafe commented 9 years ago

Any update on this idea? Would love to hear how/if it's progressing!

subtleGradient commented 9 years ago

Relevant: http://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html#other-languages

Defining React components using CoffeeScript is now possible with the latest release of React v0.13.0

div = React.createFactory 'div'

class Counter extends React.Component
  @propTypes = initialCount: React.PropTypes.number
  @defaultProps = initialCount: 0

  constructor: (props) ->
    super props
    @state = count: props.initialCount

  tick: =>
    @setState count: @state.count + 1

  render: ->
    div onClick: @tick,
      'Clicks: '
      @state.count
chadobado commented 9 years ago

Also love to hear how this is progressing and if it formally made it into the roadmap, thanks.

chadobado commented 9 years ago

@koenbok - now that React Native has been open sourced, can share a detailed thread on how they are approaching animation. Hopefully helpful to you.

https://github.com/facebook/react-native/issues/46

josefrichter commented 9 years ago

Any updates here? I know Framer is intended for prototyping, but being able to get native app via React Native (+Backbone.js probably) could be a game changer..

koenbok commented 9 years ago

Hey @iamralpht I have a pretty simple react based Framer version here and it works with most prototypes. The implementation is pretty naive, a full render for each animation frame.

So you can definitely tell the perf is worse on mobile. I was wondering if you ever got to make (or have seen) the approach you describe above where you:

vjeux commented 9 years ago

I recently gave a talk about the exact problem you are facing at React Rally and the slides are here: https://speakerdeck.com/vjeux/react-rally-animated-react-performance-toolbox

If you need to change the structure of the DOM, then you need to re-render and implementing shouldComponentUpdate is a must if you do not want everything to re-render.

Now, if you just need to update a scalar value such as top/left/width/height... then you can implement Data Binding on-top of React. See the slides starting at slides 29. This gives you the ability to do updates as fast as you can do raw dom mutations.

We are using this technique in React Native with the library called Animated. We're still working on the documentations but you can get information in those 4 links:

Let me know if you need more information or code review, I'd be happy to help out!

iamralpht commented 9 years ago

I really like Animated -- have been thinking about making Slalom run on top of Animated values next time I get to make a pass at it.

@vjeux is there a module for using Animated with plain web React? On Sun, Sep 6, 2015 at 12:45 PM Christopher Chedeau < notifications@github.com> wrote:

I recently gave a talk about the exact problem you are facing at React Rally and the slides are here: https://speakerdeck.com/vjeux/react-rally-animated-react-performance-toolbox

If you need to change the structure of the DOM, then you need to re-render and implementing shouldComponentUpdate is a must if you do not want everything to re-render.

Now, if you just need to update a scalar value such as top/left/width/height... then you can implement Data Binding on-top of React. See the slides starting at slides 29. This gives you the ability to do updates as fast as you can do raw dom mutations.

We are using this technique in React Native with the library called Animated. We're still working on the documentations but you can get information in those 4 links:

Let me know if you need more information or code review, I'd be happy to help out!

— Reply to this email directly or view it on GitHub https://github.com/koenbok/Framer/issues/158#issuecomment-138118114.

vjeux commented 9 years ago

Animated for React web is on my todo-list. I've got a hacky version working with forceUpdate (not dom mutations) here: http://fooo.fr/%7Evjeux/fb/animated-docs/ but am working on cleaning it up and pushing it for real. Hopefully soon.

koenbok commented 9 years ago

Ok this gives me more then enough to move forward :-) Thanks so much. I'll keep you posted.

chadobado commented 9 years ago

@vjeux thanks for chiming in here, excited to see this move forward

wemakeweb commented 9 years ago

@vjeux any updates for the animated react web version?

vjeux commented 9 years ago

@wemakeweb There's an initial web implementation commit here: https://github.com/facebook/react-native/commit/a50b4ea7b9ecc4c95a38b58f12a71b93ff3a3131 but needs more work.

venkysetty commented 9 years ago

@vjeux What are the steps for building JS bundle for your initial web implementation commit? Any further updates on using dom mutation?

jchavarri commented 9 years ago

@koenbok Is this Fabric animation component for React helpful for the new React-based-Framer?

I found these paragraphs on the blog post interesting:

The CSS transition properties modeled this pretty well: “whenever this other property is changed, apply that change gently.” The animations are declared, the transitions are derived. Keyframes are less successful: “when this is applied, set these properties to these specific values over time.” These semantics lead to CSS keyframe animations being applied at undesirable times (such as initial render), always from the very beginning, and without any means of dynamically modifying them.

To integrate smoothly with React’s declarative nature, we’ll need our animation behavior to be fully described by the output of our render methods: a desired end state.

I wonder how complex animations would be possible with this approach. In the Github repo they mention:

Unlike what you get from passing a style hash to VelocityComponent's animation property, Velocity "UI pack effects" can have chained animation calls and specify a defaultDuration, and also can take advantage of stagger and reverse properties on the VelocityComponent.

Blog post: https://fabric.io/blog/introducing-the-velocityreact-library Github: https://github.com/twitter-fabric/velocity-react

jchavarri commented 8 years ago

If the goal of using React is just the diffing efficiency, I found other alternative that is maybe simpler and would better fit Framer as they update the DOM just once per frame, keeping the rendering performant:

virtual-dom together with main-loop

That said, I 100% agree with @cleercode on the user-facing API and how React enforces composability and declarative reasoning. I would love to build reusable, declarative, animated components that respond at 60fps. In my mind there's something like:

I think I just want React Native + Framer 😂

I have two questions:

vjeux commented 8 years ago

I honestly don't think that you are going to get any performance improvements from using React. The reason why React is fast is because computing the optimal mutations to do to the dom in the general case is hard. But, Framer, as I understand, already knows what attributes to modify and when. So adding a virtual dom layer is only going to make things slower.

To me, the reason why you would want to use React is to generate components that can be embedded inside of a normal React applications and let the developers continue building their app on-top of the generated components.

tehfailsafe commented 8 years ago

I agree with Christopher, the benefit to me wouldn't be faster framer, but rather prototyping like normal and then dropping the components into working react apps without much modification.

Especially useful when thinking about react-native apps... Would be awesome to "export" layers and layouts directly to react components with their styles defined, flex box setup etc On Sun, Jan 24, 2016 at 1:04 PM Christopher Chedeau < notifications@github.com> wrote:

I honestly don't think that you are going to get any performance improvements from using React. The reason why React is fast is because computing the optimal mutations to do to the dom in the general case is hard. But, Framer, as I understand, already knows what attributes to modify and when. So adding a virtual dom layer is only going to make things slower.

To me, the reason why you would want to use React is to generate components that can be embedded inside of a normal React applications and let the developers continue building their app on-top of the generated components.

— Reply to this email directly or view it on GitHub https://github.com/koenbok/Framer/issues/158#issuecomment-174341503.

koenbok commented 8 years ago

Yes and no, I think, but I'd love to hear feedback if I'm wrong :-)

For normal Framer prototypes there won't be any performance improvements, only in very specific cases where you maybe create a ton of layers, destroy them and create them again right away, so react can be smart about it and reuse them. But that isn't very common.

Actually, building Framer on top of React and keeping the performance high will be a bit of a challenge really, like @vjeux explains. Luckily he also he also explored a bunch of great approaches that I can take, so I think it's doable (use virtual dom for hierarchy/events, set animated properties directly on the node).

The two benefits for prototypes will be that we can built on top of Reacts event management stuff to get better lifecycle performance, and that we can experiment with React-native bindings, possibly getting closer to production.

But by far the main reason I'd like to build on React is for Framer Studio. Framer Studio has live feedback where it updates your prototype on every keystroke. At this time we completely rebuild your prototype every time. But by leveraging the virtual dom, we can only render the difference which will (presumably) gives us a huge performance with larger prototypes because it will only have to render the differences.

koenbok commented 8 years ago

@koenbok Do you think a more declarative API for Framer would help or go against the project interest and goals? I say this because frankly imho an imperative API is much simpler to understand for newcomers to the development world than a more declarative one.

@jchavarri I do think that at this point. But I also think there might be a way to invent something in between so you get both. I just haven't had the right idea yet :-)

bartekus commented 8 years ago

Any updates on this, perhaps a way to get involved to help out?

jeffscottward commented 8 years ago

Just stumbling in here. Boop+1. My ideal situation as the end result of this proposed API change would then be a way to integrate with http://www.reactboilerplate.com/. If Framer could trigger events to run the npm generate script of this library in a way that mimics layers and componenets from Framer and routes get mapped, etc, it would be truly instant scaffolding. From design to straight to data. https://github.com/mxstbr/react-boilerplate/blob/master/docs/general/commands.md

mxstbr commented 8 years ago

What @jeffscottward mentioned would be awesome! (not sure how feasible, but worth exploring!) I'm sure we could get a few people behind that if that's the chosen direction, definitely let me know how it goes!

awitherow commented 8 years ago

@koenbok A designer on my team loves Framer and is really getting good at cranking out functionality. Would be very interested in working on spiking this.

breezykermo commented 8 years ago

Would also be very interested in helping out with this! I've been developing with React Native for the past few months, and am now messing with Framer, and if you could port UI components directly into a React or React Native app through a React-based Framer, that would be incred.

JesseBilsten commented 8 years ago

This would be very beneficial to us as well. Our company has all our styleguide elements as react components that could be easily included into a framer project and then mocked up into a prototype.

ghost commented 8 years ago

-1 let's keep Framer simple and easy to use. Building React apps brings a world of complexity and maintainability concerns to the table, and that's not the kind of headache designers or UI engineers need while prototyping.

ghost commented 8 years ago

Seems to me that being afraid of additional complexity and maintainability is an excuse for not keeping it DRY, no? An animation sequence that translates directly from Framer to my App is essentially what keeps me from repeating myself.. how the translating is happening should be what I'm willing to learn.. not be afraid of, right? If we don't push tools.. then tools won't be better..

ghost commented 8 years ago

Perhaps when more designers pick up React and ES6 we'all be all set. Until then just prototype in React Native. There are some awesome boilerplates and UI kits to choose from.

chrislloyd commented 7 years ago

Bump on this issue now that React Fiber is on the horizon (with better performance for animations). Being able to have a React context in Framer would be great for designers being able to prototype with React components from our design system.

ghost commented 7 years ago

Please don't use React

ghost commented 7 years ago

FYI https://github.com/airbnb/react-sketchapp. It does not change my opinion about using React, like it or not.

jemgold commented 7 years ago

600 internet points to the first person to prototype with react components in Framer using react-sketchapp.

Hint: you can set layer names with the 'name' prop

jordandobson commented 7 years ago

hahaha!

On Wed, Apr 26, 2017 at 6:04 PM Jon Gold notifications@github.com wrote:

600 internet points to the first person to prototype with react components in Framer using react-sketchapp.

Hint: you can set layer names with the 'name' prop

On Apr 26, 2017 1:41 AM, "Josh Habdas" notifications@github.com wrote:

FYI https://github.com/airbnb/react-sketchapp. It does not change my opinion about using React, like it or not.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/koenbok/Framer/issues/158#issuecomment-297296289, or mute the thread < https://github.com/notifications/unsubscribe-auth/AAkHG_OBQKgA1mHik_4lCME6bAN5_wLxks5rzwNVgaJpZM4DT64Z

.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/koenbok/Framer/issues/158#issuecomment-297582684, or mute the thread https://github.com/notifications/unsubscribe-auth/AACbYl22ZfbfRJyzaZhq7LInBetmgqIoks5rz-mqgaJpZM4DT64Z .

--

  • Jordan Dobson
ghost commented 7 years ago

I'll put up a dozen chocolate chip cookies (we're talking Otis Spunkmeyer quality here folks) to the first designer that does it with Redux using Functional stateless components. Hint: You're going to need a developer to acutally do the work.

andrictham commented 7 years ago

@jhabdas @jongold There’s a learning curve with React and Redux, but there’s also a learning curve with Framer and Coffeescript.

Also, react-redux is a more “natural” way to think about interactions: a user event dispatches an action which results in a state change. The UI then reflects that state change. As a designer, I’m already thinking about it in these terms. If I prototype in react-redux, I’ll be self-documenting my design intent in a lossless form. Currently, I have to: prepare a Sketch file, write functional specs, and deliver a prototype.

One benefit of prototyping in code is you can use existing components from the world/your team which speeds up prototyping. Very rarely have I worked on a project where we designed everything from scratch, usually some third-party UI component is used.

Even if we make components from scratch, we still have to communicate how the component API will be designed (the text that should go in there, type of image, color variants, icon options, etc). Sketch symbols is one way, or perhaps a spec doc, but that’s very time consuming. If we are already spending time prototyping in code, why wouldn’t we just go ahead and do it in code too?

With designers picking up RxJS now, I don’t think it’s that hard to imagine some using Redux for prototyping.

ghost commented 7 years ago

https://medium.com/@gianluca.guarini/things-nobody-will-tell-you-about-react-js-3a373c1b03b4