Mobile Navigation - Copy this React, Tailwind Component to your project
Import { useState, useEffect } from "react"; import { NavLink } from "react router dom"; import { AnimatePresence, motion } from "framer motion"; import { Menu, X, ChevronRight, Phone, Mail, MapPin } from "lucide react"; const data = [ { title: "Trang chủ", href: "/" }, { title: "Thuê xe 4 chỗ", href: "/thue xe 4 cho" }, { title: "Thuê xe 7 chỗ", href: "/thue xe 7 cho" }, { title: "Thuê xe 16 chỗ", href: "/thue xe 16 cho" }, { title: "Thuê xe 29 chỗ", href: "/thue xe 29 cho" }, ]; const menuVariants = { closed: { opacity: 0, x: "100%" }, open: { opacity: 1, x: 0, transition: { type: "spring", stiffness: 300, damping: 30 }, }, }; const linkVariants = { closed: { x: 20, opacity: 0 }, open: { x: 0, opacity: 1 }, }; const overlayVariants = { closed: { opacity: 0 }, open: { opacity: 1 }, }; export default function MobileNavbar() { const [isOpen, setIsOpen] = useState(false); useEffect(() => { document.body.style.overflow = isOpen ? "hidden" : "unset"; }, [isOpen]); return ( <nav className="z 50 lg:hidden flex 1 flex justify end"> {!isOpen && ( <button onClick={() => setIsOpen(true)} className="z 50 p 3 border border gray 600 rounded full text gray 600 hover:bg gray 200 transition all duration 300" aria label="Open menu" > <Menu size={24} /> </button> )} <AnimatePresence> {isOpen && ( <> <motion.div variants={overlayVariants} initial="closed" animate="open" exit="closed" transition={{ duration: 0.3 }} className="fixed inset 0 bg black bg opacity 50" onClick={() => setIsOpen(false)} /> <motion.div variants={menuVariants} initial="closed" animate="open" exit="closed" className="fixed top 0 right 0 w 80 h screen bg white flex flex col" > <div className="p 6 flex justify between items center border b border gray 300"> <h2 className="text 2xl font bold text gray 800"> Minh Khang Travel </h2> <button onClick={() => setIsOpen(false)} className="p 2 rounded full text gray 600 hover:bg gray 200 transition all duration 300" aria label="Close menu" > <X size={24} /> </button> </div> <ul className="space y 4 p 6"> {data.map((item, index) => ( <motion.li key={item.href} variants={linkVariants} initial="closed" animate="open" exit="closed" transition={{ delay: index * 0.1 }} > <NavLink to={item.href} className={({ isActive }) => `flex items center py 3 text lg rounded lg transition all duration 300 ease in out ${ isActive ? "text blue 600 font semibold bg blue 50" : "text gray 600 hover:text blue 600 hover:bg gray 100" }` } onClick={() => setIsOpen(false)} > {item.title} <ChevronRight className="ml auto opacity 0 group hover:opacity 100 transition opacity duration 300" size={20} /> </NavLink> </motion.li> ))} </ul> <div className="mt auto p 6 bg white"> <h3 className="text lg font semibold text gray 800 mb 4"> Liên hệ với chúng tôi </h3> <ul className="space y 3"> <li className="flex items center text gray 600"> <Phone size={18} className="mr 2 text gray 800" /> <a href="tel:+84123456789" className="hover:text blue 600 transition colors" > +84 123 456 789 </a> </li> <li className="flex items center text gray 600"> <Mail size={18} className="mr 2 text gray 800" /> <a href="mailto:info@minhkhangtravel.com" className="hover:text blue 600 transition colors" > info@minhkhangtravel.com </a> </li> <li className="flex items center text gray 600"> <MapPin size={18} className="mr 2 text gray 800" /> <span>123 Đường ABC, Quận XYZ, TP.HCM</span> </li> </ul> </div> </motion.div> </> )} </AnimatePresence> </nav> ); }
