<div id="root"></div>
body{
  background-color: #F9F9FA
}
.slideshow {
  width: 480px;
  height: 360px;
  background: #000;
  position: relative;
}
.slideshow-slides {
  list-style: none;
  margin: 0;
  padding: 0;
}
.slideshow-slides li {
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  margin: 0;
  padding: 0;
  transition: .2s;
  opacity: 0;
}
.slideshow-slides li.active {
  opacity: 1;
}
figure {
  margin: 0;
  padding: 0;
}
figcaption {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  color: #fff;
  padding: 10px;
}

.slideshow-dots {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  text-align: center;
  list-style: none;
}
.slideshow-dots li {
  display: inline;
  margin: 0;
  padding: 0;
}
.slideshow-dots a {
  cursor: pointer;
  display: inline-block;
  width: 10px;
  height: 10px;
  margin: 0 5px;
  background: #fff;
  border-radius: 10px;
  text-indent: -9990px;
  opacity: .5;
  transition: .3s;
}
.slideshow-dots li.active a {
  opacity: 1;
}
var hasOwn = {}.hasOwnProperty;

function classNames () {
  var classes = '';

  for (var i = 0; i < arguments.length; i++) {
    var arg = arguments[i];
    if (!arg) continue;

    var argType = typeof arg;

    if (argType === 'string' || argType === 'number') {
      classes += ' ' + arg;
    } else if (Array.isArray(arg)) {
      classes += ' ' + classNames.apply(null, arg);
    } else if (argType === 'object') {
      for (var key in arg) {
        if (hasOwn.call(arg, key) && arg[key]) {
          classes += ' ' + key;
        }
      }
    }
  }

  return classes.substr(1);
}

class SlideShow extends React.Component {
  constructor() {
    super()
    this.state = { activeIndex: 0 };
  }
  jumpToSlide(index) {
    this.setState({ activeIndex: index });
  }
  render() {
    return (
      <div className="slideshow">
        <ul className="slideshow-slides">
          {
            this.props.slides.map((slide, index) => (
              <li className={ classNames({ active: index == this.state.activeIndex }) }>
                <figure>
                  <img src={ slide.imageUrl } />
                  { slide.caption ? <figcaption>{ slide.caption }</figcaption> : null }
                </figure>
              </li>
            ))
          }
        </ul>
        <ul className="slideshow-dots">
          {
            this.props.slides.map((slide, index) => (
              <li className={ (index == this.state.activeIndex) ? 'active': '' }>
                <a onClick={ (event)=> this.jumpToSlide(index) }>{ index + 1 }</a>
              </li>
            ))
          }
        </ul>
      </div>
    );
  }
}

let _slides = [{
  imageUrl: "https://i.ytimg.com/vi/MxwjEacvrtY/hqdefault.jpg",
  caption: "Allan Allan Al Al Allan"
}, {
  imageUrl: "https://pbs.twimg.com/profile_images/2576554888/s8vftzr3j0a9r703xdfn.jpeg",
  caption: "Steve Steve Steve"
}];

class App extends React.Component {
  render() {
    return <SlideShow slides={ _slides } />
  }
}

var root = document.querySelector('#root');
ReactDOM.render(<App />, root)
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/react/0.14.3/react-with-addons.js
  2. https://cdnjs.cloudflare.com/ajax/libs/react/0.14.3/react-dom.js