I customerized the arrow shape and color of swiper js by adding svg, but it did not have any functionality. And I ended up having two sets of arrows on each side, one is my own arrow button which does not function, the other one is built in swiper js arrow which functions well.
so how to replace swiper's arrow with my own arrow that functions well?
import React from "react";
import sportsList from "../utils/sportsList";
import Card from "./Card";
import { Swiper, SwiperSlide } from "swiper/react";
import "swiper/css";
import "swiper/css/navigation";
import { Navigation } from "swiper";
export default function SliderComponent() {
return (
<>
<Swiper
spaceBetween={50}
slidesPerView={4}
onSlideChange={() => console.log("slide change")}
onSwiper={(swiper) => console.log(swiper)}
grabCursor={true}
modules={[Navigation]}
navigation={true}
breakpoints={{
// when window width is >= 320px
320: {
slidesPerView: 1,
spaceBetween: 24,
},
// when window width is >= 480px
480: {
slidesPerView: 2,
spaceBetween: 24,
},
// when window width is >= 640px
640: {
slidesPerView: 6,
spaceBetween: 24,
},
1024: {
slidesPerView: 6,
spaceBetween: 32,
slidesPerGroup: 1,
},
1336: {
slidesPerView: 6,
spaceBetween: 32,
},
}}
className="relative w-10/12 mx-auto flex flex-row"
>
<div className="absolute inset-y-0 left-0 z-10 flex items-center">
<button class="bg-white -ml-2 lg:-ml-4 flex justify-center items-center w-10 h-10 rounded-full shadow focus:outline-none">
<svg
viewBox="0 0 20 20"
fill="currentColor"
class="chevron-left w-6 h-6"
>
<path
fill-rule="evenodd"
d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z"
clip-rule="evenodd"
></path>
</svg>
</button>
</div>
{sportsList.map((item) => {
return (
<SwiperSlide key={item.id}>
<Card item={item} />
</SwiperSlide>
);
})}
<div class="absolute inset-y-0 right-0 z-10 flex items-center">
<button class="bg-white -mr-2 lg:-mr-4 flex justify-center items-center w-10 h-10 rounded-full shadow focus:outline-none">
<svg
viewBox="0 0 20 20"
fill="currentColor"
class="chevron-right w-6 h-6"
>
<path
fill-rule="evenodd"
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
clip-rule="evenodd"
></path>
</svg>
</button>
</div>
</Swiper>
</>
);
}
To customize previous and next button in swiper.js you should pass NavigationOptions object to navigation instead of true, something like this will do it:
navigation={{
nextEl: ".image-swiper-button-next",
prevEl: ".image-swiper-button-prev",
disabledClass: "swiper-button-disabled"
}}
and then you can use those classnames for your buttons
don't forget to remove this import "swiper/css/navigation"; so it won't override your navigation button styles
you can see an example below
import React from "react";
import sportsList from "../utils/sportsList";
import Card from "./Card";
import { Swiper, SwiperSlide } from "swiper/react";
import "swiper/css";
import "swiper/css/navigation";
import { Navigation } from "swiper";
import "swiper/css/bundle";
import SwiperCore from "swiper";
SwiperCore.use([Navigation]);
export default function SliderComponent() {
return (
<>
<Swiper
spaceBetween={50}
slidesPerView={4}
slidesPerGroup={3}
onSlideChange={() => console.log("slide change")}
onSwiper={(swiper) => console.log(swiper)}
grabCursor={true}
navigation={{
prevEl: ".swiper-button-prev",
nextEl: ".swiper-button-next",
}}
breakpoints={{
// when window width is >= 320px
320: {
slidesPerView: 1,
spaceBetween: 24,
},
// when window width is >= 480px
480: {
slidesPerView: 2,
spaceBetween: 24,
},
// when window width is >= 640px
640: {
slidesPerView: 2,
spaceBetween: 24,
},
1024: {
slidesPerView: 4,
spaceBetween: 32,
slidesPerGroup: 1,
},
1336: {
slidesPerView: 6,
spaceBetween: 32,
},
}}
tag="section"
wrapperTag="ul"
id="main"
style={{
"--swiper-navigation-color": "red",
"--swiper-navigation-size": "150px",
}}
className="relative w-10/12 mx-auto flex flex-row"
>
<div className="absolute inset-y-0 left-0 z-10 flex items-center">
<button className=" swiper-button-prev bg-white -ml-2 lg:-ml-4 flex justify-center items-center w-10 h-10 rounded-full shadow focus:outline-none"></button>
</div>
Related
I am trying to replicate the scroll functionality (both video and text) from this website, except my video is a long lottie file.
I am using the following frameworks: Nextjs, React, Tailwind
The code below is after many failed attempts. I'm unable to keep the lottie fixed and make it look like one continuous animation. When the position is sticky/fixed it isn't animated on scroll for some reason. Would really appreciate some help. Thank you.
import Head from 'next/head'
import backgroundImage from '#/images/background-faqs.jpg'
import Image from 'next/future/image'
import { CallToAction } from '#/components/CallToAction'
import { Faqs } from '#/components/Faqs'
import { Footer } from '#/components/Footer'
import { Header } from '#/components/Header'
import { Hero } from '#/components/Hero'
import { Pricing } from '#/components/Pricing'
import { PrimaryFeatures } from '#/components/PrimaryFeatures'
import { SecondaryFeatures } from '#/components/SecondaryFeatures'
import { testimonials } from '#/components/testimonials'
import React, { useState } from 'react'
import { useLottie, useLottieInteractivity } from 'lottie-react'
import likeButton from '../images/lottie.json'
const options = {
animationData: likeButton,
}
const LottieAnimation = () => {
const lottieObj = useLottie(options)
const Animation = useLottieInteractivity({
lottieObj,
mode: 'scroll',
container: 'lottie_container',
actions: [
{
visibility: [0, 0.3],
type: 'stop',
frames: [0],
},
{
visibility: [0.3, 0.7],
type: 'seek',
frames: [0, 100],
},
{
visibility: [0.7, 1.0],
type: 'stop',
frames: [100],
},
],
})
return Animation
}
const LottieAnimation2 = () => {
const lottieObj = useLottie(options)
const Animation = useLottieInteractivity({
lottieObj,
mode: 'scroll',
container: 'lottie_container',
actions: [
{
visibility: [0, 0.3],
type: 'stop',
frames: [100],
},
{
visibility: [0.3, 0.7],
type: 'seek',
frames: [100, 107],
},
{
visibility: [0.7, 1.0],
type: 'stop',
frames: [107],
},
],
})
return Animation
}
const LottieAnimation3 = () => {
const lottieObj = useLottie(options)
const Animation = useLottieInteractivity({
lottieObj,
mode: 'scroll',
container: 'lottie_container',
actions: [
{
visibility: [0, 0.3],
type: 'stop',
frames: [107],
},
{
visibility: [0.4, 0.6],
type: 'seek',
frames: [107, 115],
},
{
visibility: [0.7, 1.0],
type: 'stop',
frames: [115],
},
],
})
return Animation
}
const LottieAnimation4 = () => {
const lottieObj = useLottie(options)
const Animation = useLottieInteractivity({
lottieObj,
mode: 'scroll',
container: 'lottie_container',
actions: [
{
visibility: [0, 0.3],
type: 'stop',
frames: [0],
},
{
visibility: [0.4, 0.6],
type: 'seek',
frames: [0, 100],
},
{
visibility: [0.7, 1.0],
type: 'seek',
frames: [100, 0],
},
],
})
return Animation
}
const LottieAnimation5 = () => {
const lottieObj = useLottie(options)
const Animation = useLottieInteractivity({
lottieObj,
mode: 'scroll',
container: 'lottie_container',
actions: [
{
visibility: [0, 0.3],
type: 'stop',
frames: [0],
},
{
visibility: [0.4, 0.6],
type: 'seek',
frames: [0, 100],
},
{
visibility: [0.7, 1.0],
type: 'seek',
frames: [100, 0],
},
],
})
return Animation
}
export default function Home() {
return (
<>
<div class="absolute inset-x-0 top-[-10rem] -z-10 transform-gpu overflow-hidden blur-3xl sm:top-[-20rem]">
<svg
class="relative left-[calc(50%-11rem)] -z-10 h-[21.1875rem] max-w-none -translate-x-1/2 rotate-[30deg] sm:left-[calc(50%-30rem)] sm:h-[42.375rem]"
viewBox="0 0 1155 678"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill="url(#45de2b6b-92d5-4d68-a6a0-9b9b2abad533)"
fill-opacity=".25"
d="M317.219 518.975L203.852 678 0 438.341l317.219 80.634 204.172-286.402c1.307 132.337 45.083 346.658 209.733 145.248C936.936 126.058 882.053-94.234 1031.02 41.331c119.18 108.451 130.68 295.337 121.53 375.223L855 299l21.173 362.054-558.954-142.079z"
/>
<defs>
<linearGradient
id="45de2b6b-92d5-4d68-a6a0-9b9b2abad533"
x1="1155.49"
x2="-78.208"
y1=".177"
y2="474.645"
gradientUnits="userSpaceOnUse"
>
<stop stop-color="#9089FC"></stop>
<stop offset="1" stop-color="#FF80B5"></stop>
</linearGradient>
</defs>
</svg>
</div>
<Head>
<title>name</title>
<meta name="description" content="need to fill" />
</Head>
<Header />
<main>
<div>
<Hero />
<div class="absolute inset-x-0 top-[calc(100%-13rem)] -z-10 transform-gpu overflow-hidden blur-3xl sm:top-[calc(100%-30rem)]">
<svg
class="relative left-[calc(50%+3rem)] h-[21.1875rem] max-w-none -translate-x-1/2 sm:left-[calc(50%+36rem)] sm:h-[42.375rem]"
viewBox="0 0 1155 678"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill="url(#ecb5b0c9-546c-4772-8c71-4d3f06d544bc)"
fill-opacity=".3"
d="M317.219 518.975L203.852 678 0 438.341l317.219 80.634 204.172-286.402c1.307 132.337 45.083 346.658 209.733 145.248C936.936 126.058 882.053-94.234 1031.02 41.331c119.18 108.451 130.68 295.337 121.53 375.223L855 299l21.173 362.054-558.954-142.079z"
/>
<defs>
<linearGradient
id="ecb5b0c9-546c-4772-8c71-4d3f06d544bc"
x1="1155.49"
x2="-78.208"
y1=".177"
y2="474.645"
gradientUnits="userSpaceOnUse"
>
<stop stop-color="#9089FC"></stop>
<stop offset="1" stop-color="#FF80B5"></stop>
</linearGradient>
</defs>
</svg>
</div>
</div>
<div id="lottie_container" class="flex scroll-smooth">
<div class="ml-auto inline-block w-full md:w-5/12">
<div class="flex h-screen flex-col items-center justify-center">
<LottieAnimation />
</div>
<div class="flex h-screen flex-col items-center justify-center">
<LottieAnimation2 />
</div>
<div class="flex h-screen flex-col items-center justify-center">
<LottieAnimation3 />
</div>
<div class="flex h-screen flex-col items-center justify-center">
<LottieAnimation4 />
</div>
<div class="flex h-screen flex-col items-center justify-center">
<LottieAnimation5 />
</div>
</div>
<div class="ml-auto inline-block w-full md:w-5/12">
<div class="flex h-screen flex-col items-center justify-center">
<h2 class="mb-5 text-4xl">Animation 1</h2>
<p class="mb-5">description</p>
</div>
<div class="flex h-screen flex-col items-center justify-center">
<h2 class="mb-5 text-4xl">Animation 2</h2>
<p class="mb-5">description</p>
</div>
<div class="flex h-screen flex-col items-center justify-center">
<h2 class="mb-5 text-4xl">Animation 3</h2>
<p class="mb-5">description</p>
</div>
<div class="flex h-screen flex-col items-center justify-center">
<h2 class="mb-5 text-4xl">Animation 4</h2>
<p class="mb-5">description</p>
</div>
<div class="flex h-screen flex-col items-center justify-center">
<h2 class="mb-5 text-4xl">Animation 5</h2>
<p class="mb-5">description</p>
</div>
</div>
</div>
<PrimaryFeatures />
<SecondaryFeatures />
<CallToAction />
<testimonials />
<Pricing />
<Faqs />
</main>
<Footer />
</>
)
}
Stack: NextJS, JavaScript, React, Tailwind, Framer Motion
I've scoured the web for answers to this but mostly the answers were saying that the <div> that wraps the image must have a position of relative. I tried this and it didn't change anything.
Code for the text and images:
import React from "react";
import { motion } from "framer-motion";
import Image from "next/image";
export default function Card({ image, name, description }) {
return (
<motion.div
className="flex justify-center mt-5"
initial="hidden"
animate="visible"
variants={{
hidden: { scale: 0.9, opacity: 0 },
visible: {
scale: 1,
opacity: 1,
transition: { delay: 0.3, ease: [0.17, 0.67, 0.83, 0.67] },
},
}}
>
<div className="relative">
<Image
className="rounded-full absolute"
src={image}
width={100}
height={100}
alt="Leader profile picture"
/>
</div>
<div>
<motion.h1
className="text-xl pl-1 font-bourton"
initial="hidden"
animate="visible"
variants={{
hidden: { scale: 0.9, opacity: 0 },
visible: {
scale: 1,
opacity: 1,
transition: { delay: 0.35, ease: [0.17, 0.67, 0.83, 0.67] },
},
}}
>
{name}
</motion.h1>
<motion.p className="text-sm p-3 text-wrap w-48 text-slate-600 font-bourton">
{description}
</motion.p>
</div>
</motion.div>
);
}
The code for the sidebar:
import { useState } from "react";
import { motion } from "framer-motion";
import classnames from "classnames";
import { useRouter } from "next/router";
const path01Variants = {
open: { d: "M3.06061 2.99999L21.0606 21" },
closed: { d: "M0 9.5L24 9.5" },
};
const path02Variants = {
open: { d: "M3.00006 21.0607L21 3.06064" },
moving: { d: "M0 14.5L24 14.5" },
closed: { d: "M0 14.5L15 14.5" },
};
const Sidebar = () => {
const [showSidebar, setShowSidebar] = useState(false);
const [animation, setAnimation] = useState("closed");
const router = useRouter();
const onClick = () => {
setAnimation("moving");
setTimeout(() => {
setAnimation(animation === "closed" ? "open" : "closed");
}, 200);
setShowSidebar(!showSidebar);
};
return (
<>
{showSidebar ? (
<button
className="flex justify-center relative z-100 items-center w-12 h-12 border border-black rounded-full"
onClick={onClick}
>
<svg width="24" height="24" viewBox="0 0 24 24">
<motion.path
stroke="#fff"
animate={animation}
variants={path01Variants}
/>
<motion.path
stroke="#fff"
animate={animation}
variants={path02Variants}
/>
</svg>
</button>
) : (
<button
className="flex justify-center top-12 right-12 items-center w-12 h-12 border border-black rounded-full"
onClick={onClick}
>
<svg width="24" height="24" viewBox="0 0 24 24">
<motion.path
stroke="#000"
animate={animation}
variants={path01Variants}
/>
<motion.path
stroke="#000"
animate={animation}
variants={path02Variants}
/>
</svg>
</button>
)}
<div
className={` bg-unionred border-black opacity-90 top-0 right-0 lg:w-[35vw] sm:w-[50vw] p-10 pl-20 fixed text-white h-full ease-in-out duration-300 ${
showSidebar ? "translate-x-0" : "translate-x-full"
}`}
>
<button
className="flex justify-center absolute top-8 right-8 items-center w-12 h-12 border border-white rounded-full"
onClick={onClick}
>
<svg width="24" height="24" viewBox="0 0 24 24">
<motion.path
stroke="#fff"
animate={animation}
variants={path01Variants}
/>
<motion.path
stroke="#fff"
animate={animation}
variants={path02Variants}
/>
</svg>
</button>
<h3 className="mt-20 text-4xl underline font-bourton text-white">
<button className="underline" onClick={() => router.push("whoweare")}>
Who We Are
</button>
</h3>
<h3 className="mt-20 text-4xl font-bourton text-white">
<button
className="underline"
onClick={() => router.push("ourleaders")}
>
Our Leaders
</button>
</h3>
<h3 className="mt-20 text-4xl font-bourton text-white">
<button className="underline">News</button>
</h3>
</div>
</>
);
};
export default Sidebar;
Before opening sidebar
After opening sidebar
Any help would be appreciated! Thank you.
It looks like you're not applying a z-index to the sidebar itself. That <div> is the container that needs to overlap the main content, so that is where you need to add the utility class.
Additionally, it looks like you're trying to use z-100 which is not one of the Tailwind defaults (see: https://tailwindcss.com/docs/z-index). You can either add that new value to your tailwind.config.js or try z-50, which is the highest default.
For example:
<div className={`z-50 bg-unionred border-black opacity-90 top-0 right-0 lg:w-[35vw] sm:w-[50vw] p-10 pl-20 fixed text-white h-full ease-in-out duration-300 ${showSidebar ? "translate-x-0" : "translate-x-full"}`}>
below is a code for a stepper that displays certain text in each step , the number of the steps is highlighted (by changing the background color of the step number) , and it will display a text beneath it , my issue is i wanted to use framer-motion with AnimatePresense and exit prop for the transitioning from one text to another but its not wokring , i would appreciate the feed back
below is the animation variants
export const instructionVariant = {
hidden: {
opacity: 0,
x: "100vw",
},
visible: {
opacity: 1,
x: 0,
transition: {
type: "spring",
mass: 0.7,
damping: 7,
ease: "easeIn",
},
},
exit: {
x: "-100vw",
opacity: 0,
transition: { duration: 0.5, ease: "easeInOut" },
},
};
export const paragraphVariant = {
hidden: {
opacity: 0,
x: "10hw",
},
visible: {
opacity: 1,
x: 0,
transition: {
type: "spring",
mass: 0.7,
damping: 7,
ease: "easeIn",
},
},
exit: {
x: "-5hw",
opacity: 0,
transition: { duration: 0.5, ease: "easeInOut" },
},
};
below is the code , i used redux-toolkit for this , if i need to ppost the code for it if needed
const Instructions: FC = () => {
const step = useAppSelector((state) => state.instruction.step);
const dispatch = useAppDispatch();
return (
<motion.div
variants={instructionVariant}
initial="hidden"
animate="visible"
exit="exit"
className="h-2/4 w-3/5 bg-primary-200 border-2 border-solid border-black rounded-lg shadow-lg shadow-black relative"
>
<div className="grid grid-rows-[1fr_4fr]">
<div className="flex justify-around items-center m-10">
{data.map((item: InstructionsProps) => {
return (
<>
<div>
<h1
className={
step >= item.id
? "flex justify-center items-center text-4xl rounded-full bg-secondary-100 text-white w-16 h-16 transition-all duration-300 ease-in"
: "flex justify-center items-center text-4xl rounded-full bg-primary-100 text-white w-16 h-16 transition-all duration-300 ease-in"
}
>
{item.id - 1}
</h1>
</div>
<div
className={
step > item.id
? "last:hidden text-secondary-100 transition-all duration-300 ease-in"
: "last:hidden transition-all duration-300 ease-in"
}
>
<FaArrowRight size={20} />
</div>
</>
);
})}
</div>
<AnimatePresence exitBeforeEnter>
<motion.h1
variants={paragraphVariant}
initial="hidden"
animate="visible"
exit="exit"
className="m-10 text-xl font-bold font-rubik"
>
{data[step - 1].description}
</motion.h1>
</AnimatePresence>
</div>
<div className="absolute right-6 bottom-6 flex justify-between items-center w-32">
<button
onClick={() => dispatch(instructionsAction.instructionreverse())}
className="hover:scale-125 active:scale-110 active:text-secondary-200 hover:text-secondary-200 transition-all duration-300 ease-in"
>
<HiOutlineChevronDoubleLeft size={35} />
</button>
<button
onClick={() => dispatch(instructionsAction.instructioncomplt())}
className="hover:scale-125 active:scale-110 active:text-secondary-200 hover:text-secondary-200 transition-all duration-300 ease-in"
>
<HiOutlineChevronDoubleRight size={35} />
</button>
</div>
</motion.div>
);
};
From the AnimatePresence docs:
Direct children must each have a unique key prop so AnimatePresence
can track their presence in the tree.
const MyComponent = ({ isVisible }) => (
<AnimatePresence>
{isVisible && (
<motion.div
key="modal"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
/>
)}
</AnimatePresence>
)
just having issues with populating the JSON into my chart. I'm seeing the response in the console log with API status with no errors, but for some reason, it's not populating it. Using Axios to fetch the example API to populate the emp sal and age. I have a feeling that I need to move the "UseEffect" somewhere but not sure where that needs to go.
import React, { useState, useEffect } from "react";
import { Link } from 'react-router-dom';
import LineChart from '../../charts/LineChart01';
import Icon from '../../images/icon-01.svg';
import EditMenu from '../EditMenu';
import axios from "axios";
// Import utilities
import { tailwindConfig, hexToRGB } from '../../utils/Utils';
const DashboardCard01 = () => {
const [chartData, setChartData] = useState({});
const [employeeSalary, setEmployeeSalary] = useState([]);
const [employeeAge, setEmployeeAge] = useState([]);
const chart = () => {
let empSal = [];
let empAge = [];
axios
.get("http://dummy.restapiexample.com/api/v1/employees")
.then(res => {
console.log(res);
for (const dataObj of res.data.data) {
empSal.push(parseInt(dataObj.employee_salary));
empAge.push(parseInt(dataObj.employee_age));
}
setChartData({
labels: empAge,
datasets: [
{
label: empAge,
data: empSal,
//backgroundColor: ["rgba(75, 192, 192, 0.6)"],
borderWidth: 4
}
]
});
})
.catch(err => {
console.log(err);
});
console.log(empSal, empAge);
datasets: [
// Indigo line
{
data: empAge,
fill: true,
backgroundColor: `rgba(${hexToRGB(tailwindConfig().theme.colors.blue[500])}, 0.08)`,
borderColor: tailwindConfig().theme.colors.indigo[500],
borderWidth: 2,
tension: 0,
pointRadius: 0,
pointHoverRadius: 3,
pointBackgroundColor: tailwindConfig().theme.colors.indigo[500],
clip: 20,
},
// Gray line
{
data: empSal,
borderColor: tailwindConfig().theme.colors.slate[300],
borderWidth: 2,
tension: 0,
pointRadius: 0,
pointHoverRadius: 3,
pointBackgroundColor: tailwindConfig().theme.colors.slate[300],
clip: 20,
},
]
};
useEffect(() => {
chart();
}, []);
return (
<div className="flex flex-col col-span-full sm:col-span-6 xl:col-span-4 bg-white shadow-lg rounded-sm border border-slate-200">
<div className="px-5 pt-5">
<header className="flex justify-between items-start mb-2">
{/* Icon */}
<img src={Icon} width="32" height="32" alt="Icon 01" />
{/* Menu button */}
<EditMenu className="relative inline-flex">
<li>
<Link className="font-medium text-sm text-slate-600 hover:text-slate-800 flex py-1 px-3" to="#0">Option 1</Link>
</li>
<li>
<Link className="font-medium text-sm text-slate-600 hover:text-slate-800 flex py-1 px-3" to="#0">Option 2</Link>
</li>
<li>
<Link className="font-medium text-sm text-rose-500 hover:text-rose-600 flex py-1 px-3" to="#0">Remove</Link>
</li>
</EditMenu>
</header>
<h2 className="text-lg font-semibold text-slate-800 mb-2">Acme Plus</h2>
<div className="text-xs font-semibold text-slate-400 uppercase mb-1">Sales</div>
<div className="flex items-start">
<div className="text-3xl font-bold text-slate-800 mr-2">$24,780</div>
<div className="text-sm font-semibold text-white px-1.5 bg-green-500 rounded-full">+49%</div>
</div>
</div>
{/* Chart built with Chart.js 3 */}
<div className="grow">
{/* Change the height attribute to adjust the chart height */}
<LineChart data={chartData} width={389} height={128} />
</div>
</div>
);
}
export default DashboardCard01;
I reused the promotion-slider.js swiper code in another FlashDealsProducts.js file with
some changes but without any error both components slides in same direction when I click
either of the slide button. I tried changing the id but it didn't worked.
Deleted dummy data of both file
Promotion-Slider.js file
import { ArrowNext, ArrowPrev } from "#components/icons";
import SwiperCore, { Navigation } from "swiper";
import { Swiper, SwiperSlide } from "swiper/react";
import "swiper/swiper-bundle.css";
const offerSliderBreakpoints = {
320: {
slidesPerView: 1,
spaceBetween: 0,
},
580: {
slidesPerView: 2,
spaceBetween: 16,
},
1024: {
slidesPerView: 3,
spaceBetween: 16,
},
1920: {
slidesPerView: 4,
spaceBetween: 24,
},
};
SwiperCore.use([Navigation]);
export default function PromotionSlider() {
return (
<div className="px-6 py-5 md:px-8 xl:px-12 md:py-10 border-t border-gray-200">
<div className="relative">
<Swiper
// id="offer"
loop={true}
breakpoints={offerSliderBreakpoints}
navigation={{
nextEl: ".next",
prevEl: ".prev",
}}
>
{data?.map((d) => (
<SwiperSlide key={d.id}>
<img
className="w-full h-auto"
src={d.bannerUrl}
alt={d.title}
width="430"
height="200"
/>
</SwiperSlide>
))}
</Swiper>
<div
className="prev cursor-pointer absolute top-2/4 -left-4 md:-left-5 z-10 -mt-4 md:-mt-5 w-8 h-8 md:w-9 md:h-9 rounded-full bg-white shadow-xl border border-gray-200 border-opacity-70 flex items-center justify-center text-gray-800 transition-all duration-200 hover:bg-primary hover:text-white hover:border-primary"
role="button"
>
<span className="sr-only">previous</span>
<ArrowPrev width={18} height={18} />
</div>
<div
className="next cursor-pointer absolute top-2/4 -right-4 md:-right-5 z-10 -mt-4 md:-mt-5 w-8 h-8 md:w-9 md:h-9 rounded-full bg-white shadow-xl border border-gray-200 border-opacity-70 flex items-center justify-center text-gray-800 transition-all duration-200 hover:bg-primary hover:text-white hover:border-primary"
role="button"
>
<span className="sr-only">next</span>
<ArrowNext width={18} height={18} />
</div>
</div>
</div>
);
}
FlashDealsProducts.js file
import Products from './Products.js';
import ProductCard from './ProductCard.js';
import { ArrowNext, ArrowPrev } from "#components/icons";
import SwiperCore, { Navigation } from "swiper";
import { Swiper, SwiperSlide } from "swiper/react";
import "swiper/swiper-bundle.css";
const SliderBreakpoints = {
320: {
slidesPerView: 1,
spaceBetween: 0,
},
580: {
slidesPerView: 2,
spaceBetween: 16,
},
1024: {
slidesPerView: 3,
spaceBetween: 16,
},
1920: {
slidesPerView: 4,
spaceBetween: 24,
},
};
SwiperCore.use([Navigation]);
export default function FlashDealProducts() {
return (
<div className='flex mt-14 flex-col'>
<div className='flex pl-1 flex-nowrap bg-white p-4'>
<h2 className=' flex-nowrap ml-7 font-bold text-lg'> Flash Deals </h2>
<span className='text-sm ml-20 font-light text-gray-800 '> Ends in </span>
<span className='px-1 ml-4 bg-red-700 text-white font-medium'> 10 hours</span>
</div>
<div className="px-6 py-5 md:px-8 xl:px-12 md:py-10 border-t bg-white border-gray-200">
<div className="relative">
<Swiper
id="flash-deals"
loop={true}
breakpoints={SliderBreakpoints}
navigation={{
nextEl: ".next",
prevEl: ".prev",
}}
>
{Products?.map((d) => (
<SwiperSlide key={d.id}>
<ProductCard key={d.id}
title={d.title}
image={d.image}
basePrice={d.basePrice}
flashHeight={200}
flashWidth={200}
discount={d.discount}
currentPrice={d.currentPrice} />
</SwiperSlide>
))}
</Swiper>
<div
className="prev cursor-pointer absolute top-2/4 -left-4 md:-left-5 z-10 -mt-4 md:-mt-5 w-8 h-8 md:w-9 md:h-9 rounded-full bg-white shadow-xl border border-gray-200 border-opacity-70 flex items-center justify-center text-gray-800 transition-all duration-200 hover:bg-primary hover:text-white hover:border-primary"
role="button"
>
<span className="sr-only">previous</span>
<ArrowPrev width={18} height={18} />
</div>
<div
className="next cursor-pointer absolute top-2/4 -right-4 md:-right-5 z-10 -mt-4 md:-mt-5 w-8 h-8 md:w-9 md:h-9 rounded-full bg-white shadow-xl border border-gray-200 border-opacity-70 flex items-center justify-center text-gray-800 transition-all duration-200 hover:bg-primary hover:text-white hover:border-primary"
role="button"
>
<span className="sr-only">next</span>
<ArrowNext width={18} height={18} />
</div>
</div>
</div>
{/* </div> */}
</div>
)
}
Check, both values of navigation object in both files are same.
Assign different values to prevEl and nextEl property for every swiper
component you use in your project.
navigation={{
nextEl: ".next", // both should be unique in every swiper
// component
prevEl: ".prev",
}}
Either you change both values or one of them in your file only if you
are using two swiper component in your project else you have to assign
different values to navigation property in every swiper component.
Make sure to replace it with new value in classes below.