Skip to content

Modus-Logo-Long-BlackCreated with Sketch.

  • Services
  • Work
  • Blog
  • Resources

    OUR RESOURCES

    Innovation Podcast

    Explore transformative innovation with industry leaders.

    Guides & Playbooks

    Implement leading digital innovation with our strategic guides.

    Practical guide to building an effective AI strategy
  • Who we are

    Our story

    Learn about our values, vision, and commitment to client success.

    Open Source

    Discover how we contribute to and benefit from the global open source ecosystem.

    Careers

    Join our dynamic team and shape the future of digital transformation.

    How we built our unique culture
  • Let's talk
  • EN
  • FR

Ext JS to React: Carousel

Published on March 27, 2018
Last Updated on April 23, 2021
Application Development

This is part of the Ext JS to React blog series. You can review the code from this article on the Ext JS to React Git repo.

The carousel component, popularized in Sencha Touch and now available in Ext JS in the modern toolkit, is similar to the tab panel in that views in a card layout are shown and hidden using a navigation bar. Unlike the tab panel, carousel navigation is simplified by dropping text and icons in favor of a simple nav element like a circle with “active” styling to show which child item in the card array is in view. In addition to interacting with the nav elements you can swipe to reveal neighboring cards in a carousel view.

Note: While not a requirement for React, this article’s code examples assume you’re starting with a starter app generated by create-react-app.

React Carousel Class

Let’s look at an example of the carousel view in React. We’ll start by defining a Carousel class. First, we’ll need to install the react-swipeable-views package:

npm install --save react-swipeable-views

The react-swipeable-views package enables the animated card-swapping action as you navigate between cards using the dot indicators as well as dragging / swiping between cards. Users of the React Material UI library may recognize its use from the “Swipeable example” in the tabs demo.

import React, { Component } from 'react';
import SwipeableViews from 'react-swipeable-views';
import './Carousel.css';

class Carousel extends Component {
  static defaultProps = {
    activecard: 0,
    className: '',
    position: 'bottom'
  }

  state = {
    activecard: this.props.activecard
  }

  render () {
    let { className } = this.props;
    className = className ? ` ${className}` : '';

    const { children, position } = this.props;
    const { activecard } = this.state;
    const xPositions = ['top', 'bottom'],
          axis = xPositions.includes(position) ? 'x' : 'y';

    return (
      <div
        {...this.props}
        className = {`carousel ${position}${className}`}
      >
        <div className={`nav-strip`}>
          {React.Children.map(children, (child, i) => {
            const isActive = (i === activecard) ? 'active' : '';

            return <div
              onClick={this.onNavClick.bind(this, i)}
              className={`nav ${isActive}`}
            >
              <span className="nav-dot"></span>
            </div>;
          })}
        </div>
        <SwipeableViews
          index={activecard}
          onChangeIndex={this.onNavClick.bind(this)}
          enableMouseEvents={true}
          axis={axis}
        >
          {React.Children.map(children, (child, i) => {
            let { className } = child.props;
            className = className ? ` ${className}` : '';

            const isActive  = (i === activecard) ? ' active' : '';
            const cardProps = {
              ...child.props,
              style     : {flex: 1},
              className : ` card${isActive}${className}`,
              cardindex : i,
              activecard
            };

            return React.cloneElement(child, cardProps);
          })}
        </SwipeableViews>
      </div>
    );
  }

  onNavClick (activecard) {
    this.setState({
      activecard
    });
  }
}

export default Carousel;

React Carousel Class Explained

Above the class definition, we’re importing react-swipeable-views which we’ll use to wrap the child card items in the render method (described below). The static defaultProps property sets the defaults for various props on the Carousel. The constructor method sets the initial state and activecard property and the onNavClick method handles the nav element click that sets the activecard property which then styles the active nav element and shows the associated child card. The render method:

  • Combines any className string passed in with those added by the class
  • Collects the activecard from the component state object to inform the nav elements / cards which is currently active / visible
  • In the return:
    • Create the wrapping Carousel element that will house the nav element container and card container
    • The nav element container is added and we iterate over the child nodes (cards) passed to the Carousel to create navigation elements. The active nav element is styled as active when the cardindex matches the activecard.
    • A react-swipeable-views instance, SwipeableViews, is added to enclose the child cards passed to the Carousel. SwipeableViews enables the swiping of cards into view in addition to interacting with the nav elements.
    • We loop over the child nodes, this time calling React.cloneElement in order to add a few props like className, cardindex, and activecard to the original nodes that were passed in. The cloneElement method allows us to effectively extend the child items by taking on additional props as needed. The cloned elements are returned in an array to be the child nodes of the SwipeableViews parent. The card whose cardindex matches the activeitem is shown while the other cards are hidden using CSS rules.

