I need to bring the sticky header. When the user scrolls I need to add this sticky header. I've kept offset greater than 200 and added the respective css code. While I am debugging the code offset is printing correctly but by scrolled site is not getting appended. Any one can guide me what I am doing wrong. Below I have added both style and logic. Thanks in advance!
JSX:
import React, { useState, useEffect } from "react"
import "../styles/global.css"
export default function Navbar() {
const [scrolled, setScrolled] = useState(false)
const handleScroll = () => {
const offset = window.scrollY
console.log("OFFSET VALUE", offset)
if (offset > 200) {
setScrolled(true)
} else {
setScrolled(false)
}
}
useEffect(() => {
window.addEventListener("scroll", handleScroll)
})
let x = ["site-header"]
if (scrolled) {
x.push("scrolled")
}
return (
<>
<header className={x.join("")}>
<div className="wrapper site-header__wrapper">
<h2 className="brand">Community Site</h2>
<nav className="nav">
<div className="nav__wrapper">
<Link className="nav__item" to="/Home">
<h3> Home</h3>
</Link>
<Link className="nav__item" to="/Aboutus">
<h3>What are we</h3>
</Link>
<Link className="nav__item " to="/Contactus">
<h3>Contact Us</h3>
</Link>
</div>
</nav>
</div>
</header>
</>
)
}
CSS:
.site-header {
width: 100%;
max-width: 100%;
box-sizing: border-box;
/* position: relative;
overflow: hidden; */
padding: 15px 10px;
background-color: white;
border: 1px white;
transition: all 0.12s ease;
}
.scrolled {
position: sticky;
top: 0;
left: 0;
background-color: red;
}
.site-header__wrapper {
padding-top: 4rem;
padding-bottom: 6rem;
}
#media (min-width: 600px) {
.site-header__wrapper {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 0;
padding-bottom: 15px;
}
}
#media (min-width: 600px) {
.nav__wrapper {
display: flex;
gap: 12px;
align-items: center;
padding-top: 10px;
padding-bottom: 0;
}
}
I ran some tests and I think I know what happen, you have the class x.join("") however I manually added "site-header" and it worked by also adding an inline style
<header
className={site-header'}
style={scrolled ? { opacity: "1" } : { opacity: "0" }}
>
I also modified the site-header by adding position: fixed; top: 0
If you want to achieve the same result by just adding the class, I recommend you to use properties like opacity or transform: translateY() and add some transition to it
You can try this code.
const [scrolling, setScrolling] = useState(false);
const [scrollTop, setScrollTop] = useState(0);
useEffect(() => {
const onScroll = (e) => {
setScrollTop(e.target.documentElement.scrollTop);
if(scrollTop > 200) {
setScrolling(true)
};
};
window.addEventListener("scroll", onScroll);
return () => window.removeEventListener("scroll", onScroll);
}, [scrollTop, scrolling]);
Related
I am trying to recreate netflix kind of carousel ui using this wds tutorial (https://www.youtube.com/watch?v=yq4BeRtUHbk) for movie cast details using Reactjs and running through a problem.
I am fetching data from moviedb database and trying to achieve netflix like carousel effect.
the problem is when i click button for changing the slider index using getComputedStyle in css,
I get entire div recreated again several times.
I Fetch the data in the MovieDetails component and pass it to MovieDetailsPage component
export default function MovieDetails() {
const [MovieDetail, setMovieDetail] = useState([])
const [CastDetails, setCastDetails] = useState([])
const { id } = useParams();
const API_Key = '4ee812b6fb59e5f8fc44beff6b8647ed';
console.log('this is id', id);
useEffect(() => {
getDetail();
getCastDetails();
console.log('main');
}, [id])
const getDetail = useCallback(() => {
fetch(`https://api.themoviedb.org/3/movie/${id}?api_key=${API_Key}&language=en-US`)
.then(res => res.json())
.then(data => {
console.log(data, 'data');
setMovieDetail(data)
})
}, [id])
const getCastDetails = useCallback(() => {
fetch(`https://api.themoviedb.org/3/movie/${id}/credits?api_key=${API_Key}&language=en-
US`)
.then(res => res.json())
.then(data => {
setCastDetails(data.cast)
}
)
console.log('get cast details rendered');
}, [id])
useEffect(() => {
console.log(MovieDetail, 'Moviedetils')
}, [MovieDetail])
return (
<div>
<MoviesDetailsPage {...MovieDetail} CastDetails={CastDetails} API_Key={API_Key} />
</div>
)
}
MovieDetailsPage.jsx
export default function MoviesDetailsPage({ id, poster_path, backdrop_path, API_Key,
CastDetails }) {
const API_image = 'https://image.tmdb.org/t/p/w500/';
document.addEventListener('click', e => {
e.preventDefault();
let handle;
if(e.target.matches(".handle")){
handle = e.target
}else{
handle = e.target.closest(".handle")
}
if(handle != null) onHandleClick(handle)
})
function onHandleClick(handle){
const slider = handle.closest(".MovieCastContainer").querySelector(".slider")
console.log(slider, 'sliderindex')
const sliderIndex = parseInt(getComputedStyle(slider).getPropertyValue("--slider-index"))
if(handle.classList.contains("left-handle")){
slider.style.setProperty("--slider-index", sliderIndex - 1)
}
if(handle.classList.contains("right-handle")){
slider.style.setProperty("--slider-index", sliderIndex + 1)
}
}
const castInfo = CastDetails && CastDetails.map(data => <img src={API_image+data.profile_path}
alt={data.name} />)
console.log(CastDetails, 'Castdetails')
return (
<div className="MovieDetailsPageCont">
<div className='MovieDetailsContainer'>
<div className="headerImg"><img src={API_image + backdrop_path}
alt='backdrop_path' style={{ width: '100%', borderRadius: '10px' }} /></div>
<div className="movieid">{id}</div>
</div>
<div className='MovieCastContainer'>
<button className="handle left-handle">
<div className="text">‹</div>
</button>
<div className='slider'>
{
castInfo ? castInfo : '...Loading'
}
</div>
<button className="handle right-handle">
<div className="text">›</div>
</button>
</div>
</div>
)
}
My css page where change the slider index to transfrom to next set of values
*, *::after, *::before{
box-sizing: border-box;
}
:root{
--slider-padding: 5rem;
}
.MovieCastContainer{
display: flex;
justify-content: center;
overflow: hidden;
}
.slider{
--slider-index: 0;
display: flex;
flex-grow: 1;
margin: 0 .25rem;
transform: translateX(calc(var(--slider-index) * -100%));
transition: transform 250ms ease-in-out;
}
.slider > img {
flex: 0 0 25%;
max-width: 25%;
aspect-ratio: 16 / 9;
padding: .25rem;
border-radius: 1rem;
overflow: hidden;
}
.handle{
border: none;
border-radius: 1rem;
flex-grow: 0;
background-color: rgba(0, 0, 0, .25);
z-index: 10;
margin: .25rem 0;
padding: 0 .5rem;
cursor: pointer;
font-size: 5rem;
display: flex;
align-items: center;
justify-content: center;
color: white;
line-height: 0;
transition: font-size 150ms ease-in-out;
}
.left-handle{
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.right-handle{
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.handle:hover,
.handle:focus {
background-color: rgba(0, 0, 0, .5);
}
.handle:hover .text,
.handle:focus .text{
transform: scale(1.2)
}
Everytime I click next button in ui the I get this
please if you can help out with this any help would be appreciated.
I'm adding a keydown eventlistener that'll simply make my box div show. However, when I press a key, nothing happens and instead the console tells me, "Uncaught TypeError: box is null".
No idea what the problem is, please help
Here's my App.js:
import "./styles.css"
const box = document.querySelector(".box");
const notification = document.querySelector(".notif");
window.onload = document.addEventListener("keydown", e => {
box.classList.add("active");
notification.classList.add("inactive");
})
function App() {
return (
<>
<div className='notif'>Press Any Key</div>
<div className='box'>
<h2>20</h2>
<h1>Shift</h1>
</div>
</>
);
}
export default App;
and the css:
#import url('https://fonts.googleapis.com/css2?family=Poppins&display=swap');
:root {
--teal: #00ccff;
--pink: #d400d4;
}
*, *::before, *::after {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
body {
display: flex;
min-height: 100vh;
align-items: center;
justify-content: center;
background: #0e1538;
}
.box {
position: relative;
width: 300px;
height: 300px;
display: flex;
justify-content: center;
align-items: center;
background: rgba(0,0,0,.5);
overflow: hidden;
border-radius: 20px;
flex-direction: column;
display: none;
}
.box.active {
display: flex;
}
.box::before {
content: '';
position: absolute;
width: 150px;
height: 140%;
background: linear-gradient(var(--teal), var(--pink));
animation: animate 4s linear infinite;
}
#keyframes animate {
0%{
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.box::after {
content: '';
position: absolute;
background: #0e1538;
inset: 4px;
border-radius: 16px;
}
.box h2 {
position: relative;
color: white;
font-size: 5em;
z-index: 10;
}
.box h1 {
position: relative;
color: white;
z-index: 10;
background: rgba(0,0,0,.5);
width: 97.5%;
text-align: center;
letter-spacing: 5px;
}
.notif {
font-size: 3em;
background: var(--teal);
padding: 0 20px;
border-radius: 20px;
}
.notif.inactive {
display: none;
}
You should be maintaining/updating state with the new class information when you press a key. Add the listener within the useEffect (along with a cleanup function). When a key is pressed the listener calls a function that updates the state (in this case switching the active/inactive classes). The component is re-rendered, and the elements' class names are changed using a little helper function.
const { useEffect, useState } = React;
function Example() {
// Initialise state
const [ active, setActive ] = useState({
box: false,
notification: true
});
// A function to update the state
function toggleActive() {
setActive(prev => ({
box: !prev.box,
notification: !prev.notification
}));
}
// An effect that adds a listener, w/ a cleanup function
useEffect(() => {
window.addEventListener('keydown', toggleActive);
return () => {
window.removeEventListener('keydown', toggleActive);
}
}, []);
// Returns the active status of the element from state
function isActive(type) {
return active[type] ? 'active' : 'inactive';
}
return (
<div>
<div className={isActive('notification')}>
Press Any Key
</div>
<div className={isActive('box')}>
<h2>20</h2>
<h1>Shift</h1>
</div>
</div>
);
}
ReactDOM.render(
<Example />,
document.getElementById('react')
);
.active { color: red; }
.inactive { color: black; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>
import "./styles.css"
import {useEffect} from 'react'
function App() {
useEffect(()=>{
const box = document.querySelector(".box");
const notification = document.querySelector(".notif");
document.addEventListener("keydown", e => {
box.classList.add("active");
notification.classList.add("inactive");
})
},[])
return (
<>
<div className='notif'>Press Any Key</div>
<div className='box'>
<h2>20</h2>
<h1>Shift</h1>
</div>
</>
);
}
export default App;
In this case, I used React + TypeScript and ant-design. The following code works perfectly but I want the codes to be summarized as much as possible. This is about starting a site that has 3 pages. For example, how can I write this part (const { id, title, description, background } = splash;) so that I don't need to define (splashs[index].background , splashs[index].title, splashs[index].description) all the time.
Thank you in advance for your cooperation.
.splash {
height: 100vh;
position: relative;
overflow: hidden;
}
.bg {
background-color: var(--cjp);
}
.BgGradiant {
background: linear-gradient(107.78deg, rgba(80, 21, 100, 0) 1.87%, rgba(80, 21, 100, 0.05) 18.6%, rgba(80, 21, 100, 0.51) 25.79%, #1C3396 99.02%, #1C3396 51.08%);
}
.context{
width: 80%;
}
.content {
text-align: center;
}
.content h1,
.content p {
color: var(--cwh);
}
.backgroundImage>img {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: -1;
-o-object-fit: cover;
object-fit: cover;
}
.logo {
width: 100%;
text-align: center;
}
.btns {
display: flex !important;
align-items: center;
justify-content: space-between;
-webkit-margin-start: auto;
margin-inline-start: auto;
-webkit-margin-end: auto;
margin-inline-end: auto;
-webkit-margin-before: 2rem;
margin-block-start: 7rem;
}
.btns :global(.ant-btn){
background-color: var(--cwh);
border-radius: var(--borderRadius12);
position: relative;
padding: 4px 10px !important;
}
.btns :global(.ant-btn)::after{
content: "";
position: absolute;
width: 125%;
height: 125%;
top: 50%;
left: 50%;
border: 1px solid var(--chb);
border-radius: var(--borderRadius14);
transform: translate(-50%, -50%);
}
.btns :global(.ant-btn > span){
margin-left: 0 !important;
}
.btns :global(.ant-btn > span > svg){
fill: var(--cal);
}
.btnSkip {
background-color: unset;
outline: none;
border: none;
color: var(--cca);
}
.btnLogin{
-webkit-margin-before: 2rem;
margin-block-start: 7rem;
}
.btnLogin :global(.ant-btn){
border-radius: var(--borderRadius10);
background-color: var(--cwh);
color: var(--cjp);
}
.btnLogin :global(.ant-btn > span){
font-family: "Display-Bold";
}
.dots {
position: absolute;
bottom: 17%;
display: flex !important;
align-items: center;
justify-content: center;
left: 50%;
transform: translateX(-50%);
}
.dot {
width: 10px;
height: 10px;
border-radius: 50%;
}
.dotActive {
background-color: var(--cwh);
}
.dotDeActive {
background-color: var(--cca);
}
.dot:not(:last-child) {
-webkit-margin-end: 0.5rem;
margin-inline-end: 0.5rem;
}
.contentInner{
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
-webkit-padding-before: 2rem;
padding-block-start: 2rem;
-webkit-padding-after: 3rem;
padding-block-end: 3rem;
}
.contentInner1{
justify-content: space-between;
}
.contentInner2{
justify-content: flex-end;
}
import React, { useState } from 'react';
import { useNavigate } from "react-router-dom";
import { Row, Col, Button } from 'antd';
import { ArrowRightOutlined } from '#ant-design/icons';
import Container from '../../Components/UI/Container/Container'
import classes from './Splash.module.css';
import { backgroundSplash1, backgroundSplash2, logoImage } from '../../Assets/index';
const Splash = () => {
let navigate = useNavigate();
const [index, setIndex] = useState<number>(0);
const {
splash,
bg,
BgGradiant,
context,
content,
backgroundImage,
logo,
btns,
btnLogin,
btnSkip,
dots,
dot,
dotActive,
dotDeActive,
contentInner,
contentInner1,
contentInner2,
} = classes
const splashs = [
{
id: 0,
title: 'Page 1 : title 1',
desctiption: '1- Lorem ipsum 1 ',
background: logoImage,
},
{
id: 1,
title: 'Page 2 : title 2',
desctiption: '2- Lorem ipsum 2 ',
background: backgroundSplash1,
},
{
id: 2,
title: 'Page 3 : title3',
desctiption: '3- Lorem ipsum 3',
background: backgroundSplash2,
}
];
const nextBnt = () => {
setIndex(index + 1);
if (index === splashs.length - 1) {
return navigate("/login");
}
}
const skipBtn = () => {
console.log('skip ');
return navigate("/login");
}
const loginBtn = () => {
return navigate("/login");
}
return (
<>
<Row>
<Col xs={24}>
<section
className={`${index === 0 ? bg : BgGradiant} ${splash}`}>
{
splashs.map((splash) => {
const { id, title, desctiption, background } = splash;
console.log(title, "title");
return (
<>
{
index !== 0 && (
<div className={backgroundImage}>
<img src={splashs[index].background} />
</div>
)
}
<Container key={id} className={backgroundImage}>
<div className={`${index === 0 ? contentInner1 : contentInner2} ${contentInner}`}>
{
index === 0 && (
<div className={logo}>
<img src={logoImage} alt="logoImage" />
</div>
)
}
<div className={context}>
<div className={content}>
<h1>{splashs[index].title}</h1>
<p>{splashs[index].desctiption}</p>
</div>
{/* BTNS */}
{
index === splashs.length - 1 ? (
<div className={btnLogin}>
<Button block onClick={loginBtn}>Login</Button>
</div>
) : (
<div className={btns}>
<button className={btnSkip} onClick={skipBtn}>skip</button>
<Button onClick={nextBnt}> <ArrowRightOutlined /></Button>
</div>
)
}
</div>
</div>
</Container>
</>
)
})
}
<div className={dots}>
{
Array.from({ length: 3 }).map((item, idx) => {
return (
<div key={idx} className={`${dot} ${index === idx ? dotActive : dotDeActive}`}></div>
)
})
}
</div>
</section>
</Col>
</Row>
</>
)
}
export default Splash;
Just an advice, your question isn't really well formulated so it's hard to understand what are you trying to accomplish. Try to keep the questions clear and remove any redundant code so the community can better understand it.
If I'm assuming correctly that you don't want to use splash[index] then you should change splash[index].title to title, same for the other props.
Since you already destructured the splash object with const { id, title, description, background } = splash; all these will be available.
Another thing here is, .map method returns the item in the array so I don't see the point in you using the index inside the loop to access the item from the array.
I am making React project but I faced error with css.
Is there any possible way to leave parent and child component same and just make scroll on the left side for the div where are shopping items. I tried with overwflow-y: scroll but it just creates scroll and doesn't make scrollable even if I put some random height. There is way I know but unfortunately at the moment I cant find it.
Parent html
const CartModal = () => {
const { totalPrice, totalAmount } = useSelector((state) => state.cart);
return (
<div className={classes["cart-modal"]}>
<div className={classes["cart-modal__navbar"]}></div>
<div className={classes["cart-modal__body"]}>
<div className={classes["body__left-side"]}>
<h1>ORDERS</h1>
<CartModalFoodList />
</div>
<div className={classes["body__right-side"]}>
<div>
<img src={BigCart} />
</div>
<div>
<h2>Total price:</h2>
<h2>{totalPrice}$</h2>
</div>
<div>
<h2>Total amount:</h2>
<h2>{totalAmount}</h2>
</div>
</div>
</div>
</div>
);
};
.cart-modal {
z-index: 100;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 65vw;
height: 75vh;
background-color: var(--main-bg-color);
border-radius: 10px;
box-shadow: 1px 2px 5px;
overflow: hidden;
}
.cart-modal__navbar {
width: 100%;
height: 15vh;
background: radial-gradient(
50% 50% at 50% 50%,
var(--gradient-color-one) 0%,
var(--gradient-color-two) 100%
);
}
.cart-modal__body {
display: flex;
height: 100%;
}
.body__left-side {
height: 100%;
width: 55%;
background-color: white;
padding: 0 3.5%;
}
.body__left-side h1 {
color: var(--strong-yellow);
text-align: center;
border-bottom: 1px solid var(--weak-yellow);
padding-bottom: 2%;
}
.body__right-side {
width: 45%;
height: 100%;
display: flex;
flex-direction: column;
}
.body__right-side div:first-child {
height: 50%;
width: 100%;
}
.body__right-side div:first-child img {
height: 100%;
width: 100%;
}
.body__right-side *:not(:first-child) {
display: flex;
justify-content: space-around;
}
.body__right-side *:not(:first-child) h2 {
font-size: 2vw;
margin: 2.5% 0;
}
Left side div
const MenuList = (props) => {
const page = props.page;
const dispatch = useDispatch();
const foodArray = props.foodList;
const navigate = useNavigate();
const location = useLocation();
const params = useParams();
const [foodList, setFoodList] = useState([]);
useEffect(() => {
setFoodList(formatArray(foodArray));
}, [foodArray]);
const queryPrams = new URLSearchParams(location.search);
const sort = queryPrams.get("sort");
const onNextPageHandler = () => {
dispatch(uiSliceActions.updatePage("forward"));
};
const onPreviousPageHandler = () => {
dispatch(uiSliceActions.updatePage("backward"));
};
const onSortPageHandler = () => {
navigate(
`/menu/${params.foodId ? params.foodId + "/" : ""}?sort=${
sort === "asc" ? "desc" : "asc"
}`
);
let foodListPart = foodList[page];
let foodListSort = foodList;
const sortFoodList = (sort) => {
foodListPart = foodListPart.sort((a, b) =>
sort === "asc" ? a.foodPrice - b.foodPrice : b.foodPrice - a.foodPrice
);
foodListSort[page] = foodListPart;
setFoodList(foodListSort);
};
sort === "asc" ? sortFoodList("asc") : sortFoodList("desc");
};
return (
<Fragment>
<div className={classes["menu-list"]}>
{foodList[page]
? foodList[page].map((foodObj) => (
<MenuItem key={foodObj.id} foodObj={foodObj} />
))
: ""}
</div>
<div className={classes["menu-list__buttons"]}>
{page >= 1 && (
<Button type="button" onClick={onPreviousPageHandler}>
Page {page}
</Button>
)}
<Button
type="button"
onClick={onSortPageHandler}
className={classes["sort-button"]}
>
{sort === "asc" ? `Descending` : `Ascending`}
</Button>
<Button type="button" onClick={onNextPageHandler}>
Page {page + 2}
</Button>
</div>
</Fragment>
);
};
And css for that div
.menu-list {
overflow-y: scroll;
}
Thank you.
Define the height of the div, then add overflow: auto;
You just need to add overflow-y: scroll to "body__left-side" class
.body__left-side {
height: 100%;
width: 55%;
background-color: white;
padding: 0 3.5%;
overflow-y: scroll;
}
just add over-flow: "auto" to cart-modal__body class
I have fixed this issue by correcting .body__left-side
.body__left-side {
height: 100%;
width: 55%;
background-color: white;
padding: 0 3.5%;
overflow-y: scroll;
}
And also by correcting .menu-list
.menu-list {
height: auto;
padding-bottom: 25%;
}
Thanks to everyone for help.
I'm following a guide on how to build a simple website using Styled Components.
When the website is in mobile view the hamburger menu is stuck open and will not close when clicking the hamburger symbol or any of the nav menu items. The hamburger symbol does toggle to the FaTimes symbol, however.
All solutions I found so far don't work or require bootstrap, which I'm unfamiliar with. Can someone please explain to me the error in my code?
Navbar
import React, {useState, useEffect} from 'react';
import { FaBars, FaTimes } from 'react-icons/fa';
import { Nav, NavbarContainer, NavLogo, NavIcon, MobileIcon, NavItem, NavMenu, NavLinks,
NavItemBtn, NavBtnLink } from './Navbar.elements';
import {Button } from '../globalstyles';
import osun from '../images/Osun.png';
import { IconContext} from 'react-icons/lib';
import Home from './pages/Home';
const Navbar = () => {
const [click, setClick, isOpen, setIsOpen] = useState(false);
const [button, setButton] = useState(true);
const toggle = () => setIsOpen(!isOpen);
const hide = () => setIsOpen(false);
const handleClick = () => setClick(!click);
// const toggleShow = () => {
// this.setState({show: !this.state.show})
// }
//const toggleShow = () => setClick(!show)
// const toggleShow = () => {
// if (window.innerwidth <= 960){
// showMenu(false)
// } else {
// showMenu(true)
// }
// }
const showButton = () => {
if (window.innerWidth <=960){
setButton(false)
} else {
setButton(true)
}
};
const closeMobileMenu = () => setClick(false);
useEffect(() => {
showButton();
//toggleShow()
}, []);
window.addEventListener('resize', showButton);
//window.addEventListener('resize', toggleShow);
return (
<>
<IconContext.Provider value={{color: "#fff"}}>
<Nav>
<NavbarContainer>
<NavLogo to ="/">
<NavIcon />
Osun Swap
</NavLogo>
<MobileIcon onClick={handleClick} onBlur={hide} >
{click ? < FaTimes/> : <FaBars/>}
</MobileIcon>
<NavMenu onClick={handleClick} click ={click}>
<NavItem>
<NavLinks to = '/' onClick={closeMobileMenu}>
Home
</NavLinks>
</NavItem>
<NavItem>
<NavLinks to = '/services' onClick={closeMobileMenu}>
Services
</NavLinks>
</NavItem>
<NavItem>
<NavLinks to = '/AboutUs' onClick={closeMobileMenu}>
About us
</NavLinks>
</NavItem>
<NavItemBtn>
{button ? (
<NavBtnLink to ='/sign-up'>
<Button primary> Connect Wallet </Button>
</NavBtnLink>
) : (
<NavBtnLink to='/sign-up'>
<Button onClick={closeMobileMenu} fontBig primary>
Connect Wallet
</Button>
</NavBtnLink>
)}
</NavItemBtn>
</NavMenu>
</NavbarContainer>
</Nav>
</IconContext.Provider>
</>
)
}
export default Navbar;
Navbar.elements
import styled from 'styled-components';
import { Link } from 'react-router-dom';
import osun from '../images/Osun.png';
import { Container } from '../globalstyles';
export const Nav = styled.nav`
background : #101522;//#282c34;//rgb(35, 31,32);//; //rgb(10, 10, 10);
display: flex;
justify-content: center;
align-items: center;
font-size: 1.2rem;
position: sticky;
top:0;
z-index:999;
`;
export const NavbarContainer = styled(Container)`
display: flex;
justify-content:space-between;
height: 80px;
${Container}
`;
export const NavLogo = styled(Link)`
color: #ffff;
justify-self: flex-start;
cursor: pointer;
font-size: 2rem;
display: flex;
align-items: center;
`;
export const NavIcon = styled.div`
background-image: url(${osun});
margin-right: 0.5rem;
`;
export const MobileIcon = styled.div`
display: none;
#media screen and (max-width: 960px){
display:block;
position: absolute;
top: 0;
right:0 ;
transform: translate(-100%, 60%);
font-size: 1.8rem;
cursor: pointer;
}
`;
export const NavMenu = styled.ul`
display: flex;
align-items: center;
list-style: none;
//text-decoration: none;
text-align: center;
/* display: flex;
flex-direction: column;
width: 100px;
height: 500px;
top: 80px;
left: -100%;
opacity:1;
transition: all 0.5s ease; */
#media screen and (max-width: 960px) {
display: flex;
flex-direction: column;
width: 100%;
//list-style: none;
height: 90vh;
top: 80px;
//right: -100%;
right: ${({click}) => (click ? 0 : '-100%')};
opacity:1;
//transform: ${({open}) => open ? 'translateX(0)' : 'translateX(100%)'};
transition: all 0.5s ease;
background: #101522; //rgb(35, 31,32);//
}
`;
export const NavItem = styled.li`
height: 80px;
border-bottom: 2px solid transparent;
#media screen and (max-width: 960px){
//visibility: hidden;
// display: block;
position: relative;
width: 100%;
//top:0;
//right:0;
//transform: translate(-100%, 60%);
//font-size:1.8rem;
//cursor: pointer;
}
&:hover {
border-bottom: 2px solid #4b59f7;
}
`;
export const NavLinks = styled(Link)`
color: #fff;
display:flex;
align-items: center;
text-decoration: none;
padding:0.5rem 1rem;
height: 100%;
#media screen and (max-width: 960px){
text-align: center;
padding: 2rem;
width: 100%;
display: table;
&:hover {
color:#4b59f7;
transition: all 0.3s ease;
}
}
`;
export const NavItemBtn = styled.li`
#media screen and (max-width: 960){
display:flex;
justify-content: center;
align-items: center;
width: 100%;
height: 120px
}
`;
export const NavBtnLink= styled(Link)`
display: flex;
justify-content:center;
align-items: center;
text-decoration: none;
padding: 8px 16px;
height: 100%;
width: 100%;
border: none;
outline: none;
`;
I tried to reproduce your issue and ran into errors with your code example, which may be the cause of your issue. In particular:
const [click, setClick, isOpen, setIsOpen] = useState(false);
is not a valid setup for useState. Try splitting this into two separate useState calls like:
const [click, setClick] = useState(false);
const [isOpen, setIsOpen] = useState(false);
As you had it in the original example, my IDE immediately flagged that line, and also informed me that isOpen was not initialized to anything, which threw major errors when I tried to click the button / blur it.