Converting a react made responsive navbar into nextjs navbar - next.js

I am trying to convert a react made responsive navbar component into next js navbar component. I don't know much about next js. Can anyone help with this code.The responsiveness works just fine. However, I cannot close the hamburger menu once I clicked it. The issue is with close Hamburger menu button. Here is the navbar component code converted from React js app:
import React from 'react';
import React from 'react';
import { GiHamburgerMenu } from 'react-icons/gi';
import { MdOutlineRestaurantMenu } from 'react-icons/md';
import Image from "next/image";
import styles from "../styles/Navbar.module.css"
const Navbar = () => {
const [toggleMenu, setToggleMenu] = React.useState(false);
return (
<nav className={styles.app__navbar}>
<div className={styles.app__navbar_logo}>
<Image src="/img/ephielogo.png" alt="app__logo" />
</div>
<ul className={styles.app__navbar_links}>
<li className={styles.p__opensans}>Home</li>
<li className={styles.p__opensans}>About</li>
<li className={styles.p__opensans}>Menu</li>
<li className={styles.p__opensans}>Awards</li>
<li className={styles.p__opensans}>Contact</li>
</ul>
<div className={styles.app__navbar_login}>
<a href="#login" className={styles.p__opensans}>Log In / Registration</a>
<div />
<a href="/" className={styles.p__opensans}>Book Table</a>
</div>
<div className={styles.app__navbar_smallscreen}>
<GiHamburgerMenu color="#fff" fontSize={27} onClick={() => setToggleMenu(true)} />
{toggleMenu && (
<div className={styles["app__navbar_smallscreen_overlay"] + " " + styles["flex__center"] + styles["slide_bottom"]}>
<MdOutlineRestaurantMenu fontSize={27} className="overlay__close" onClick={() => setToggleMenu(false)} />
<ul className={styles.app__navbar_smallscreen_links}>
<li><a href="#home" onClick={() => setToggleMenu(false)}>Home</a></li>
<li><a href="#about" onClick={() => setToggleMenu(false)}>About</a></li>
<li><a href="#menu" onClick={() => setToggleMenu(false)}>Menu</a></li>
<li><a href="#awards" onClick={() => setToggleMenu(false)}>Awards</a></li>
<li><a href="#contact" onClick={() => setToggleMenu(false)}>Contact</a></li>
</ul>
</div>
)}
</div>
</nav>
);
};
export default Navbar;
Here is my Navbar.Module.css code.
.app__navbar {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
background: var(--color-black);
padding: 1rem 2rem;
}
.app__navbar_logo {
display: flex;
justify-content: flex-start;
align-items: center;
}
.app__navbar_logo img {
width: 150px;
}
.app__navbar_links {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
color: var(--color-white);
list-style: none;
}
.app__navbar_links li {
margin: 0 1rem;
cursor: pointer;
}
.app__navbar_links li:hover {
color: var(--color-grey);
}
.app__navbar_login {
display: flex;
justify-content: flex-end;
align-items: center;
}
.app__navbar_login a {
margin: 0 1rem;
text-decoration: none;
transition: .5s ease;
color: var(--color-white)
}
.app__navbar_login a:hover {
border-bottom: 1px solid var(--color-golden);
}
.app__navbar_login div {
width: 1px;
height: 30px;
background: var(--color-grey);
}
.app__navbar_smallscreen {
display: none;
}
.app__navbar_smallscreen_overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background: var(--color-black);
transition: .5s ease;
flex-direction: column;
z-index: 5;
}
.app__navbar_smallscreen_overlay .overlay__close {
font-size: 27px;
color: var(--color-golden);
cursor: pointer;
position: absolute;
top: 20px;
right: 20px;
}
.app__navbar_smallscreen_links {
list-style: none;
}
.app__navbar_smallscreen_links li {
margin: 2rem;
cursor: pointer;
color: var(--color-golden);
font-size: 2rem;
text-align: center;
font-family: var(--font-base);
}
.app__navbar_smallscreen_links li:hover {
color: var(--color-white);
}
#media screen and (min-width: 2000px) {
.app__navbar_logo img {
width: 210px;
}
}
#media screen and (max-width: 1150px) {
.app__navbar_links {
display: none;
}
.app__navbar_smallscreen {
display: flex;
}
}
#media screen and (max-width: 650px) {
.app__navbar {
padding: 1rem;
}
.app__navbar_login {
display: none;
}
.app__navbar_logo img {
width: 110px;
}
}

Related

Mobile Dropdown Design Next.js (CSS or Tailwind)

