A mixin-based design for a React.js Bootstrap component library

Bootstrap ships classes for cross-cutting concerns, e.g. size (lg, md, sm) and style (default, primary, success, etc).

One soluton for a React.js component library is to make components for all combinations. Here’s a suggestion for composing the classes via mixins.

The main idea is to have a set of properties, e.g. bsSize, bsStyle, and construct the className string from them:


var ClassNameHelper = {
    extendClassName: function() {
        var bsClass = this.props.bsClass;
        var bsStyle = this.props.bsStyle;
        var bsSize = this.props.bsSize;
        var prefix = this.props.bsClass + '-';

        var classes = {}
        // TODO: Check there are no conflicting values in this.props.className
        if(this.props.bsClass)
            classes[this.props.bsClass] = true;
        if(this.props.bsSize)
            classes[prefix + this.props.bsSize] = true;
        if(this.props.bsStyle)
            classes[prefix + this.props.bsStyle] = true;
        // Merge with previous classes
        if(this.props.className)
            this.props.className.split(' ').map(
                function(klass){
                    classes[klass] = true;
                }
            );
        // This produces a ' ' delineated string
        // from all members of classes that evaluate as truthy
        return React.addons.classSet(classes);
    },
};

The mixin would be used in the component library like this:

var Button = React.createClass({
    mixins = [ClassNameHelper],
    getDefaultProps: function() {return {bsClass: 'btn'};},
    render: function() {
        return this.transferPropsTo(
            <button className={this.extendClassName()}>
                {this.props.children}
            </button>
        );
    }
});

Users could pass in the arguments as props:

<Button bsSize="sm" bsStyle="default">Sign Up!</Button>

I prefer creating ad hoc asset components though, so I think there should also be a set of mixins:

var Large = {getDefaultProps: function() { return {bsSize: 'lg'};}};
var Medium = {getDefaultProps: function() { return {bsSize: 'md'};}};
var Small = {getDefaultProps: function() { return {bsSize: 'sm'};}};

var Default = {getDefaultProps: function() { return {bsStyle: 'default'};}};
var Primary = {getDefaultProps: function() { return {bsStyle: 'primary'};}};
var Success = {getDefaultProps: function() { return {bsStyle: 'success'};}};
var Info = {getDefaultProps: function() { return {bsStyle: 'info'};}};
var Warning = {getDefaultProps: function() { return {bsStyle: 'warning'};}};
var Danger = {getDefaultProps: function() { return {bsStyle: 'danger'};}};
var Link = {getDefaultProps: function() { return {bsStyle: 'link'};}};

var SignupButton = React.createClass({
    mixins = [Large, Success, Button],

    render: function() {return <Button>Sign Up Now!</Button>;}
});

If we can get the design right, I think that a good Bootstrap component library could be a very popular resource.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s