Modern Testimonials in React Tutorial
Tags: react, testimonials, npm
Published: 2020-07-15 00:09:51

Update: I wrote this when my CSS skills weren't too great, so please avoid !important for best practice :)

In this blog I will be sharing a short tutorial on how to add modern testimonials to your ReactJS project. When I first started searching the web for a clean solution, I was overwhelmed by the different approaches to accomplishing this. Eventually, I found a customizable carousel component for React, and used CSS to give it a nice look and feel.

<h3>React Configuration</h3>
1) Create React App
``` npx create-react-app my-app
cd my-app
npm start ```

2) Install <a href="https://www.npmjs.com/package/react-responsive-carousel">react-responsive-carousel</a>

``` npm i react-responsive-carousel ```

3) Create Testimonals.js

``` javascript
import React, { Component } from "react";
import "react-responsive-carousel/lib/styles/carousel.min.css"; // requires a loader
import { Carousel } from 'react-responsive-carousel';

export default class Testimonials extends Component {
  render() {
    return (
      <Carousel>
        <div>
          <img src="assets/1.jpeg" />
          <p className="legend">Legend 1</p>
        </div>
        <div>
          <img src="assets/2.jpeg" />
          <p className="legend">Legend 2</p>
        </div>
        <div>
          <img src="assets/3.jpeg" />
          <p className="legend">Legend 3</p>
        </div>
      </Carousel>
    );
  }
}
```

4) Import Testimonials into App.js
``` javascript
import React from "react";
import logo from "./logo.svg";
import "./App.css";
import Testimonials from "./Testimonials.js";

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <h1>Testimonials</h1>
        <Testimonials />
      </header>
    </div>
  );
}

export default App;
```
<h4>What You Should See Now:</h4>
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/lsooxlqkh9tzob5h64l2.png)<hr>
<h2>Now Let's Customize!</h2>

<h3>1. Updating Testimonials</h3>
To help set you up with a nice template, here is an updated Testimonials.js file that I'm borrowing from one of my projects.

``` javascript
import React, { Component } from "react";
import "react-responsive-carousel/lib/styles/carousel.min.css";
import { Carousel } from "react-responsive-carousel";

export default class Testimonials extends Component {
  render() {
    return (
      <Carousel
        showArrows={true}
        infiniteLoop={true}
        showThumbs={false}
        showStatus={false}
        autoPlay={true}
        interval={6100}
      >
        <div>
          <img src="/images/shirley.png" />
          <div className="myCarousel">
            <h3>Shirley Fultz</h3>
            <h4>Designer</h4>
            <p>
              It's freeing to be able to catch up on customized news and not be
              distracted by a social media element on the same site
            </p>
          </div>
        </div>

        <div>
          <img src="/images/daniel.png" />
          <div className="myCarousel">
            <h3>Daniel Keystone</h3>
            <h4>Designer</h4>
            <p>
              The simple and intuitive design makes it easy for me use. I highly
              recommend Fetch to my peers.
            </p>
          </div>
        </div>

        <div>
          <img src="/images/theo.png" />
          <div className="myCarousel">
            <h3>Theo Sorel</h3>
            <h4>Designer</h4>
            <p>
              I enjoy catching up with Fetch on my laptop, or on my phone when
              I'm on the go!
            </p>
          </div>
        </div>
      </Carousel>
    );
  }
}
```

<h3>2. Updating Images</h3>
1) Create an images folder inside the "public" folder.

2) Add three images. I've named my images: shirley, daniel, and theo.
<div>
<img src="https://dev-to-uploads.s3.amazonaws.com/i/9dhr4cw2s0skgfig8qnw.png" width="100px">
<img src="https://dev-to-uploads.s3.amazonaws.com/i/81co8nilff5r9eer3xga.png" width="100px">
<img src="https://dev-to-uploads.s3.amazonaws.com/i/1xwiaya5i7wweic3pz96.png" width="100px" display="flex">
</div>

<h3>3) Updating CSS</h3>
``` css
.carousel-root {
  width: 64% !important;
  margin: auto !important;
  margin-top: 3% !important;
}

.carousel .slide {
  background: #fff !important;
  color: black;
  height: 100%;
}

.carousel .slide img {
  width: 139px !important;
  border-radius: 50%;
}

.myCarousel {
  background: #fafafa;
  margin-top: -6%;
  width: 54%;
  margin-left: auto;
  margin-right: auto;
  padding-top: 6%;
  padding-bottom: 8%;
  padding-left: 5%;
  padding-right: 5%;
  border: 1px solid #ddd;
  height: 286px;
}

.carousel .control-dots {
  padding-left: 5px !important;
  outline: 0;
  bottom: 5% !important;
}

.myCarousel h3 {
  color: #222;
  font-weight: 100;
  letter-spacing: 0.2px;
  margin-bottom: 4px;
  font-weight: 600;
  text-transform: uppercase;
  font-size: 17px;
}

.myCarousel h4 {
  text-transform: uppercase;
  margin-top: 0;
  padding-top: 0;
  font-weight: 500;
  color: #787878;
  font-size: 14px;
}

.myCarousel p {
  font-weight: 100 !important;
  line-height: 29px !important;
  color: #222;
  font-size: 15px;
  font-family: sans-serif;
  max-height: 67px;
}

.myCarousel p:before {
  content: "“";
  color: #aaa;
  font-size: 26px;
  font-family: monospace;
  font-weight: 100;
}

.myCarousel p:after {
  content: "”";
  color: #aaa;
  font-size: 26px;
  font-family: monospace;
  font-weight: 100;
  line-height: 0;
}

.carousel .control-dots .dot {
  box-shadow: none !important;
  background: #454545 !important;
  outline: 0;
}

.carousel.carousel-slider .control-arrow {
  background: #000 !important;
  height: 50px !important;
  position: absolute;
  top: 35% !important;
}

.App {
  text-align: center;
}

@media only screen and (max-width: 934px) {
  .carousel-root {
    outline: 0;
    width: 93% !important;
    margin: auto !important;
  }

  .carousel.carousel-slider .control-arrow {
    display: none !important;
  }
  .myCarousel {
    background: #fafafa;
    margin-top: -9%;
    width: 88%;
    margin-left: auto;
    margin-right: auto;
    padding-top: 8%;
    padding-bottom: 12.5%;
    padding-left: 5%;
    padding-right: 5%;
    border: 1px solid #ddd;
    height: 269px;
  }

  .carousel .slide img {
    width: 24% !important;
    border-radius: 50%;
  }
}
```
<b>Important:</b> The CSS becomes a bit hacky because we are importing pre-defined styles from "react-responsive-carousel/lib/styles/carousel.min.css". If you have the time, you can sort out the conflicting selectors and rules.

<b>Note:</b> I've removed the arrows in viewport screens below 935px given the limited real-estate.

<h3>End Result</h3>
<img src="https://i.imgur.com/fOtMSIS.gif">