I want to make my mobile menu have a dropdown when the main labels are clicked as they do for the regular desktop navigation. The dropdown works for the mobile menu, but it displays it on the left side of the main label. What I want it to do is expand or toggle/show underneath the top label when clicked if that makes sense. An example would be the mobile menu here: https://www.youtube.com/watch?v=JEV7WE0UBiQ&t=2738s, but in my case, I only need to go one dropdown deep.
Here are my Navbar and Dropdown components for review. I also provided the relevant CSS as well.
I know there is much to be improved and there are other small errors I am getting, but if I can get help on this part, that would be great. I've actually been using the help of ChatGPT to assist with some things, but it can only get me so far. Sometimes it's great, and other times I just want to punch it, lol!
import React, { useState } from "react";
import Link from "next/link";
import Dropdown from "./Dropdown";
import { menuItems, mobileMenuItems } from "./MenuItems";
// Import the FontAwesomeIcon component
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
// import the icons you need
import {
faChevronDown,
faBars,
faXmark,
} from "#fortawesome/free-solid-svg-icons";
function Navbar() {
const [click, setClick] = useState(false);
const [dropdownOpen, setDropdownOpen] = useState({
dropdown1: false,
dropdown2: false,
dropdown3: false,
});
const handleClick = () => {
setClick(!click);
setDropdownOpen({ dropdown1: false, dropdown2: false, dropdown3: false });
};
const closeMobileMenu = () => {
setClick(false);
setDropdownOpen({ dropdown1: false, dropdown2: false, dropdown3: false });
};
const toggleDropdown = (dropdown) => {
if (window.innerWidth < 950) {
setDropdownOpen({ [dropdown]: !dropdownOpen[dropdown] });
} else {
setDropdownOpen({ [dropdown]: !dropdownOpen[dropdown] });
}
};
return (
<nav>
<div className="container mx-auto px-10 mb-8">
<div className="relative border-b w-full inline-block border-blue-400 py-8">
<div className="absolute inset-y-0 left-0 flex items-center sm:hidden">
{/* Mobile menu button*/}
<button
className="inline-flex p-2 rounded-md text-gray-400 hover:text-white hover:bg-violet-700 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white text-3xl md:hidden"
onClick={() => {
setClick(!click);
}}
>
<FontAwesomeIcon icon={click ? faXmark : faBars} />
</button>
</div>
<div className="flex-1 flex items-center justify-center sm:items-stretch sm:justify-start">
<div className="flex-1 flex flex-shrink-0 flex px-12 items-center ">
<h1 className="font-bold text-4xl cursor-pointer text-white">
My<span className="text-blue-500">site</span>
</h1>
</div>
<div className="hidden md:float-left md:contents">
<ul className="nav-menu">
{menuItems.map((link, index) => (
<li
key={index}
className="nav-item"
onMouseEnter={
link.dropdownType
? () => toggleDropdown(link.dropdownType)
: null
}
onMouseLeave={
link.dropdownType
? () => toggleDropdown(link.dropdownType)
: null
}
>
<Link href={link.href}>
<a className="menuItems nav-links">
{link.icon && (
<FontAwesomeIcon
className="px-2"
icon={link.icon}
style={{ fontSize: 20, color: link.color }}
/>
)}
{link.label}
{link.dropdownType && (
<span className="faChevronDown">
<FontAwesomeIcon
icon={faChevronDown}
></FontAwesomeIcon>
</span>
)}
</a>
</Link>
{link.dropdownType && dropdownOpen[link.dropdownType] && (
<Dropdown type={link.dropdownType} />
)}
</li>
))}
</ul>
</div>
</div>
</div>
</div>
{/* ----------------------Hamburger Menu----------------------- */}
<ul
className={click ? "mobileNav-menu active" : "sm:hidden mobileNav-menu"}
>
{mobileMenuItems.map((link, index) => (
<li key={index} className="nav-item">
<Link href={link.href}>
<a
onClick={
link.dropdownType
? () => toggleDropdown(link.dropdownType)
: closeMobileMenu
}
className="menuItems nav-links dropdown-toggle"
>
{link.icon && (
<FontAwesomeIcon
className="px-2"
icon={link.icon}
style={{ fontSize: 20, color: link.color }}
/>
)}
{link.label}
{link.dropdownType && (
<span className="faChevronDown">
<FontAwesomeIcon icon={faChevronDown}></FontAwesomeIcon>
</span>
)}
</a>
</Link>
{link.dropdownType && dropdownOpen[link.dropdownType] && (
<ul className="dropdown-menu">
<Dropdown type={link.dropdownType} onClick={closeMobileMenu} />
</ul>
)}
</li>
))}
</ul>
</nav>
);
}
export default Navbar;
and the Dropdown component
import React, { useState, useEffect } from "react";
import Link from "next/link";
import {
getFeaturedArticlesCategories,
getNewsCategories,
getReviewsCategories,
} from "../services";
function useCategories() {
const [categories, setCategories] = useState({
featured: [],
news: [],
reviews: [],
});
useEffect(() => {
let cancel = false;
const fetchCategories = async () => {
const featured = await getFeaturedArticlesCategories();
const news = await getNewsCategories();
const reviews = await getReviewsCategories();
if (!cancel) {
setCategories({ featured, news, reviews });
}
};
fetchCategories();
return () => {
cancel = true;
};
}, []);
return categories;
}
function Dropdown({ type, onClick }) {
const [click, setClick] = useState(false);
const categories = useCategories();
const handleClick = () => setClick(!click);
return (
<>
<ul
onClick={() => {
handleClick();
onClick();
}}
className={click ? "dropdown-menu clicked" : "dropdown-menu"}
>
{categories[type].map((item, { active }) => (
<Link href={`/${type}/${item.slug}`} key={item.slug}>
<a
className={`group flex justify-center items-center px-4 py-2 text-sm font-semibold cursor-pointer ${
active
? "text-gray-700"
: "menuItems hover:bg-indigo-500 transition-all duration-500 ease-in"
}`}
>
{item.name}
</a>
</Link>
))}
</ul>
</>
);
}
export default Dropdown;
and the CSS
//Nav Menu
.menuItems {
&:hover {
color: rgb(255, 0, 0);
}
}
.navbar {
width: 90%;
height: 6rem;
display: flex;
justify-content: center;
align-items: center;
font-size: 1.2rem;
padding-left: 2.5rem;
padding-right: 2.5rem;
margin-left: auto;
margin-right: auto;
margin-bottom: 5rem;
border-bottom-width: 1px;
border-color: #60a5fa;
}
.navbar-logo {
color: #fff;
justify-self: start;
margin-left: -1rem;
cursor: pointer;
text-decoration: none;
line-height: 2.5rem;
font-size: 2.25rem;
font-weight: 700;
}
.nav-menu {
display: grid;
grid-template-columns: repeat(5, auto);
grid-gap: 1rem;
list-style: none;
text-align: center;
width: 70vw;
justify-content: end;
margin-right: 2rem;
}
.nav-item {
display: flex;
align-items: center;
height: 4rem;
}
.nav-links {
color: white;
text-decoration: none;
padding: 0.5rem 1rem;
display: inline-flex;
font-weight: 600;
justify-content: center;
width: 100%;
cursor: pointer;
}
.nav-links:hover {
background-color: #1888ff;
border-radius: 4px;
transition: all 0.2s ease-out;
}
.faBars {
color: #fff;
}
.nav-links-mobile {
display: none;
}
.menu-icon {
display: none;
}
#media screen and (max-width: 950px) {
.NavbarItems {
position: relative;
}
.mobileNav-menu {
display: flex;
flex-direction: column;
width: 100%;
height: 90vh;
position: absolute;
padding-top: 5rem;
padding-bottom: 15rem;
padding-left: 1rem;
bottom: 0;
top: 5rem;
left: -100%;
opacity: 1;
transition: all 0.5s ease;
}
.mobileNav-menu.active {
background: #242222;
left: 0;
opacity: 1;
transition: all 0.5s ease;
z-index: 1;
}
.nav-links {
text-align: center;
padding: 2rem;
width: 100%;
display: table;
}
.nav-links:hover {
background-color: #1888ff;
border-radius: 0;
}
.navbar-logo {
position: absolute;
top: 0;
left: 0;
transform: translate(25%, 50%);
}
.menu-icon {
display: block;
position: absolute;
top: 0;
right: 0;
transform: translate(-100%, 60%);
font-size: 1.8rem;
cursor: pointer;
}
.faXmark {
color: #fff;
font-size: 2rem;
}
.faChevronDown {
margin-left: 0.5rem;
padding: 0.5rem;
}
.nav-links-mobile {
display: block;
text-align: center;
padding: 1.5rem;
margin: 2rem auto;
border-radius: 4px;
width: 80%;
background: #1888ff;
text-decoration: none;
color: #fff;
font-size: 1.5rem;
}
.nav-links-mobile:hover {
background: #fff;
color: #1888ff;
transition: 250ms;
}
}
//Dropdown
.dropdown-menu {
background: rgb(184, 183, 231);
width: 10rem;
position: absolute;
border-radius: 0.375rem;
top: 6rem;
list-style: none;
text-align: start;
z-index: 10;
}
.dropdown-menu li {
background: #1888ff;
cursor: pointer;
}
.dropdown-menu li:hover {
background: #5cabff;
}
.dropdown-menu.clicked {
display: none;
}
.dropdown-link {
display: block;
height: 100%;
width: 100%;
text-decoration: none;
color: #fff;
padding: 16px;
}

