Automating Design Mocks (part 1)
This is all very naive thinking aloud. You have probably already done this yourself (or implemented it and blogged about it, i am sorry i missed your post, it would have saved me some time).
Let’s pretend you have a widget you’re developing. You know well enough that it parameterizes on a few things, say some Text and an image. If you’re prototyping this in something like React, you end up with this:
<Widget image="foo.png" text="widgetext">
And that’s good. It’s easy to throw a bunch on a page and update those values and reload the page to see what things look like.
Say you want to have many of those, to show a grid of possible values. One way to do this is like so
var images = ["foo.png", ...];
var texts = ["widgetext", ...];// suppose you want to fuzz the parameters so that you
// can see unexpected pairings of image/text
var combos = _.zip(_.shuffle(images), _.shuffle(texts));var mocks = combos.map(function(pair){
return (<Widget image={pair[0]} text={pair[1]} />);
});<div>
{mocks}
</div>
This gets you pretty far, but say you want to fuzz the inputs to Widget based on, say, an api response or even just a larger collection that you’re sampling from.
One way to do this is to make the widget collection its own widget and combining spread attributes:
WidgetCollection = React.createClass({
propTypes:{
count: React.PropTypes.number,
childProps: React.PropTypes.array.isRequired
// childProps = [{text:'', image:''}, ...]
},
render:function(){
var childProps = this.props.childProps;
var collection = count.map(
function(el, idx){ return <Widget {...childProps[idx]} />
})); return (
<div>
{collection}
</div>
);
}
});
This is better in a way, we invoke the WidgetCollection and always pass through a new random assortment of childProps to get variety, like so
<WidgetCollection count={24} childProps={[...]} />
How could we expect childProps to vary?
At this point, we only need to worry about how we generate the collection of childProps and that ends up being an interesting question for purposes of design.
In our example, we have “text” and “image”, so how are the ways we might want to reasonably fuzz those values?
- text might be completely random
- text might be plucked from a larger pool (say an api response)
- text might need to be repeated the same way each time
- text might need to react to an input on the page
- the pool of text might be smaller than the number of protos we want
image is similar:
- image might need to respond to a drop target. (similar to the input example above for text)
- there might be less images than mocks
- even if you have a collection if image, you may want to only show one of them across all mocks
- you probably want the order of image randomized each time
- if you have n images, and n mocks, you probably want to see all n images.
So you can imagine something like this
var Shuffler = React.createClass({
propTypes:{
count: React.PropTypes.number,
childData: React.PropTypes.object
},
getInitialState: function(){
return {childProps: this.props.childData}
},
spinValues: function(){
// randomize values in some way, probably
// via setState to trigger a rerender
},
render: function(){
return
(<div>
<WidgetCollection count={this.props.count}
childProps={this.state.childProps} />
<button onClick={this.spinValues}>Refresh</button>
</div>);}
});
Ok, so you can imagine how this works: You drop a shuffler (which, for now, does not support polymorphism or react’s children or anything like that) into your jsx and you get this collection of mocks and a button that lets you refresh them all at once.
and now you can visually see your design being fuzzed and it breaking or it succeeding or colors being too similar to each other or type not breaking correctly, spawning tens of TODOs.
what’s missing?
well, at this point you’ve tasted automation, and you’ve spun some values around. But the single ui shuffle button is sorely lacking. namely
- you want to pin values
- you may want to ‘keep’ some parameters (they were interesting cases or breaking ones (the two are probably one and the same)).
- you may want to set values manually without reloading or editing code.
there’s other things too, but those are the big ones off the top of my head. there’s clearly a whole Microsoft Access style ui that you could build around this, but nobody wants that.
thinking about that ui and the ways to signal how data should change or not or be described is probably coming up in part 2.