I am trying to convert a pure JavaScript, CSS, and HTML animated navbar into a ReactJS component to use in a project.
The original code is written in HTML with a separate CSS styling file, and a JavaScript file which is linked to the HTML code via <script>
tag. The below is a code snippet of my JavaScript file that I am trying to convert into ReactJS:
const navSlide = () => {
const burger = document.querySelector('.burger');
const navLinks = document.querySelectorAll('.nav-links li');
burger.addEventListener('click', ()=> {
navLinks.forEach((link, index) => {
if (link.style.animation) {
link.style.animation = '';
} else {
link.style.animation = 'navLinkFade 0.5s ease forwards $(index / 7 + 1}s
}
});
}
navSlide();
The ReactJS component that I am trying to change to accommodate the above code snippet currently contains the following code:
import React, { useState } from "react";
const NavBar = () => {
const [navOpened, setNavOpened] = useState(false);
const navClassNames = navOpened ? "nav-links nav-active" : "nav-links";
return (
<div className="navbar">
<nav>
<div className="logo">
<h4>Reuben McQueen</h4>
</div>
<ul className={navClassNames}>
<li>
<a href="#">Projects</a>
</li>
<li>
{" "}
<a href="#">Experiments</a>
</li>
<li>
{" "}
<a href="#">Skills</a>
</li>
<li>
{" "}
<a href="#">Contact Me</a>
</li>
</ul>
<div className="burger" onClick={() => setNavOpened(!navOpened)}>
<div className="line1" />
<div className="line2" />
<div className="line3" />
</div>
</nav>
</div>
);
};
export default NavBar;
The CSS for .nav-links
li
is the following:
.nav-links li {
list-style: none;
}
The code should individually move in each list item after the time delay is given.
You should be able to map over your navlinks
and apply styles to them (or lack thereof) depending upon the drawer state.. Something like this simulates what you are after, I believe..
EDIT: I updated my answer to something a little more efficient...
ORIGINAL ANSWER:
const NavBar = () => {
const [navOpened, setNavOpened] = React.useState(false);
const navLinks = ["One", "Two", "Three"];
const handleBurgerClick = () => {
setNavOpened(!navOpened);
}
return (
<div>
<div onClick={handleBurgerClick} className="burger">BURGER {navOpened ? "(close " : "(open "}me)</div>
<ul className="nav-links">
{navOpened
? navLinks.map((nl, index) => {
return (
<li
style={{
animation: `navLinkFade 0.5s ease forwards ${index / 7 + 0.1}s`
}}
>
Link {nl}
</li>
);
})
: ""}
</ul>
</div>
);
};
ReactDOM.render(<NavBar />, document.body);
.burger {
cursor: pointer;
text-align: center;
width: 80px;
}
.burger:hover {
color: blue;
}
.nav-links li {
list-style: none;
opacity: 0;
}
@keyframes navLinkFade {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>
MORE ADVANCED ANSWER (lets you fade in AND out)
const NavBar = ({ navLinks = [] }) => {
const [navOpened, setNavOpened] = React.useState(false);
const [styles, setStyles] = React.useState({ opacity: 0 });
const handleBurgerClick = () => {
setStyles(
navOpened ? { name: 'navLinkFadeOut' } : { opacity: 0, name: 'navLinkFadeIn' }
);
setNavOpened(!navOpened);
}
const oppositeIndex = (arr, index) => arr.indexOf([...arr].reverse()[index]);
const getDelay = index => (navOpened ? index : oppositeIndex(navLinks, index)) / 7 + 0.1;
const getStyle = index => {
return styles.name ? {
...styles,
animation: `${styles.name} 0.5s ease forwards ${getDelay(index)}s`
} : styles;
}
return (
<div>
<button onClick={handleBurgerClick} className="burger">
BURGER {navOpened ? "(close " : "(open "}me)
</button>
<ul className='nav-links'>
{navLinks.map((e, i) => <li style={getStyle(i)}>{e}</li>)}
</ul>
</div>
);
};
ReactDOM.render(
<NavBar navLinks={["One", "Two", "Three"]} />,
document.body
);
.burger {
cursor: pointer;
text-align: center;
width: 140px;
height: 25px;
}
.burger:hover {
color: blue;
}
.nav-links li {
list-style: none;
}
@keyframes navLinkFadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes navLinkFadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>