Navbar covering the full width of screen

I am making a dashboard for my project in which I am also including navbar in it , but when I included navbar , it is covering the whole length of the screen . I tried a lot , but I am not that much pro in css , can anyone correct this code ??
Here is my dashboard code :
import React from 'react';
import Navbar from './components/Navbar/Navbar';
import RightNavbar from './components/RightNavbar/RightNavbar';
import styles from './App.module.scss';
function App({ history }) {
return (
<div>
<Navbar/>
<RightNavbar/>
<ToastContainer />
<div className = {styles.container}>
</div>
</div>
);
}
export default App;
Here is my Navbar code :
//STYLES
import styles from "./Navbar.module.scss";
//CONTEXT
import { useContext } from "react";
import NavContext from "../../Context/NavContext";
//REACT ROUTER
import { NavLink } from "react-router-dom";
//ICONS
import {
MdOutlineDashboard,
MdOutlineAnalytics,
MdOutlinedFlag,
MdPeopleOutline,
MdOutlineMessage,
MdOutlineLogout,
} from "react-icons/md";
import { IoMdLogIn } from "react-icons/io";
import { FaReact, FaTimes } from "react-icons/fa";
import { BsThreeDots } from "react-icons/bs";
import { VscDashboard } from "react-icons/vsc";
const NavUrl = ({ url, icon, description }) => {
const { nav, setNav } = useContext(NavContext);
const checkWindowSize = () => {
if (window.innerWidth < 1024) setNav(!nav);
};
return (
<li className={styles.li_navlink}>
<NavLink
to={`${url}`}
className={({ isActive }) => (isActive ? styles.active : undefined)}
onClick={() => checkWindowSize()}
>
{icon}
<span className={styles.description}>{description}</span>
</NavLink>
</li>
);
};
const Navbar = () => {
const { nav, setNav } = useContext(NavContext);
return (
<div
className={`${styles.navbar_container} ${
nav ? styles.navbar_mobile_active : undefined
}`}
>
<nav className={nav ? undefined : styles.nav_small}>
{/* LOGO */}
<div className={styles.logo}>
<VscDashboard className={styles.logo_icon} />
<FaTimes
className={styles.mobile_cancel_icon}
onClick={() => {
setNav(!nav);
}}
/>
</div>
{/* MENU */}
<ul className={styles.menu_container}>
{/* FIRST CATEGORY */}
<span className={styles.categories}>
{nav ? "Pages" : <BsThreeDots />}
</span>
<NavUrl
url="/"
icon={<MdOutlineDashboard />}
description="Dashboard"
/>
<NavUrl
url="analytics"
icon={<MdOutlineAnalytics />}
description="Analytics"
/>
<NavUrl
url="campaings"
icon={<MdOutlinedFlag />}
description="Campaings"
/>
<NavUrl url="team" icon={<MdPeopleOutline />} description="Team" />
<NavUrl
url="messages"
icon={<MdOutlineMessage />}
description="Messages"
/>
</ul>
{/* LOGOUT BUTTON */}
<div
className={`${styles.btn_logout}`}
onClick={() => {
setNav(!nav);
}}
>
<MdOutlineLogout />
</div>
</nav>
<div
className={nav ? styles.mobile_nav_background_active : undefined}
onClick={() => {
setNav(!nav);
}}
></div>
</div>
);
};
export default Navbar;
And here is my Navbar.module.scss :
.navbar_container {
--color_nav_bg: rgb(30, 41, 59);
--color_nav_txt: rgb(100, 116, 139);
--color_nav_ctg: rgb(226, 232, 240);
--color_nav_active: rgb(85, 79, 232);
--color_nav_not_active: rgb(61, 74, 94);
--color_nav_active_bg: rgb(15, 23, 42);
--nav_width: 16rem;
background: var(--color_nav_bg);
height: 100vh;
padding: var(--padding-md) var(--padding-sm);
transition: transform 300ms ease-in-out;
#media screen and (max-width: 1024px) {
transform: translateX(-100%);
position: absolute;
top: 0;
left: 0;
z-index: 12;
}
#media screen and (max-width: 18rem) {
width: 100vw;
}
}
.navbar_mobile_active {
#media screen and (max-width: 1024px) {
transform: translateX(0);
}
}
nav {
position: relative;
width: var(--nav_width);
height: 100%;
display: flex;
flex-direction: column;
overflow-y: scroll;
overflow-x: hidden;
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
transition: width linear 0.3s;
&::-webkit-scrollbar {
display: none;
}
}
.logo {
padding: 0 0.35rem;
font-size: 2.2rem;
display: flex;
.logo_icon {
color: var(--color_nav_active);
}
.mobile_cancel_icon {
display: none;
}
#media screen and (max-width: 1024px) {
.logo_icon {
display: none;
}
.mobile_cancel_icon {
display: block;
cursor: pointer;
font-size: 2.2rem;
padding: 0.2rem;
color: var(--color_nav_active);
}
}
}
.menu_container {
margin-top: var(--margin-lg);
display: flex;
flex-direction: column;
gap: 0.3rem;
}
.categories {
color: var(--color_nav_txt);
text-transform: uppercase;
font-size: 0.8rem;
margin-bottom: var(--margin-xxs);
svg {
font-size: 1rem;
}
}
.second_category {
margin-top: 3rem;
}
.li_navlink a {
display: flex;
align-items: center;
flex: 1;
padding: 0.5rem 0.75rem;
text-decoration: none;
color: var(--color_nav_ctg);
transition: all ease-in-out 0.2s;
.description {
margin-left: 0.5rem;
font-weight: 400;
transition: opacity 200ms ease;
}
svg {
font-size: 1.5rem;
color: var(--color_nav_not_active);
flex-shrink: 0;
}
&:hover {
background: var(--color_nav_active_bg);
}
&:hover svg {
color: var(--color_nav_active);
}
}
.li_navlink .active {
background: var(--color_nav_active_bg);
svg {
color: var(--color_nav_active);
}
}
.btn_logout {
margin-top: auto;
display: flex;
justify-content: flex-end;
transition: all ease-in-out 200ms;
padding: 0.5rem 0.75rem 0 0.75rem;
svg {
font-size: 1.5rem;
color: var(--color_nav_active);
cursor: pointer;
transform: scaleX(-1);
}
}
.mobile_nav_background_active {
width: 0;
height: 100vh;
transition: all ease-out 500ms;
transition-delay: 300ms;
cursor: pointer;
#media screen and (max-width: 1024px) {
display: block;
position: absolute;
top: 0;
left: calc(var(--nav_width) + var(--padding-md));
width: calc(100vw - var(--nav_width) - var(--padding-md));
background: rgba(0, 0, 0, 0.185);
z-index: -1;
}
}
//NAVIGATION SMALL
.nav_small {
width: 3rem;
.categories {
padding: 0 1rem;
}
.description {
opacity: 0;
}
.btn_logout {
svg {
transform: scaleX(1);
}
}
}

