I am working on a project with a setup combination of react, tailwind and react icons. In my project multiple sliders are required (some has navigation, some has pagination etc…)
So, I created a slider factory component Carousel
and controlling variation through props
// Carousel/index.jsx
import { Children, useState } from "react";
import { v4 as uuidv4 } from "uuid";
import { HiOutlineArrowLeft, HiOutlineArrowRight } from "react-icons/hi";
import { Swiper, SwiperSlide } from "swiper/react";
import { Autoplay, Keyboard, Mousewheel, Navigation, Pagination } from "swiper";
import "swiper/css";
import "swiper/css/pagination";
import "swiper/css/navigation";
import NextSlideBtn from "./NextSlideBtn";
import PrevSlideBtn from "./PrevSlideBtn";
const Carousel = ({
children,
loop,
pagination,
navigation,
autoplay,
breakpoints,
}) => {
const childrenArray = Children.toArray(children);
const [swiperRef, setSwiperRef] = useState();
return (
<div className="group relative">
<Swiper
className="rounded overflow-hidden"
onSwiper={setSwiperRef}
modules={[
Autoplay,
Keyboard,
Mousewheel,
Pagination,
Navigation,
]}
mousewheel
keyboard
grabCursor
loop={loop || false}
autoplay={
autoplay && {
delay: 5000,
disableOnInteraction: true,
}
}
spaceBetween={breakpoints && 20}
breakpoints={
breakpoints && {
450: {
slidesPerView: 2,
},
768: {
slidesPerView: 3,
},
1536: {
slidesPerView: 4,
},
}
}
pagination={
pagination && {
clickable: true,
}
}
>
{childrenArray.map((item) => (
<SwiperSlide key={uuidv4()}>{item}</SwiperSlide>
))}
</Swiper>
{navigation && (
<div className="hidden group-hover:block">
<PrevSlideBtn swiperRef={swiperRef}>
<HiOutlineArrowLeft className="text-violet-600" />
</PrevSlideBtn>
<NextSlideBtn swiperRef={swiperRef}>
<HiOutlineArrowRight className="text-violet-600" />
</NextSlideBtn>
</div>
)}
</div>
);
};
export default Carousel;
// Carousel/NextSlideBtn.jsx
const NextSlideBtn = ({ children, swiperRef }) => {
const handleNextSlide = () => swiperRef.slideNext();
return (
<button
onClick={handleNextSlide}
className="absolute z-50 top-1/2 -translate-y-1/2 -right-2 translate-x-2 bg-white shadow-md rounded-full p-3"
>
{children}
</button>
);
};
export default NextSlideBtn;
// Carousel/PrevSlideBtn.jsx
const PrevSlideBtn = ({ children, swiperRef }) => {
const handlePrevSlide = () => swiperRef.slidePrev();
return (
<button
onClick={handlePrevSlide}
className="absolute z-50 top-1/2 -translate-y-1/2 -left-2 -translate-x-2 bg-white shadow-md rounded-full p-3"
>
{children}
</button>
);
};
export default PrevSlideBtn;
One of the requirement was to create custom navigation button, which I managed to accomplish as you can see in the code above, but for more visibility I am marking the flow in short
// Carousel/index.jsx
const [swiperRef, setSwiperRef] = useState();
<div>
<Swiper
onSwiper={setSwiperRef}
...
>
...
</Swiper>
<PrevSlideBtn swiperRef={swiperRef} />
<NextSlideBtn swiperRef={swiperRef} />
</div>
// Carousel/NextSlideBtn.jsx
const NextSlideBtn = ({ children, swiperRef }) => {
const handleNextSlide = () => swiperRef.slideNext();
return (
<button
onClick={handleNextSlide}
...
>
{children}
</button>
);
};
export default NextSlideBtn;
// Carousel/PrevSlideBtn.jsx
const PrevSlideBtn = ({ children, swiperRef }) => {
const handlePrevSlide = () => swiperRef.slidePrev();
return (
<button
onClick={handlePrevSlide}
...
>
{children}
</button>
);
};
export default PrevSlideBtn;
Couple of github issues, stackoverflow questions and swiper docs helped me out to accomplish this, and it was pretty straight forward to understand.
Now my question is how can I customize swiper react pagination (like radio buttons which some websites use, or any other styles…) using tailwind and I want to make it as a separate component like I did for navigation buttons.
I’ve tried many solutions eg:
const paginationBullets = {
type: "custom",
clickable: true,
renderCustom: (_, current, total) => {
return <MyCustomSwiperPaginationComponent current={current} total={total} />;
},
};
But nothing seems to work as expected.
Please help me out.
Component separation is my goal.