Next js not closing mobile nav when click nav link - next.js

I'm using Next Js with Tailwind CSS for creating the website. Use Javascript to toggle the menu for Mobile devices. But Next Js click the nav menu link not closing the opened nav.
Button-
const Navbar = () => {
const [ isHidden, setIsHidden ] = useState(true)
return (
<>
<button onClick={() => setIsHidden(c => !c)} className="menu-button md:hidden rounded-lg focus:outline-none focus:shadow-outline">
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path strokeLinecap="round" stroke-linejoin="round" d="M4 6h16M4 12h16M4 18h16" />
<path className="hidden" fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" />
</svg>
</button>
<nav className={`mobile-menu flex-col flex-grow pb-4 md:pb-0 md:flex md:justify-end md:flex-row flex hidden ${isHidden ? "hidden" : ""}`}>
<Link href="/about">
<a className="md:mt-0 mt-3 px-3 py-2">About</a>
</Link>
<Link href="/about-us">
<a className="md:mt-0 mt-3 px-3 py-2">Boost</a>
</Link>
<Link href="/about-us">
<a className="md:mt-0 mt-3 px-3 py-2">Technology</a>
</Link>
<Link href="/about-us">
<a className="md:mt-0 mt-3 px-3 py-2">Contact</a>
</Link>
</nav>
</>
)
}
export default Navbar
Using the below Javascript for toggle Menu.
const btn = document.querySelector('button.menu-button');
const menu = document.querySelector(".mobile-menu");
btn.addEventListener("click", () => {
menu.classList.toggle("hidden");
})