CSS transition for navigation bar

I would like to add an animation for when you open the nav links menu on smaller screens. I dont really understand transitions and couldnt find a great source that would tell me how to do it this way. Was wondering if i could have any suggestions on how to do it.
The section I would like to animate is the dropdown that appears when you click the hamburger menu. So that it slowly opens from top to bottom.
Similarly to what w3 did here but vertically rather than horizontally.
https://www.w3schools.com/w3css/w3css_sidebar.asp
Image for reference:
function ToggleNavLinks() {
var navLink = document.getElementsByClassName("nav-links")[0];
if (window.getComputedStyle(navLink).display === "none") {
navLink.style.display = "flex";
} else {
navLink.style.display = "none";
}
}
.navbar {
justify-content: space-between;
position: relative;
background-color: var(--bg-secondary);
display: flex;
justify-content: space-between;
align-items: center;
}
.navbar-links {
height: 100%;
}
.nav-links ul {
margin: 0;
padding: 0;
display: flex;
}
.nav-links li {
list-style: none;
}
.nav-links li a {
font-size: 1.5rem;
text-decoration: none;
color: white;
padding: 1rem;
display: block;
}
.nav-links li a:hover {
color: #4c6bc1;
}
.nav-toggle {
position: absolute;
top: 1.5rem;
right: 1rem;
display: none;
flex-direction: column;
justify-content: space-between;
height: 21px;
width: 30px;
}
.nav-toggle:hover {
cursor: pointer;
}
.nav-toggle .bar {
height: 3px;
width: 100%;
background-color: white;
border-radius: 10px;
}
#media (max-width: 800px) {
.nav-toggle {
display: flex;
}
.nav-links {
display: none;
width: 100%;
}
.navbar {
flex-direction: column;
align-items: flex-start;
}
.nav-links ul {
width: 100%;
flex-direction: column;
}
.nav-links li {
text-align: center;
}
.nav-links.active {
display: flex;
}
<body>
<header>
<nav class="navbar">
<img class="logo" alt="logo" src="https://via.placeholder.com/80">
<a class="nav-toggle" onclick="ToggleNavLinks()">
<span class="bar"></span>
<span class="bar"></span>
<span class="bar"></span>
</a>
<!-- Links used in the navbar -->
<div class="nav-links">
<ul>
<li>
Home
</li>
<li>
Projects
</li>
<li>
Contact
</li>
</ul>
</div>
<svg class="theme-toggle" alt="Icon used for toggling dark mode" aria-hidden="true" focusable="false" data-prefix="far" data-icon="moon" class="svg-inline--fa fa-moon fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M279.135 512c78.756 0 150.982-35.804 198.844-94.775 28.27-34.831-2.558-85.722-46.249-77.401-82.348 15.683-158.272-47.268-158.272-130.792 0-48.424 26.06-92.292 67.434-115.836 38.745-22.05 28.999-80.788-15.022-88.919A257.936 257.936 0 0 0 279.135 0c-141.36 0-256 114.575-256 256 0 141.36 114.576 256 256 256zm0-464c12.985 0 25.689 1.201 38.016 3.478-54.76 31.163-91.693 90.042-91.693 157.554 0 113.848 103.641 199.2 215.252 177.944C402.574 433.964 344.366 464 279.135 464c-114.875 0-208-93.125-208-208s93.125-208 208-208z"></path></svg>
</nav>
</header>
<div>
{{{body}}}
</div>
</body>

