I have make a nav bar using tailwind css in next.js it is responsive and working fine.
every thing is working fine but when i click the burger button it shows the list appears instantly but i want to show the bottom (un-order list) on small screen size with smooth transition and i have no idea how to make the transition smooth
the solution of the problem i want is to make this list smoothly visible on the screen
`
import React, { useEffect, useState } from "react";
import { MenuAlt1Icon } from "#heroicons/react/outline";
function Header() {
const [isOpen, setisOpen] = React.useState(false);
const [size, setSize] = useState(0);
function handleClick() {
setisOpen(!isOpen);
}
useEffect(() => {
setSize(window.innerWidth);
window.addEventListener("resize", handleSize);
return () => window.removeEventListener("resize", handleSize);
}, []);
const handleSize = () => {
setSize(window.innerWidth);
};
`
Above is the javascript code
and below is the jsx and tailwind
return (
<header>
<nav className={` shadow-md px-5 ${isOpen && size < 640 && "pb-3"}`}>
<button
type="button"
className={`${
size >= 640 ? "hidden" : "inline-block h-12 focus:outline-none"
}`}
onClick={handleClick}
>
<MenuAlt1Icon className="h-6 w-6" />
</button>
<ul
className={` ${
size >= 640
? " flex h-12 items-center space-x-2 "
: `${
isOpen
? `block space-y-2 border-t-2 border-gray-50 pt-2 transition duration-500 ease-linear`
: `hidden`
}`
}`}
>
<li>element 1</li>
<li>element 2</li>
<li>element 3</li>
<li>element 4</li>
</ul>
</nav>
</header>
);
}
export default Header;
If you want a top to down dropdown animation, try to read: Animating max-height with CSS transitions
You can try to use these tailwind classes transition-all max-h-screen max-h-0.
Now don't be like me. By applying the class md:hidden to the navbar and hamburger you don't have to check if it clicked again to show the ul or navlinks. What you should instead do is add a negative -translate-x-full to make it display off screen and when the hamburger is clicked add a translate-x-0 to make it show by sliding into the screen. If not the sidebar won't be animated
do this
<ul className={`md:hidden flex flex-col fixed left-0 w-3/4 h-screen top-[60px] bg-green-300 items-center justify-around transition-all ease-in-out duration-200 ${isNavExpanded ? "translate-x-0 " : "-translate-x-full"}`}>
{links.map((item) => (
<li key={`link-${item}`} className="nav-link">
<a href={`#${item}`} className="">
{item}
</a>
</li>
))}
</ul>
instead of this
{isNavbarExpanded && (<ul className={`md:hidden flex flex-col fixed left-0 w-3/4 h-screen top-[60px] bg-green-300 items-center justify-around transition-all ease-in-out duration-200 ${isNavExpanded ? "translate-x-0 " : "-translate-x-full"}`}>
{links.map((item) => (
<li key={`link-${item}`} className="nav-link">
<a href={`#${item}`} className="">
{item}
</a>
</li>
))}
</ul>)}
Try this,
I used Tailwind Responsive Design way in official Doc.
so you can adjust sm: or md: in the className
import { useState } from "react";
import { MenuAlt1Icon } from "#heroicons/react/outline";
export default function Header() {
const [isOpen, setisOpen] = useState(false);
return (
<header>
<nav className={"shadow-md px-5 pb-3 sm:pb-0"}>
<button
type="button"
className={"inline-block h-12 focus:outline-none sm:hidden"}
onClick={() => setisOpen(!isOpen)}
>
<MenuAlt1Icon className="w-6 h-6" />
</button>
<ul className={`"flex flex-col sm:flex-row w-full h-auto justify-between space-x-2 space-y-2" ${isOpen === false && "hidden sm:flex"}`}>
<li>element 1</li>
<li>element 2</li>
<li>element 3</li>
<li>element 4</li>
</ul>
</nav>
</header>
);
}
Happy coding :)
Related
Demo
The text expands in width with the sidebar, when ideally, the transition is much smoother. Maybe delayed so it tricks the eye to thinking it appears only when fully expanded.
How should I think about achieving this?
<div className="flex flex-col items-center space-y-4 w-full mt-8">
<Logo open={open} />
{open && <div className="h-auto w-3/4 text-xs text-slate-400">This looks weird when the line is super long</div>}
....
Should I attach a delay? transition-delay does nothing on the inner div.
I made an over simplified example, hopefully can help finding a good solution.
This one uses a cross delay approach to make the transition smooth when opening and closing the drawer.
There is a state open controls the drawer. On the drawer container:
open ? "w-52 delay-0" : "w-12 delay-300"
And the inside element uses a reversed delay value, something like:
open ? "opacity-100 delay-300" : "opacity-0 delay-0"
This way, during both opening and closing transition, parent and child elements will have properly ordered animation.
Live demo is here: stackblitz
import React, { useState } from "react";
import "./App.css";
const list = ["Option 1", "Option 2", "Option 3", "Option 4", "Option 5"];
const ListItem = ({ open, text, index }) => {
return (
<li className={`bg-teal-100 h-12 flex justify-end`}>
<div
className={`${
open ? "w-24" : "w-12"
} flex justify-center align-center p-3 transition-all duration-300 ease-in-out`}
>
{index + 1}
</div>
<div
className={`${
open ? "opacity-100 delay-300" : "opacity-0 delay-0"
} flex justify-center align-center p-3 flex-1 transition-all duration-300 ease-in-out`}
>
{text}
</div>
</li>
);
};
const SlideDrawer = ({ open }) => {
return (
<div
className={`${
open ? "w-52 delay-0" : "w-12 delay-300"
} absolute left-0 top-0 bottom-0 transition-all duration-300 ease-in-out overflow-hidden flex justify-start bg-pink-200`}
>
<div className={`w-52 flex flex-col justify-start align-end`}>
<div
className={`${
open ? "w-52 p-6 delay-300" : "w-12 p-3 delay-0"
} h-72 flex flex-col justify-start align-center transition-all duration-300 ease-in-out `}
>
<figure
className={`${
open ? "w-40 h-40 delay-300" : "w-6 h-6 delay-0"
} transition-all bg-teal-100 rounded-full duration-300 ease-in-out`}
></figure>
</div>
<ul className="w-full flex flex-col list-none">
{list.map((item, index) => (
<ListItem key={item} open={open} index={index} text={item} />
))}
</ul>
</div>
</div>
);
};
function App() {
const [drawerOpen, setDrawerOpen] = useState(false);
return (
<>
<div className="w-full flex justify-end">
<button
className="m-6 p-3 rounded-lg bg-slate-300"
onClick={() => setDrawerOpen((prev) => !prev)}
>
Open drawer
</button>
</div>
<SlideDrawer open={drawerOpen} />
</>
);
}
export default App;
As you can see the underline is not complete filling the full length. I couldn't figure out why that is. This is made with tailwindCSS. Does anyone know where to find the full width for the deposit part?
My code:
function MyPage() {
const [currentTab, setCurrentTab] = useState<string>("deposit");
const [inputValue, setInputValue] = useState<string>("");
const [outputValue, setOutputValue] = useState<string>();
function classNames(...classes: string[]) {
return classes.filter(Boolean).join(" ");
}
return(
<div className="text-sm font-medium text-center text-gray-500 border-b border-gray-200 dark:text-gray-400 dark:border-gray-700">
<ul className="flex flex-wrap -mb-px">
<li className="mr-2 ">
<button
onClick={() => {
setCurrentTab("withdrawal"),
currentTab != "withdrawal" ? setOutputValue("") : null;
}}
className={classNames(
currentTab == "withdrawal"
? "text-gray-100 border-gray-100 inline-block p-4 border-b-2 rounded-t-lg active"
: "inline-block p-4 rounded-t-lg active transition-all ease-in duration-100"
)}
>
Withdrawal
</button>
</li>
<li className="mr-2 ">
<button
onClick={() => {
setCurrentTab("deposit"), currentTab != "deposit" ? setOutputValue("") : null;
}}
className={classNames(
currentTab == "deposit"
? " text-gray-100 border-gray-100 inline-block p-4 border-b-2 rounded-t-lg active"
: "inline-block p-4 rounded-t-lg active transition-all ease-in duration-100 "
)}
aria-current="page"
>
Deposit
</button>
</li>
</ul>
</div>
)
}
mr-2 class for button's wrapper element <li className="mr-2"> creates margin on the right side of every li element of the loop - so your button cannot stretch on full width.
By adding last:mr-0 we're simply removing margin for the last child element of the loop. The example for this can be found here
<li className="mr-2 last:mr-0">
Compiled CSS for last:mr-0 would look like
.last\:mr-0:last-child {
margin-right: 0px;
}
Navbar menu items are shown in mobile view and function correctly but in the desktop mode, they are hidden. I am a beginner in tailwind so appreciate some detailed answers Thank you!
I am using react with typescript.
code:-
import React, { useState } from 'react'
import CloseIcon from '../../assets/icons/close.svg';
import HamburgerMenuIcon from '../../assets/icons/hamburger-menu.svg';
export const HeaderBar = () => {
const [toggle, setToggle] = useState(false);
const links = [
{ name: "Home", link: "/" },
{ name: "About", link: "/" },
{ name: "Work", link: "/" },
{ name: "Experience", link: "/" },
{ name: "Contact", link: "/" }
]
return (
<div className='shadow-md w-full fixed top-0 left-0'>
<div className='md:flex items:center justify-between bg-white bg-opacity-10 backdrop-filter backdrop-blur-sm py-4 md:px-10 px-7'>
<div className='font-bold text2xl cursor-pointer flex items-center font-[poppins] text-gray-800 bg-slate-900'>
<span className='text-3xl'></span>
Designer
</div>
<div className='text-3xl absolute right-8 top-6 md:hidden cursor-pointer' onClick={() => { setToggle(!toggle) }}>
<img src={toggle ? CloseIcon : HamburgerMenuIcon} height={20} width={20} />
</div>
<ul className={` bg-white md:flex md:items-center md:pb-0 absolute md:static md:z-auto z-[-1] left-0 w-full md:w-auto bg-red-600 md:pl-0 pl-4 transition-all duration-500 ease-in-out ${toggle ? 'top-[55px] opacity-100' : '-top-[140px] opacity-0'} `}>
{links.map((link) => {
return (
<li key={link.name} className='bg-white bg-opacity-10 backdrop-filter backdrop-blur-sm md:ml-8 text-md md:my-0 my-4 '>
<a href={link.link} className='text-gray-800 hover:text-gray-400 duration:500'>
{link.name}
</a>
</li>
)
})}
</ul>
</div>
</div >
);
};
I found the bug here
${toggle ? 'top-[55px] opacity-100' : '-top-[140px] opacity-0'} `}>
should change to
${!toggle ? 'top-[55px] opacity-100' : '-top-[140px] opacity-0'} `}>
I'm trying to make a responsive nav bar with tailwind. I want to list my nav links with a single item in each row when I open the navigation menu. Right now, they are all on one row. I'm using tailwind:
function Navbar() {
const [isOpen, setIsOpen] = useState(false);
return (
<header>
<div className="flex flex-col max-w-screen-xl px-4 mx-auto md:items-center md:justify-between md:flex-row md:px-6 lg:px-8">
<div className="p-4 flex flex-row items-center justify-between">
<Link href="/">
<a className="text-lg font-semibold tracking-widest text-gray-900 uppercase rounded-lg dark-mode:text-white focus:outline-none focus:shadow-outline">
Header
</a>
</Link>
<button
className="md:hidden rounded-lg focus:outline-none focus:shadow-outline"
onClick={() => {
setIsOpen(!isOpen);
}}
>
Menu
</button>
</div>
<nav className={isOpen ? "flex" : "md:flex hidden"}>
<NavLink pathTo="/" displayText="Home" />
<NavLink pathTo="/" displayText="Page 1" />
<NavLink pathTo="/" displayText="Page 2" />
</nav>
</div>
</header>
);
}
export default Navbar;
My NavLink component is as follows:
import React from "react";
import Link from "next/link";
interface NavItem {
pathTo: string;
displayText: string;
}
function NavLink(item: NavItem) {
return (
<Link href={item.pathTo}>
<a className="block lg:p-4 px-4 py-2 mt-2 border-b-2 border-white text-sm bg-transparent dark-mode:bg-transparent dark-mode:hover:border-red-400 dark-mode:focus:border-red-400 dark-mode:focus:text-white dark-mode:text-gray-200 md:mt-0 md:ml-4 hover:text-gray-900 focus:text-gray-900 hover:border-red-400 focus:border-red-400">
{item.displayText}
</a>
</Link>
);
}
export default NavLink;
What am I missing? I want the NavLinks to have one item on each row when opened from the menu. I thought display:block would do it, but it seems not to. Why's that?
You need to add a flex direction to your nav links. Adding flex-col should do the trick.
I am working on a project with React and using Tailwind as my CSS.
I have got a Sidebar that should really not be present in the landing page when user lands only when clicking burger menu. At the moment this is present when user lands and it's looking slightly funny. I am thinking this might be related with the fact that tailwind doesn't recognise activeclasses in Ternary Operators.
My code:
import React, {useState} from 'react';
import {Link} from 'react-router-dom';
import * as FaIcons from 'react-icons/fa';
import * as AiIcons from 'react-icons/ai';
import {SidebarData} from './SidebarData';
function Navbar() {
const [sidebar,setSidebar] = useState(false)
const showSidebar =() => setSidebar(!sidebar)
return(
<>
<div className="navbar flex bg-white text-black h-12 justify-start items-center m-0 p-0 ">
<Link to ="#" className="menu-bars ml-8 text-4xl bg-none">
<FaIcons.FaBars onClick={showSidebar}/>
</Link>
</div>
<nav className={sidebar ? 'nav-menu active left-0 transition duration-250 ' : 'nav-menu bg-white w-1/4 h-screen flex justify-center fixed top-0 -left-100 transition duration-1000'}>
<ul className="nav-menu-items w-full " onClick={showSidebar}>
<li className="navbar-toggle w-full h-5 flex justify-start items-center">
<Link to='#' className="menu-bars flex justify-start items-center pt-8 pr-0 pb-10 list-none h-1">
<AiIcons.AiOutlineClose/>
</Link>
</li>
{SidebarData.map((item,index) =>{
return (
<li key={index} className="{item.cName}">
<Link to={item.path} className="text w-11/12 h-full flex items-center pt-0 pb-1 border">
{item.icon}
<span className="ml-1">{item.title}</span>
</Link>
</li>
)
})}
</ul>
</nav>
</>
);
}
How it looks like:
How it should really look like when you land:
After clicking the burger menu:
This one is in black but you get the picture. It's quite different.
All help is appreciated,thanks!
Please make sure that your tailwind config files are configured properly for the active class and check out this tutorial here