It may be that your event listener was created multiple times (we don't see the whole code). More React like approach could look like this:
const Home = () => {
const [ isHidden, setIsHidden ] = useState(true)
return (
<button onClick={() => setIsHidden(c => !c)}>click me</button>
<nav className={`your classes ${isHidden ? "hidden" : ""}`}>
...
</nav>
)
}
So you have a state and based on that state you are adding "hidden" class. Button has an onclick handler which toggles the state.
If you want to close navbar also on link click you can try this approach:
<Link href="/about">
<a
onClick={(e) => {
e.preventDefault()
setIsHidden(true)
}
>About</a>
</Link>

Related

Why is z-index not working even after providing the position and the index

I wanted to place an absolute element behind a relative element. I have mentioned the z-index and also the position for the respective elements but its still not working.
This is what i had tried. I am using tailwind css.
const Searchbar: React.FC<SearchbarProps> = ({}) => {
const [toggle, setToggle] = useState(false);
const [dropdown, setDropdownToggle] = useState(false);
return (
<form className={`search flex items-center basis-9/12 pl-5 z-20 relative ${toggle ? 'dark': ''}`} >
{/* ICON */}
<svg className="ico-svg" viewBox="0 0 20 20" width="20">
<path d="M20,8c0-4.4-3.6-8-8-8C7.6,0,4,3.6,4,8c0,1.9,0.6,3.6,1.7,4.9L0,18.6L1.4,20l7.1-7.1l-0.2-0.2 C6.9,11.6,6,9.9,6,8c0-3.3,2.7-6,6-6c3.3,0,6,2.7,6,6c0,3.3-2.7,6-6,6c-0.7,0-1.3-0.1-1.9-0.3L10,13.7l-1.5,1.5l0.4,0.2 c1,0.4,2.1,0.7,3.2,0.7C16.4,16,20,12.4,20,8z"></path>
</svg>
{/* INPUT */}
<input className='basis-9/12 pl-3 h-[48px] text-sm font-normal self-stretch'
onClick={() => setToggle(!toggle)}
type="text" name="search" id="search" placeholder='Search websites, elements, courses...'/>
<div className="dropdown flex items-center justify-end basis-3/12">
{/* TEXT */}
<p className='uppercase mr-9 font-light text-xs'>in</p>
{/* DROPDOWN */}
<button className={`flex items-center h-[48px] justify-between basis-6/12 px-5 ${dropdown ? 'active': ''}`} onClick={(e) => {
e.preventDefault();
setDropdownToggle(!dropdown)
}
}>
<p className="capitalize text-sm font-medium">inspiration</p>
<svg className="dropdown__arrow" viewBox="0 0 20 20" width="12">
<path d="M1.6,4.1c-0.4,0-0.9,0.2-1.2,0.5c-0.7,0.7-0.7,1.7,0,2.4l8.4,8.4c0.7,0.7,1.7,0.7,2.4,0L19.5,7 c0.7-0.7,0.7-1.7,0-2.4c-0.7-0.7-1.7-0.7-2.4,0L10,11.8L2.8,4.6C2.5,4.3,2.1,4.1,1.6,4.1z"></path>
</svg>
</button>
{/* DROPDOWN LIST */}
<div className={`dropdown__list capitalize px-5 pt-2 pb-5 text-sm font-normal ${dropdown ? 'active' : ''}`}>
<ul>
<li className='pt-3'>Inspiration</li>
<li className='pt-3 pl-3'>websites</li>
<li className='pt-3 pl-3'>elements</li>
<li className='pt-3 pl-3'>collections</li>
<li className='pt-3'>blog</li>
<li className='pt-3'>courses</li>
<li className='pt-3'>directory</li>
</ul>
</div>
</div>
{/* SUGGESTIONS */}
<div className="search__suggestions z-10 absolute">
</div>
</form>
);
}
This is how its behaving:
Actual behaviour
Instead of this:
Expected Behaviour
As you can see i have a form tag that is relative places and i also have a div with the class "search__suggestions" that is placed absolutely. I have also provided the appropriate index to the tags, but for some reason its not working. Anyone knows why its behaving this way?

How to stop background scroll of Fixed element in React?

I'm using NextJS with tailwind. and I'm creating a drawer, popup and modal with position: fixed. so when i implement this and scroll on it the background component will scroll as well. even if the fixed is scrollable when the scroll end the back element starts to scroll. how can I make it stop for the background to be not scrollable and clickable?
function Drawer() {
const toggle = useSelector(selectMenu);
const dispatch = useDispatch();
const handleOnClose = (e) => {
if (e.target.id === "container") dispatch(toggleMenu(!toggle));
};
return (
<div
id="container"
onClick={handleOnClose}
className={`md:hidden h-full w-full backdrop-blur-sm fixed ${
!toggle && "hidden"
}`}
>
<div
className={`${
toggle ? " translate-x-0" : "translate-x-full"
} md:hidden fixed h-screen w-3/4 ease-in-out duration-300 bg-white z-50 bottom-0 top-0 right-0 flex flex-col px-4 py-3 space-y-5 shadow-2xl`}
>
<Link
href="/"
className="cursor-pointer flex px-2 space-x-4"
onClick={() => dispatch(toggleMenu(!toggle))}
>
<HomeModernIcon className="h-6 w-6 text-black" />
<h1>Dashboard</h1>
</Link>
<div className=" h-[1px] w-full bg-gray-600" />
<Link
href="/clients"
className="cursor-pointer flex px-2 space-x-4"
onClick={() => dispatch(toggleMenu(!toggle))}
>
<TruckIcon className="h-6 w-6 text-black" />
<h1>Clients</h1>
</Link>
<div className=" h-[1px] w-full bg-gray-600" />
<Link
href="/employee"
className="cursor-pointer flex px-2 space-x-4"
onClick={() => dispatch(toggleMenu(!toggle))}
>
<PuzzlePieceIcon className="h-6 w-6 text-black" />
<h1>Employee</h1>
</Link>
<div className=" h-[1px] w-full bg-gray-600" />
<Link
href="/services"
className="cursor-pointer flex px-2 space-x-4"
onClick={() => dispatch(toggleMenu(!toggle))}
>
<WrenchIcon className="h-6 w-6 text-black" />
<h1>Services</h1>
</Link>
</div>
</div>
);
}
Inside Modal component add this useEffect. since you are using tailwind-css, add overflow-hidden className to the body element
useEffect(() => {
// this will disable the scroll if our back page was scrollable
document.body.classList.add("overflow-hidden");
// when you close the modal, remove this class
return () => {
document.body.classList.remove("overflow-hidden");
};
}, []);

Accordion closing imediately after opening with tailwind css

I have the following accordion item:
<div class="accordion-item mb-5 overflow-hidden rounded-lg border border-jacarta-100 dark:border-jacarta-600">
<h2 class="accordion-header" id="faq-heading-1">
<button class="accordion-button relative flex w-full items-center justify-between bg-white px-4 py-3 text-left font-display text-jacarta-700 dark:bg-jacarta-700 dark:text-white" type="button" data-bs-toggle="collapse" data-bs-target="#faq-1" aria-expanded="false" aria-controls="faq-1">
<span>What is tax and legal advisory?</span>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" class="accordion-arrow h-4 w-4 shrink-0 fill-jacarta-700 transition-transform dark:fill-white">
<path fill="none" d="M0 0h24v24H0z"></path>
<path d="M12 13.172l4.95-4.95 1.414 1.414L12 16 5.636 9.636 7.05 8.222z"></path>
</svg>
</button>
</h2>
<div id="faq-1" class="accordion-collapse" aria-labelledby="faq-heading-1" data-bs-parent="#accordionFAQ">
<div class="accordion-body border-t border-jacarta-100 bg-white p-4 dark:border-jacarta-600 dark:bg-jacarta-700">
<p class="dark:text-jacarta-200">Learn how to create your very first NFT and how to create your NFT collections. Unique.
</p>
</div>
</div>
</div>
This item closes immediately after opening:
I expect to see this:
I have determined that unselecting the following css features via browser inspector gives me what I want:
For some reason the collapse class is added twice when I toggle the accordion. Why is the css created in a style sheet and both inline? I only have one file and it is separate. How can I fix this accordion button?
The problem arises because tailwind adds the collapse property which should be empty. Reference is below:
https://github.com/tailwindlabs/tailwindcss/issues/9663
For short term solution do the following:
In tailwind.config.js add this property:
corePlugins: {
visibility: false
},
In src/css/style.css add this:
#layer utilities {
.visible {
visibility: visible;
}
.invisible {
visibility: hidden;
}
}

Tailwind and DaisyUI in a Next.js app, I can't get the navbar to stretch across the entire webpage

I have a next.js app that uses DaisyUI which is a tailwind based css component library. The problem is that I can't get any DaisyUI navbar to stretch all the way across the webpage horizontally. The navbar components stack up vertically crowding to the left side of the page.
This is the way that it's supposed to look
So I copied the JSX code from the DaisyUI example into my next.js app's Layout but as you can see from the first image it didn't work.
This is the relevant code from my app:"_app.tsx"
import '../styles/globals.css'
import type { AppProps } from 'next/app'
import Layout from '../components/Layout'
function MyApp({ Component, pageProps }: AppProps) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
)
}
export default MyApp
"index.tsx"
import type { NextPage } from 'next'
import { useState } from 'react'
import styles from '../styles/Home.module.css'
const Home: NextPage = () => {
return (
<div className="hero min-h-screen bg-base-200">
<div className="hero-content text-center">
<div className="max-w-md">
<h1 className="text-5xl font-bold">Hello visitor</h1>
<p className="py-6">This is a placeholder for the landing page of my website</p>
<button className="btn btn-primary">Get Started</button>
</div>
</div>
</div>
)
}
export default Home
"components/Layout.tsx"
import Head from 'next/head'
import Image from 'next/image'
import styles from '../styles/Home.module.css'
const Layout = ({ children } : { children: any }) => {
return (
<div data-theme="synthwave" className={styles.container}>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<div className="navbar bg-base-100">
<div className="navbar-start">
<div className="dropdown">
<label tabIndex={0} className="btn btn-ghost btn-circle">
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 6h16M4 12h16M4 18h7" /></svg>
</label>
<ul tabIndex={0} className="menu menu-compact dropdown-content mt-3 p-2 shadow bg-base-100 rounded-box w-52">
<li><a>Homepage</a></li>
<li><a>Portfolio</a></li>
<li><a>About</a></li>
</ul>
</div>
</div>
<div className="navbar-center">
<a className="btn btn-ghost normal-case text-xl">daisyUI</a>
</div>
<div className="navbar-end">
<button className="btn btn-ghost btn-circle">
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" /></svg>
</button>
<button className="btn btn-ghost btn-circle">
<div className="indicator">
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" /></svg>
<span className="badge badge-xs badge-primary indicator-item"></span>
</div>
</button>
</div>
</div>
<main className={styles.main}>
{children}
</main>
<footer className={styles.footer}>
<a
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Powered by{' '}
<span className={styles.logo}>
<Image src="/vercel.svg" alt="Vercel Logo" width={72} height={16} />
</span>
</a>
</footer>
</div>
);
};
export default Layout
Also this is the tailwind.config.js file:
/** #type {import('tailwindcss').Config} */
module.exports = {
//...
content: ['./pages/**/*.{js,ts,jsx,tsx}'],
plugins: [require("daisyui")],
daisyui: {
styled: true,
themes: true,
base: true,
utils: true,
logs: true,
rtl: false
}
}
I don't understand why the navbar is getting scrunched together on the left side. As you can see, the synthwave theme is being loaded just fine. Also the Head, "Hello visitor" hero, Get Started button, etc... are all loading fine. The navbar just won't stretch. So why is the navbar not extending across the entire page horizontally?
​
The problem was with the tailwind.config.js file. I changed it to this:
/** u/type {import('tailwindcss').Config} */
module.exports = {
//...
content: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
plugins: [require("daisyui")],
daisyui: {
styled: true,
themes: true,
base: true,
utils: true,
logs: true,
rtl: false
}
}
As you can see, I added './components/**/*.{js,ts,jsx,tsx}' to the content section of the file. This applies DaisyUI to the Layout.tsx file

How to avoid same row divs from taking extra height (using grid)

I dont want the folders not to take the extra height.
The folder object destructered here:
<div className='grid grid-cols-3 gap-4'>
{folders &&
folders.map((folder, index) => (
<Folder folder={folder} index={index} key={index} />
))}
</div>
The Folder.jsx
as you can see it is takig the extra height.
<div
className="border-2 border-gray-400 rounded-lg max-w-xs"
key={index}
>
<div className="flex my-2 mx-1 justify-between">
<p>{folder.name}</p>
<div>
<AddLink folderName={folder.name} />
<button onClick={() => deleteFolder(folder.name)}>
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
/>
</svg>
</button>
</div>
</div>
<p className="flex sm:text-xs justify-end">{folder.date}</p>

Resources