React Carousel CSS

The CSS used to render the Carousel view:

.carousel {
  position: relative;
}
 
.nav-strip {
  display: flex;
  justify-content: center;
  position: absolute;
  pointer-events: none;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1;
}
.nav-strip + div,
.nav-strip + div .react-swipeable-view-container {
  height: 100%;
  width: 100%;
}
.carousel.top .nav-strip {
  bottom: auto;
}
.carousel.bottom .nav-strip {
  top: auto;
}
.carousel.left .nav-strip {
  right: auto;
}
.carousel.right .nav-strip {
  left: auto;
}
.carousel.top .nav-strip,
.carousel.bottom .nav-strip {
  flex-direction: row;
}
.carousel.left .nav-strip,
.carousel.right .nav-strip {
  flex-direction: column;
}
 
.react-swipeable-view-container > div {
  flex-basis: 100%;
  background: #f7f7f7;
}
 
.nav {
  text-align: center;
  cursor: pointer;
  pointer-events: all;
}
 
.carousel.top .nav,
.carousel.bottom .nav {
  padding: 12px 6px;
}
.carousel.left .nav,
.carousel.right .nav {
  padding: 6px 12px;
}
 
.nav-strip .nav-dot {
  background-color: #d2d2d2;
  border-radius: 50%;
  height: 12px;
  width: 12px;
  display: inline-block;
}
.nav-strip .nav:hover .nav-dot {
  background-color: #b5b5b5;
}
.nav-strip .nav.active .nav-dot {
  background-color: #1e8bfb;
}
 
.carousel .card {
  padding: 12px;
}
React Carousel Example
We can create a Carousel instance like:

import React, { Component } from 'react';
import Carousel from './Carousel';

class App extends Component {
  render() {
    return (
      <Carousel style={{ height: '400px', width: '600px' }}>
        <div>Content for the first panel</div>
        <div>... and the second panel</div>
      </Carousel>
    );
  }
}

export default App;
Ext JS to React: Carousel, Panel

We pass in the style prop to give the rendered component explicit dimensions. We can pass a position prop to position the navigation indicators on the “top” or “bottom”. An activecard prop can also be passed to designate the initially active card view.

Conclusion

Hopefully the example demonstrates how easy it will be to get a carousel view built for your React applications. The example is relatively basic, but gets the job done for the most common use cases. It would be fairly easy to enhance the example and allow the carousel instance to stipulate whether the carousel is oriented horizontally as shown, or vertical. However, if you’re looking for a pre-built slider, look no further than react-slick for a very performant and highly configurable carousel view.

Posted in Application Development
Share this

Mitchell Simoens

Mitchell Simoens is a Senior Front End Engineer at Modus Create. Mitchell has spent the last 10 years working with Ext JS including developing core functionality, Sencha Fiddle and (I hope your insurance covers blown minds) supporting the online community with over 40,000 posts on the Sencha Forums. Before working with Ext JS, Mitchell used Perl and PHP but loves spending time with Node JS for today's needs. When not working, you can find Mitchell relaxing with his wife and daughter, or developing his talents as an amateur furniture maker.
Follow

Related Posts

  • React Landing
    Ext JS to React: Migration to Open Source

    Worried about Migrating from Ext JS? Modus has the Answers Idera’s acquisition of Sencha has…

  • Ext JS to React: FAQ
    Ext JS to React: FAQ

    This is part of the Ext JS to React blog series. React is Facebook's breakout…

Want more insights to fuel your innovation efforts?

Sign up to receive our monthly newsletter and exclusive content about digital transformation and product development.

What we do

Our services
AI and data
Product development
Design and UX
IT modernization
Platform and MLOps
Developer experience
Security

Our partners
Atlassian
AWS
GitHub
Other partners

Who we are

Our story
Careers
Open source

Our work

Our case studies

Our resources

Blog
Innovation podcast
Guides & playbooks

Connect with us

Get monthly insights on AI adoption

© 2025 Modus Create, LLC

Privacy PolicySitemap
Scroll To Top
  • Services
  • Work
  • Blog
  • Resources
    • Innovation Podcast
    • Guides & Playbooks
  • Who we are
    • Our story
    • Careers
  • Let’s talk
  • EN
  • FR