Simple Accordion example

by Joe Hudson

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.0/JSXTransformer.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.0/react-with-addons.js"></script>
<script src="http://facebook.github.io/react/js/jsfiddle-integration.js"></script>

<div id="example"></div>

CSS

.accordion {
	border: solid 1px #000;
	border-bottom-width: 0;
}
.accordion-section {
	border-bottom: solid 1px #000;
}

.accordion-section > h3 {
	padding: 6px;
	font-size: 16px;
	background-color: #CCC;
    margin: 0;
}
.accordion-section > .body {
    height: 0;
    padding: 0 10px;
    overflow-y: hidden;
    transition: height .5s;
    transition: height .5s, padding-top .5s, padding-bottom .5s;
}
.accordion-section.selected > .body {
    height: 100px;
	padding-top: 10px;
	padding-bottom: 10px;
}

JavaScript 1.7

var Accordion = React.createClass({
    getInitialState: function() {
        // we should also listen for property changes and reset the state
        // but we aren't for this demo
        return {
            // initialize state with the selected section if provided
            selected: this.props.selected
        };
    },

    render: function() {
        // enhance the section contents so we can track clicks and show sections
        var children = React.Children.map(
            this.props.children, this.enhanceSection);

        return (
            <div className="accordion">
                {children}
            </div>
        );
    },

    // return a cloned Section object with click tracking and "active" awareness
    enhanceSection: function(child) {
        var selectedId = this.state.selected,
            id = child.props.id;

        return React.addons.cloneWithProps(child, {
            key: id,
            // private attributes/methods that the Section component works with
            _selected: id === selectedId,
            _onSelect: this.onSelect
        });
    },

    // when this section is selected, inform the parent Accordion component
    onSelect: function(id) {
        this.setState({selected: id});
    }
});

// the Accordion Section component
Accordion.Section = React.createClass({
    render: function() {
        var className = 'accordion-section' + (this.props._selected ? ' selected' : '');
    
        return (
            <div className={className}>
                <h3 onClick={this.onSelect}>
                    {this.props.title}
                </h3>
                <div className="body">
                    {this.props.children}
                </div>
            </div>
        );
    },

    onSelect: function() {
        // tell the parent Accordion component that this section was selected
        this.props._onSelect(this.props.id);   
    }
});


React.render((
    <Accordion selected="2">
       ...