<ImageCarousel />

A slideshow component for cycling through images like a carousel.

Component

1import React, { useState } from "react";
2import "./Styles/_imagecarousel.scss";
3
4export default function ImageCarousel({ ...props }) {
5 const { children } = props;
6 const [currentImg, setCurrentImage] = useState(0);
7
8 const childrenWithProps = React.Children.map(children, (child, index) => {
9 if (React.isValidElement(child)) {
10 return React.cloneElement(child, { currentImg, index });
11 }
12 return child;
13 });
14
15 const prev = () => setCurrentImage((currentImg) => currentImg - 1);
16 const next = () => setCurrentImage((currentImg) => currentImg + 1);
17
18 return (
19 <div className="Image-Carousel">
20 {currentImg > 0 && (
21 <button onClick={prev} className="prev">
22 <i className="fas fa-chevron-circle-left" />
23 </button>
24 )}
25
26 {currentImg < children.length - 1 && (
27 <button onClick={next} className="next">
28 <i className="fas fa-chevron-circle-right" />
29 </button>
30 )}
31
32 <div>
33 {children.map((element, idx, array) => (
34 <button
35 key={idx}
36 onClick={() => setCurrentImage(idx)}
37 className={idx === currentImg ? "isActive" : ""}
38 />
39 ))}
40 </div>
41 <ul>{childrenWithProps}</ul>
42 </div>
43 );
44}
45
46export { CarouselItem } from "./Components/CarouselItem";

Styles

1$properties: (
2 Nav-Btn-Position: 0.5rem,
3);
4
5.Image-Carousel {
6 width: 700px;
7 height: 500px;
8 position: relative;
9
10 & > div {
11 position: absolute;
12 background-color: white;
13 border-radius: 5px;
14 z-index: 2;
15 bottom: 5px;
16 left: 50%;
17 transform: translateX(-50%);
18
19 & button {
20 border: none;
21 border-radius: 50%;
22 width: 10px;
23 height: 10px;
24 background: hsl(0, 0%, 66%);
25 margin: 0px 4px;
26 cursor: pointer;
27 padding: 0;
28
29 &.isActive {
30 background: hsl(0, 0%, 15%);
31 }
32 }
33 }
34
35 & > button {
36 position: absolute;
37 background: none;
38 z-index: 2;
39 border: none;
40 color: white;
41 font-size: 1.25rem;
42 top: 50%;
43 transform: translateY(-50%);
44 cursor: pointer;
45
46 &:hover,
47 &:focus {
48 color: white;
49 }
50
51 &.prev {
52 left: map-get($properties, Nav-Btn-Position);
53 }
54
55 &.next {
56 right: map-get($properties, Nav-Btn-Position);
57 }
58 }
59
60 & ul {
61 margin: 0;
62 padding: 0;
63 list-style: none;
64 }
65
66 & li {
67 position: absolute;
68 inset: 0;
69 opacity: 0;
70 transition: 200ms opacity ease-in-out;
71 transition-delay: 200ms;
72
73 & > img {
74 display: block;
75 width: 100%;
76 height: 100%;
77 object-fit: cover;
78 object-position: center;
79 }
80
81 &.isActive {
82 opacity: 1;
83 z-index: 1;
84 transition-delay: 0ms;
85 }
86 }
87}

Usage

1