I need to toggle between an X button and hamburger menu with Bootstrap. I'm using React.js

I'm using the latest version of Bootstrap and want to toggle between the famous X icon and hamburger menu. I don't know if I can actually change the 3 lines of the menu since it's by default, but these 2 icons presently overlap each other.
So there are 2 questions here:
How can I toggle these two icons?
When the menu is clicked, it should have a complete white background (right now it doesn't completely cover the screen in white)
Sorry I don't have a sandbox example for you right now.
Thanks for your input!
/*JSX code*/
import React from 'react';
import { NavigationBarStyled } from './style';
import { Nav, Navbar } from 'react-bootstrap';
//IMAGES
import logo from '../../images/adyslogo.png';
import Image from 'react-bootstrap/Image';
import { GrCart } from 'react-icons/gr';
import CloseButton from '../../images/closebutton.svg';
const NavigationBar = () => {
return (
<NavigationBarStyled>
<Navbar expand='sm' fixed='top'>
<Navbar.Brand href='/'><Image src={logo} className='logo'/></Navbar.Brand>
<div className='close-button'>
<button type="button" className="x-closebutton" aria-label="Close">
<img src={CloseButton} className='x-button' alt="close configuration" draggable="false" />
</button>
<Navbar.Toggle aria-controls='basic-navbar-nav' className='hamburger-menu'/>
</div>
<Navbar.Collapse id='basic-navbar-nav'>
<Nav className='mr-auto'>
<Nav.Item><Nav.Link href='/' className="middle-menu">HOME</Nav.Link></Nav.Item>
<Nav.Item><Nav.Link href='/about' className="middle-menu">ABOUT</Nav.Link></Nav.Item>
<Nav.Item><Nav.Link href='/menu' className="middle-menu">MENU</Nav.Link></Nav.Item>
<Nav.Item><Nav.Link href='/gallery' className="middle-menu">GALLERY</Nav.Link></Nav.Item>
<Nav.Item><Nav.Link href='/contact' className="middle-menu">CONTACT</Nav.Link></Nav.Item>
</Nav>
<Nav className='ml-auto'>
<Nav.Item><Nav.Link href='/cart'><GrCart size='25px' className='cart'/></Nav.Link></Nav.Item>
</Nav>
</Navbar.Collapse>
</Navbar>
</NavigationBarStyled>
)
}
export default NavigationBar;
/*CSS*/
import styled from 'styled-components';
export const NavigationBarStyled = styled.nav`
.navbar {
background-color: #FFF;
height: 80px;
}
.navbar-brand, .navbar-nav .nav-link {
color: #273746 ;
font-size: 1rem;
font-weight: 600;
&:hover {
color: rgb(255, 20, 147);
}
}
.logo {
max-height: 60px;
max-width: 60px;
}
.middle-menu {
margin: 20px;
}
.cart {
margin-right: 50px;
}
.close-button {
display: flex;
align-items: flex-start;
justify-content: flex-start;
}
.x-closebutton {
display: flex;
align-items: flex-start;
justify-content: flex-start;
border: none;
background-color: #fff;
margin-right: -54px;
}
.x-button {
display: flex;
width: 45px;
height: 45px;
cursor: pointer;
}
.hamburger-menu {
border: none;
color: #000;
}
.mr-auto {
display: flex;
align-items: center;
background-color: white;
min-width: 100vw;
min-height: 100vh;
}
`;
It's actually rather easy to toggle state but, keep in mind you won't have the graceful height calculation which comes with Bootstrap.
I'll comment out what doesn't seem important to this answer...
import React, { Component } from "react";
//import { Link } from "gatsby";
//import Image from "./image";
import "../../scss/molecules/_topnav.scss";
//const helpers = require("../../helpers");
class Nav extends Component {
state = { collapse: true };
/*
componentDidMount() {
helpers.useIntersect(".navbar-collapse", "navbar-collapsed");
}
*/
constructor(props) {
super(props);
this.brandLogo = this.props.brandLogo;
this.listItems = this.props.pages
//.sort((a, b) => (a.node.navigationOrder || 100) - (b.node.navigationOrder || 100))
.map((page) => page.node.slug && page.node.pageName && !page.node.hideInNavigation && (
<li className="nav-item" key={page.node.id}>
<Link to={`${page.node.slug}`} className="nav-link" title={page.node.pageName}>{page.node.pageName}</Link>
</li>)
);
}
render() {
return (
<>
<nav className={[
"navbar",
"navbar-expand-lg",
"navbar-light",
"fixed-top",
this.state.collapse ? "" : "active"].join(" ")}
>
<a className="navbar-brand" href="/"><Image fluid={this.brandLogo} /></a>
<button
className="navbar-toggler"
type="button"
data-toggle="collapse"
data-target="#topnav"
aria-controls="topnav"
aria-expanded={!this.state.collapse}
aria-label="Toggle navigation" onClick={() => {
this.setState({ collapse: !this.state.collapse });
}
}>
<span className="navbar-toggler-icon"></span>
</button>
<div
className={[
"collapse",
"navbar-collapse",
"fade",
!this.state.collapse ? "show" : "",
].join(" ")} id="topnav">
<ul className="navbar-nav ml-lg-auto">{this.listItems}</ul>
</div>
</nav>
</>
);
}
}
export default Nav;
SCSS solution to cover state and mobile -vs- desktop navigation
A simple toggle between display "none" and "block". You can transition transforms to counter the missing height calculation.
We'll use the proper content characters to cover the icons.
It's a bit too much but I'll leave this file complete.
#import "../variables";
#import "../functions";
#import "../vendor/bootstrap/functions";
#import "../vendor/bootstrap/variables";
#import "../vendor/bootstrap/mixins";
#import "../vendor/bootstrap/transitions";
.navbar {
&.navbar-light {
transition: all ease 0.2s;
.navbar-brand {
transition: all ease 0.2s;
.image {
height: auto;
width: rem-value(142);
}
}
.nav-item {
align-items: center;
display: flex;
}
.nav-link {
font-family: $font-family-monospace;
font-size: rem-value(20);
}
#include media-breakpoint-up(md) {
.navbar-collapse {
&:not(.show) {
opacity: 1;
}
}
.nav-item {
margin: auto 1rem;
}
}
#include media-breakpoint-up(lg) {
.nav-item {
&:last-child {
.nav-link {
background-color: $primary;
border-radius: rem-value(3);
color: $white;
margin-left: 1.5rem;
&:hover,
&:active,
&:focus {
background-color: $brand-primary-headings;
}
}
}
}
}
#include media-breakpoint-down(md) {
background-color: $white;
box-shadow: 0 0 1px 1px $gray-300;
padding-top: 0;
padding-bottom: 0;
.navbar-brand {
transform: scale(0.65);
transform-origin: left;
padding-top: 0;
padding-bottom: 0;
}
.navbar-collapse {
&.collapse {
background: white;
margin: 0 -1rem;
height: 0;
transform: scale(0);
transform-origin: top center;
transition: all ease 0.5s;
padding: 1rem;
position: relative;
&.show {
height: calc(100vh - 80px);
transform: scale(1);
}
}
}
.navbar-toggler {
&[aria-expanded="true"] {
.navbar-toggler-icon {
background-image: none;
position: relative;
&:before {
content: "\00d7";
font-family: sans-serif;
font-size: rem-value(40);
line-height: 0.8;
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
}
}
}
}
.nav-item {
border-bottom: 1px solid $gray-300;
margin: 0;
position: relative;
&:before {
content: "\203A";
line-height: 1.2;
font-size: rem-value(30);
color: $brand-primary-headings;
position: absolute;
right: 0.5rem;
width: rem-value(40);
height: rem-value(40);
text-align: center;
}
}
.nav-link {
line-height: 1.8;
width: 100%;
}
}
#at-root .scrolled & {
background-color: $white;
box-shadow: 0 0 1px 1px $gray-300;
padding-top: 0;
padding-bottom: 0;
.navbar-brand {
transform: scale(0.65);
padding-top: 0;
padding-bottom: 0;
}
}
}
}
Example can be seen at devlab.career
Hopefully with this example you can implement this too.

