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>
)
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 />
</>
)
}
i have an ul with a bunch of li as children, i wanted to add an staggerChildren to the li elements but the code isnt working at all
function Aside(props: any) {
/*==========Categories Variants========= */
const categorieContaiener = {
hidden: { opacity: 0, y: "100vh" },
show: {
opacity: 1,
y: 0,
transition: {
when: "beforeChildren",
delay: 1,
staggerChildren: 1,
},
},
};
const categorieItem = {
hidden: { opacity: 0, x: "100vw" },
show: {
opacity: 1,
x: 0,
transition: {
duration: 3,
},
},
};
return (
<div
className="aside bottom-0 sticky w-full h-[15%] md:w-[15%] md:h-full
bg-gradient-to-r from-[rgba(0,0,0,1)] to-transparent md:fixed text-white "
>
<div className="top w-full flex justify-center mt-5">
<div className="logo w-[130px] md:w-[160px] h-[60px]">
<img className="w-full h-full object-cover " src={logo} alt="" />
</div>
</div>
<div className="body text-white flex flex-col justify-between">
<motion.ul
className="w-full bg-blue-500"
variants={categorieContaiener}
initial="hidden"
animate="show"
>
{props.categories.map((categorie: string, index: number) => {
return (
<motion.li
key={index}
variants={categorieItem}
className="bg-red-500 m-1"
>
<Categorie
categorie={categorie}
categorieId={index}
setGifNameF={props.setGifNameF}
/>
</motion.li>
);
})}
</motion.ul>
</div>
</div>
);
}
its weird because i alredy use this effect on other page, now im using almost the exact same code but it isnt working out :/
I'm using next JS with tailwind css and using react-responsive-carousel package.the issue that i'm having is that when i start to swipe the images they're next to each other horizontally. they have no effect (like fade or ease in out) to them while swiping. and i wanted to make animation transition with ease-in-out or fade to it. how can i add fade in out animation instead of its default slide?
<Carousel
swipeScrollTolerance={100}
preventMovementUntilSwipeScrollTolerance
key={house.id}
axis="horizontal"
showStatus={false}
showThumbs={false}
swipeable={true}
className="group "
renderIndicator={(onClickHandler, isSelected, index, label) => {
const defStyle = {
marginLeft: 6,
color: "#b9b9b9",
cursor: "pointer",
};
const style = isSelected
? { ...defStyle, color: "#dcdcdc" }
: { ...defStyle };
return (
<span
style={style}
onClick={onClickHandler}
onKeyDown={onClickHandler}
value={index}
key={index}
role="button"
tabIndex={0}
aria-label={`${label} ${index + 1}`}
>
<FontAwesomeIcon
icon={faCircle}
className="sm:h-[0.35rem] sm:w-[0.35rem] h-2 w-2 font-thin"
/>
</span>
);
}}
renderArrowPrev={(clickHandler, hasPrev) => {
return (
<div
className={`${
hasPrev && !toggle ? "absolute" : "hidden"
} top-0 bottom-0 left-0 flex justify-center items-center p-3 opacity-0 group-hover:opacity-70 cursor-pointer z-10 text-white`}
onClick={clickHandler}
>
<FontAwesomeIcon
icon={faChevronCircleLeft}
className="h-8 w-8 font-thin"
/>
</div>
);
}}
renderArrowNext={(clickHandler, hasNext) => {
return (
<div
className={`${
hasNext && !toggle ? "absolute" : "hidden"
} top-0 bottom-0 right-0 flex justify-center items-center p-3 opacity-0 group-hover:opacity-70 cursor-pointerz-10 text-white`}
onClick={clickHandler}
>
<FontAwesomeIcon
icon={faChevronCircleRight}
className="h-8 w-8 font-thin"
/>
</div>
);
}}
>
{house.img.map((img, index) => {
return (
<Link href={`/living/${house.id}`} key={img.id}>
<div
key={img.id}
className=" w-full relative -z-10 pt-[100%] cursor-pointer"
>
<Image
src={img.img}
alt="profile"
fill
className="w-full h-full top-0 left-0 -z-10 object-cover rounded-2xl ease-in-out duration-200"
/>
</div>
</Link>
);
})}
</Carousel>
I have a mySQL database with about 100 rows, containing the data of products I'm listing in an eCommerce app.
I have them displayed on the front-end by using Axios to get the rows from my back-end SELECT * statement. They are then held as an array state const [rows, setRows] = useState([]);.
These rows are then mapped for each row found in the table, so around 100 maps.
I have noticed with this many results performance has started to become an issue and I've heard similar issues from mapping arrays.
I've benchmarked and tinkered to find that this component is the one causing the performance issues.
I would like any solutions to improve my component's performance, without altering the structure too much.
Heres the component
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import Button from '#mui/material/Button';
export default function ProductCard(props) {
const [rows, setRows] = useState([]);
const isntDesktop = props.isntDesktop; //Constant from parent
const isMobile = window.innerWidth < 768; //Checks if screen is smaller than mobile
const sidebar = props.sidebar; //Sidebar state from parent component
useEffect(() => {
axios.get('http://localhost:8080/products/get/')
.then(res => {
setRows(res.data);
}).catch(err => {
console.log(err);
});
});
return (
rows
.sort((a, b) => a.name.localeCompare(b.name))
//Map products
.map((row, index) => {
return (
/* Adjust structure for mobile */
isMobile ? (
/* Product card */
<div
key={index}
class={`${
sidebar ? 'border-0' : 'border'
} relative mt-6 py-8 px-5 rounded`}
>
{/* Heading */}
<h2 class="text-2xl font-semibold tracking-wide text-gray-700">{row.name}</h2>
<div class="flex items-center sm:items-start space-x-5">
{/* Image */}
<img
src={row.image}
alt="product"
class={`${
sidebar ? 'opacity-50' : 'opacity-100'
} mt-4 min-w-[125px] sm:w-[300px] h-auto`}
/>
<div class="mt-4">
{/* Price */}
<p class="text-2xl sm:text-xl font-semibold sm:font-medium text-gray-600">£ {row.price}</p>
{/* Keywords */}
<ul class="ml-5 mt-2 space-y-1">
<li class="list-disc text-gray-600">{row.keyword_one}</li>
<li class="list-disc text-gray-600" >{row.keyword_two}</li>
<li class="list-disc text-gray-600">{row.keyword_three}</li>
</ul>
</div>
</div>
<div
class={`${
sidebar ? 'bg-none' : 'bg-gray-100'
} mt-4 py-2 px-4 flex justify-center space-x-2.5`}>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6 text-sky-500">
<path stroke-linecap="round" stroke-linejoin="round" d="M8.25 18.75a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m3 0h6m-9 0H3.375a1.125 1.125 0 01-1.125-1.125V14.25m17.25 4.5a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m3 0h1.125c.621 0 1.129-.504 1.09-1.124a17.902 17.902 0 00-3.213-9.193 2.056 2.056 0 00-1.58-.86H14.25M16.5 18.75h-2.25m0-11.177v-.958c0-.568-.422-1.048-.987-1.106a48.554 48.554 0 00-10.026 0 1.106 1.106 0 00-.987 1.106v7.635m12-6.677v6.677m0 4.5v-4.5m0 0h-12" />
</svg>
<label class="text-gray-600 text-sm">Free delivery on orders over £50</label>
</div>
<div class="mt-4 w-full mx-auto flex flex-col sm:flex-row space-y-2.5 sm:space-y-0 sm:space-x-2.5">
{sidebar && isntDesktop ? (
<Button
type="submit"
variant="contained"
sx={{
opacity: 0.5,
bgcolor: '#6366f1',
textTransform: 'none',
width: '100%',
':hover': {
backgroundColor: '#4f46e5',
},
}}
>
View product
</Button>
) : (
<Button
type="submit"
variant="contained"
sx={{
opacity: 1,
bgcolor: '#6366f1',
textTransform: 'none',
width: '100%',
':hover': {
backgroundColor: '#4f46e5',
},
}}
>
View product
</Button>
)}
<Button
type="submit"
sx={{
border: ' 1px solid #38bdf8',
color: '#38bdf8',
textTransform: 'none',
width: '100%',
':hover': {
color: '#ffffff',
backgroundColor: '#38bdf8',
},
}}
>
Add to cart
</Button>
</div>
</div>
) : (
<div key={index} class="flex mt-6 py-8 px-5 border rounded">
{/* Image */}
<img src={row.image} alt="product" class="mr-4 w-[300px] h-auto" />
<div class="relative w-full px-5 items-center">
{/* Heading */}
<h2 class="text-2xl font-semibold tracking-wide text-gray-700">{row.name}</h2>
<div class="mt-8 flex justify-between">
{/* Keywords */}
<ul class="ml-5 space-y-1">
<li class="list-disc text-gray-600">{row.keyword_one}</li>
<li class="list-disc text-gray-600" >{row.keyword_two}</li>
<li class="list-disc text-gray-600">{row.keyword_three}</li>
</ul>
{/* Promo */}
<div class="flex flex-col ml-5">
{/* Price */}
<p class="text-xl font-medium text-gray-600">£ {row.price}</p>
<div
class={`${
sidebar ? 'bg-none' : 'bg-gray-100'
} mt-4 py-2 px-4 flex space-x-2.5`}>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6 text-sky-500">
<path stroke-linecap="round" stroke-linejoin="round" d="M8.25 18.75a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m3 0h6m-9 0H3.375a1.125 1.125 0 01-1.125-1.125V14.25m17.25 4.5a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m3 0h1.125c.621 0 1.129-.504 1.09-1.124a17.902 17.902 0 00-3.213-9.193 2.056 2.056 0 00-1.58-.86H14.25M16.5 18.75h-2.25m0-11.177v-.958c0-.568-.422-1.048-.987-1.106a48.554 48.554 0 00-10.026 0 1.106 1.106 0 00-.987 1.106v7.635m12-6.677v6.677m0 4.5v-4.5m0 0h-12" />
</svg>
<label class="text-gray-600 text-sm">Free delivery on orders over £50</label>
</div>
</div>
</div>
<div class="absolute bottom-0 w-full pr-5 flex space-x-2.5">
{sidebar && isntDesktop ? (
<Button
type="submit"
variant="contained"
sx={{
opacity: 0.5,
bgcolor: '#6366f1',
textTransform: 'none',
width: '100%',
':hover': {
backgroundColor: '#4f46e5',
},
}}
>
View product
</Button>
) : (
<Button
type="submit"
variant="contained"
sx={{
opacity: 1,
bgcolor: '#6366f1',
textTransform: 'none',
width: '100%',
':hover': {
backgroundColor: '#4f46e5',
},
}}
>
View product
</Button>
)}
<Button
type="submit"
sx={{
border: ' 1px solid #38bdf8',
color: '#38bdf8',
textTransform: 'none',
width: '100%',
':hover': {
color: '#ffffff',
backgroundColor: '#38bdf8',
},
}}
>
Add to cart
</Button>
</div>
</div>
</div>
)
)
})
)
}
Since you (probably) want to fetch your data once (on mount), you will have to add an empty dependency array to your useEffect to avoid infinitely running a query . You can read more about it here: https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects (In the Note section).
useEffect(() => {
axios.get('http://localhost:8080/products/get/').then(res => {
setRows(res.data);
}).catch(err => {
console.log(err);
});
}, [])
I saw that you render all your data on render and unfortunately, React is notoriously slow when it comes to rendering large lists. You might need to think about windowing your data, aka rendering a chunk of your data when your page first load and render more data as the user scroll further down. There's a great library that handles this for you: https://tanstack.com/virtual/v3/docs/guide/introduction.
I hope this helps!
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"}`}>