React Accordion

A Simple React Accordion example.

Made with

Html
Css/SCSS
Javascript

Html

<div id="app"></div>

Css

@import url('https://fonts.googleapis.com/css?family=PT+Sans');
html, body, #app {
  height: 100%;
}

.container {
  min-height: 100%;
  padding: 30px;
  font-family: 'PT Sans';
  text-align: center;
  
  h1 {
    text-align: center;
    color: #1569a8;
  }
  
  .btn {
    display: inline-block;
    margin-bottom: 20px;
    border: 1px solid #1569a8;
    background: white;
    color: #1569a8;
    padding: 5px 10px;
    border-radius: 5px;
    margin-right: 5px;
    font-size: 15px;
    cursor: pointer;
    outline: none;
    
    &:hover {
      background: #1569a8;
      color: white;
      transition: .5s;
    }
  }
}

.accordion {
  margin: 0 auto;
  width: 80%;
  
  .title {
    padding: 30px 30px;
    cursor: pointer;
    transform: translate3d(0, 0, 0);
    color: white;
    position: relative;
    font-size: 20px;
    background: #1569a8;
    margin-bottom: -1px;
    border-bottom: 1px solid #0e4671;
    text-align: left;

    &::after {
      content: "+";
      font-size: 18px;
      color: white;
      transition: transform .5s ease-in-out;
      position: absolute;
      right: 30px;
      font-family: monospace;
    }

    &.is-expanded {
      transition: background .5s;
      background: #0e4671;
      
      &::after {
        content: "-";
        transform: rotate(-360deg);
      }
    }
  }

  .content {
    overflow: hidden;
    max-height: 0;
    transition: max-height .5s;
    margin: 0;
    padding: 0 30px;
    border: solid 1px #eeeeee;
    border-top: 0;
    background: #e8f4fc;

    p {
      padding: 30px 0;
      margin: 0;
      opacity: 0;
      transition: .5s;
    }
    
    &.is-expanded {
      max-height: 500px;
      overflow: hidden;
      p {
        opacity: 1;
      }
    }
  }
  
  &:after {
    width: 100%;
    height: 10px;
    display: block;
    background: #0e4671;
    content: '';
  }
}

Javascript


Author

class Accordion extends React.Component {
  render() {
    const { title, expand, onClick } = this.props;
    
    return (
      <div>
        <dt className={expand ? 'title is-expanded' : 'title'} onClick={onClick}>
          {title}
        </dt>
        <dd className={expand ? 'content is-expanded' : 'content'} onClick={onClick}>
          <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi eu interdum diam. Donec interdum porttitor risus non bibendum. Maecenas sollicitudin eros in quam imperdiet placerat. Cras justo purus, rhoncus nec lobortis ut, iaculis vel ipsum. Donec dignissim arcu nec elit faucibus condimentum. Donec facilisis consectetur enim sit amet varius. Pellentesque justo dui, sodales quis luctus a, iaculis eget mauris.

            Aliquam dapibus, ante quis fringilla feugiat, mauris risus condimentum massa, at elementum libero quam ac ligula. Pellentesque at rhoncus dolor. Duis porttitor nibh ut lobortis aliquam. Nullam eu dolor venenatis mauris placerat tristique eget id dolor. Quisque blandit adipiscing erat vitae dapibus. Nulla aliquam magna nec elementum tincidunt.
          </p>
        </dd>
      </div>
    );
    
  }
}

class Application extends React.Component {  
  constructor (props) {
    super(props);
    this.state = {
      block1: true,
      block2: false,
      block3: false,
    };
  }
  
  toggle = (index) => () => {
    this.setState({ [`block${index}`]: !this.state[`block${index}`] });
  }
  
  toggleExpand = (expand = false) => () => {
    this.setState({
      block1: expand,
      block2: expand,
      block3: expand,
    });
  }
  
  render() {
    const accordionList = [{ title: 'First Accordion' }, { title: 'Second Accordion' }, { title: 'Third Accordion' }];
    
    return <div className="container">
      <h1>React Accordion</h1>
      <button type="button" className="btn" onClick={this.toggleExpand(true)}>Expand All</button>
      <button type="button" className="btn" onClick={this.toggleExpand()}>Collapse All</button>
      <dl className="accordion">
        {
          accordionList.map((item, index) => (
            <Accordion title={item.title} onClick={this.toggle(index + 1)} expand={this.state[`block${index+1}`]} />
          ))
        }
      </dl>
    </div>;
  }
}

React.render(<Application />, document.getElementById('app'));

Demo

See the Pen React Accordion by Elaine Huang (@elainehuang) on CodePen.