How to set the content of div to be visible inside parent div using css

i want the content inside the expandable_container div to be visible.
Now it moves up while adding align-items: center to the expandable div.
I have a side panel which contains list items. when the list item overflows i add a expand button. clicking that button should show the full content of list item. It works but then. when the content in list item overflows then the content in list item is half seen. like in below image
i want that content to properly placed. I tried adding padding-top to expandable class. However this will affect other list items that doesnt have expandable component. How can i fix this. Below is the code,
export default class Expandable extends React.PureComponent{
constructor(props) {
super(props);
this.expandable_ref = React.createRef();
this.state = {
expanded: false,
overflow: false,
};
}
componentDidMount () {
if (this.expandable_ref.current.offsetHeight <
this.expandable_ref.current.scrollHeight) {
this.setState({overflow: true});
}
}
on_expand = () => {
this.setState({expanded: true});
console.log("in expnad");
};
on_collapse = () => {
this.setState({expanded: false});
};
render () {
return (
<div className={(this.state.overflow ?
this.props.container_classname : '')}>
<div className={(this.state.overflow ?
this.props.classname : '')} style={{overflow: 'hidden',
display: 'flex', height: (this.state.expanded ? null :
this.props.base_height)}}
ref={this.expandable_ref}>
{this.props.children}
</div>
{this.state.overflow && this.state.expanded &&
<div className={this.props.expand}>
<button onClick={this.on_collapse}>
{this.props.arrow_up}</button>
</div>}
{this.state.overflow && !this.state.expanded &&
<div className={this.props.expand}>
<button onClick={this.on_expand}>
{this.props.arrow_down}</button>
</div>}
</div>
);
}
}
Class SidePanel extends React.purecomponent {
switch (notification.type) {
case 'new_model_uploaded':
return (
<Expandable
base_height={42}
arrow_down={<SvgAccDown className='grey' width="10"
height="10"/>}
arrow_up={<SvgAccUp className='grey' width="26"
height="26"/>}
container_classname='expandable_container'
classname='expandable'
expand='expand'>
<ListItem
icon={<SvgProject width="26" height="26"/>}
text={<Text
name={notification.initiator.name}
text=' created model '
model_name={notification.attributes.modelname}/>}
timestamp={notification.timestamp}>
<div className="additional_details">
<PreviewImage
width={70}
height={70}
model_id={filtered_model.id}
/>
</div>
</ListItem>
</Expandable>
);
case 'deleted':
return (
<ListItem
icon={<Svg width="20" height="22"/>}
text={<Text
name={notification.initiator.name}
text=' deleted model '
model_name={notification.attributes.modelname}/>}
timestamp={notification.timestamp}/>
);}
}
function ListItem(props) {
return (
<li className="notification">
<div className="details_container">
<div className="details">
{props.icon}
{props.text}
<Timestamp>{props.timestamp}</Timestamp>
</div>
{props.children}
</div>
</li>
);
}
.notification {
display: flex;
flex-direction: row;
font-size: 12px;
padding: 8px;
min-height: 49px;
flex-grow: 1;
li {
list-style: none;
}
.details_container {
display: flex;
flex-direction: column;
flex-grow: 1;
margin-right: 8px;
.details {
display: flex;
color: #333;
align-items: center;
flex-grow: 1;
svg {
margin-right: 8px;
margin-left: 7px;
flex: 0 0 auto;
align-self: center;
flex-shrink: 0;
}
span {
flex-grow: 5;
text-align: left;
}
time {
flex: 0 0 auto;
margin-left: 8px;
padding-top: 2px;
color: #CCCCCC;
}
}
.additional_details {
flex-basis: 100%;
width: 226px;
margin-left: 11%;
span {
display: block;
word-break: break-all;
margin-left: 2px;
}
}
}
}
.expandable_container {
display: flex;
margin-top: 8px;
flex-direction: column;
border-bottom: 1px solid #CCCCCC;
.expandable {
align-items: center;
padding-top: 35px;
}
}
.expand {
display: flex;
align-items: center;
position: relative;
top: 10px;
border: 1px solid #CCCCCC;
width: 150px;
height: 20px;
left: 30%;
background-color: $white;
justify-content: center;
}
Could someone help me solve this thanks.

Resources