While I was experimenting with animation, I had to make a few basic prototypes for a layout system and see how they intertwine. Here's the API in conjunction with React:
var MyComp = React.createClass({
registerLayoutValues: function() {
return {
self: {
width: 30,
left: (get('parent', 'width') - get('self', 'width')) / 2 // Center.
}
};
},
render: function() {
return <div />;
}
});
var App = React.createClass({
registerLayoutValues: function() {
return {
self: {
height: get('self', 'width') * 2,
width: get('MyComp', 'width') + 10, // Padding/margin.
anyValueCanBeHere: 20
},
MyComp: {
height: 50
}
};
},
render: function() {
return (
<div>
<MyComp ref="MyComp" />
</div>
);
}
});
It's rather simple: this constructs a DAG whose nodes are the values in registerLayoutValues
, and whose edges are toward the dependencies they need. For example, MyCompleft
depends AppWidth
and MyCompWidth
. So you start from the sink nodes and resolve the graph, like promises. How it translates to actual style is unimportant.
Text layout can be handled natively. If a width
is specified to depend on height
but height
doesn't exist, the system touches the DOM first and retrieves the value, hoping that it makes sense, and then proceed to resolve dependents as usual.
There might or might not have benefits in baking this props/state JS promise into React. If there is: the initial render isn't called until the values are resolved. This is a micro-view/alternative of the pre-render pass we were talking about. It's better because this seems more general and natural, and worse because I have no idea if this actually makes sense =).
Absolute layout should be the building block for other layout systems. Relative layout can be sugar for absolute layout (e.g. centerAt()
). The idea is that, due to whatever current constraints, we need to be able to get to the lower, imperative level (absolute positioning) for things like animation. A list of three items, whose middle item animates out onto an arbitrary position, might require the last item to stay at its position for the duration of the transition. The mid-transition layout corresponds to none of today's layout systems: flexbox, autolayout, grid-based layout, and even physics (explanations). In this sense, absolute positioning is a nice stop-gap solution until someone comes up with a layout system that makes sense of animation's craziness. A similar stopgap is jQuery Magic Move, which records the current positions of items, places them absolutely, animates stuff and then re-places them according to the old layout arrangement. Aka, it interpolates between two renders. The problem is concurrent animation: if, during transitioning out, another item inserts itself, how do you get the new starting point for your interpolation? The starting point itself is an incoherent layout.