Fix menu for mobile and small screens
This commit is contained in:
parent
db358e48bf
commit
62433173eb
3 changed files with 243 additions and 876 deletions
13
package.json
13
package.json
|
|
@ -10,21 +10,22 @@
|
||||||
"lint": "next lint"
|
"lint": "next lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@emotion/is-prop-valid": "^1.3.1",
|
||||||
"@headlessui/react": "^2.2.0",
|
"@headlessui/react": "^2.2.0",
|
||||||
|
"framer-motion": "11.12.0",
|
||||||
"lucide-react": "^0.462.0",
|
"lucide-react": "^0.462.0",
|
||||||
"next": "15.0.3",
|
"next": "15.0.3",
|
||||||
"react": "19.0.0-rc-66855b96-20241106",
|
"react": "18.3.1",
|
||||||
"react-dom": "19.0.0-rc-66855b96-20241106",
|
"react-dom": "18.3.1",
|
||||||
"react-icons": "^5.0.1"
|
"react-icons": "^5.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/next": "^8.0.7",
|
"@types/node": "^22.10.1",
|
||||||
"@types/node": "^22.10.0",
|
|
||||||
"@types/react": "^18.3.12",
|
"@types/react": "^18.3.12",
|
||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "^18.3.1",
|
||||||
"@typescript-eslint/parser": "^8.16.0",
|
"@typescript-eslint/parser": "^8.16.0",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"eslint": "^9.15.0",
|
"eslint": "^9.16.0",
|
||||||
"eslint-config-next": "15.0.3",
|
"eslint-config-next": "15.0.3",
|
||||||
"eslint-plugin-import": "^2.31.0",
|
"eslint-plugin-import": "^2.31.0",
|
||||||
"postcss": "^8.4.49",
|
"postcss": "^8.4.49",
|
||||||
|
|
|
||||||
944
pnpm-lock.yaml
generated
944
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,9 +1,18 @@
|
||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useState } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { Menu, X } from 'lucide-react';
|
import { Menu, X } from 'lucide-react';
|
||||||
|
import dynamic from 'next/dynamic';
|
||||||
|
|
||||||
|
const MotionDiv = dynamic(() => import('framer-motion').then(mod => mod.motion.div), {
|
||||||
|
ssr: false
|
||||||
|
});
|
||||||
|
|
||||||
|
const AnimatePresence = dynamic(() => import('framer-motion').then(mod => mod.AnimatePresence), {
|
||||||
|
ssr: false
|
||||||
|
});
|
||||||
|
|
||||||
const navigation = [
|
const navigation = [
|
||||||
{ name: 'Home', href: '/' },
|
{ name: 'Home', href: '/' },
|
||||||
|
|
@ -21,6 +30,7 @@ export default function Header() {
|
||||||
<div className="flex lg:flex-1">
|
<div className="flex lg:flex-1">
|
||||||
<Link href="/" className="-m-1.5 p-1.5">
|
<Link href="/" className="-m-1.5 p-1.5">
|
||||||
<span className="sr-only">FINLION</span>
|
<span className="sr-only">FINLION</span>
|
||||||
|
<MotionDiv whileHover={{ scale: 1.05 }}>
|
||||||
<Image
|
<Image
|
||||||
className="h-12 w-auto"
|
className="h-12 w-auto"
|
||||||
src="/images/logo.jpg"
|
src="/images/logo.jpg"
|
||||||
|
|
@ -29,100 +39,92 @@ export default function Header() {
|
||||||
height={48}
|
height={48}
|
||||||
priority
|
priority
|
||||||
/>
|
/>
|
||||||
|
</MotionDiv>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Mobile menu button */}
|
|
||||||
<div className="flex lg:hidden">
|
<div className="flex lg:hidden">
|
||||||
<button
|
<MotionDiv
|
||||||
type="button"
|
whileTap={{ scale: 0.95 }}
|
||||||
className="-m-2.5 inline-flex items-center justify-center rounded-md p-2.5 text-gray-700"
|
className="inline-flex items-center justify-center rounded-md p-2.5 text-gray-700 hover:bg-gray-100 transition-colors"
|
||||||
onClick={() => setMobileMenuOpen(true)}
|
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
|
||||||
>
|
>
|
||||||
<span className="sr-only">Open main menu</span>
|
<span className="sr-only">Toggle menu</span>
|
||||||
|
{mobileMenuOpen ? (
|
||||||
|
<X className="h-6 w-6" aria-hidden="true" />
|
||||||
|
) : (
|
||||||
<Menu className="h-6 w-6" aria-hidden="true" />
|
<Menu className="h-6 w-6" aria-hidden="true" />
|
||||||
</button>
|
)}
|
||||||
|
</MotionDiv>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Desktop navigation */}
|
{/* Desktop Navigation */}
|
||||||
<div className="hidden lg:flex lg:gap-x-12">
|
<div className="hidden lg:flex lg:gap-x-12">
|
||||||
{navigation.map((item) => (
|
{navigation.map((item) => (
|
||||||
|
<MotionDiv key={item.name} whileHover={{ scale: 1.05 }}>
|
||||||
<Link
|
<Link
|
||||||
key={item.name}
|
|
||||||
href={item.href}
|
href={item.href}
|
||||||
className="text-sm font-semibold leading-6 text-gray-900 hover:text-blue-800 transition-colors"
|
className="text-sm font-semibold leading-6 text-gray-900 hover:text-blue-800 transition-colors"
|
||||||
>
|
>
|
||||||
{item.name}
|
{item.name}
|
||||||
</Link>
|
</Link>
|
||||||
|
</MotionDiv>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* CTA Button */}
|
|
||||||
<div className="hidden lg:flex lg:flex-1 lg:justify-end">
|
<div className="hidden lg:flex lg:flex-1 lg:justify-end">
|
||||||
|
<MotionDiv whileHover={{ scale: 1.05 }} whileTap={{ scale: 0.95 }}>
|
||||||
<Link
|
<Link
|
||||||
href="/contact"
|
href="/contact"
|
||||||
className="rounded-md bg-blue-800 px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-blue-700 transition-colors"
|
className="rounded-md bg-blue-800 px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-blue-700 transition-colors"
|
||||||
>
|
>
|
||||||
Get Started
|
Get Started
|
||||||
</Link>
|
</Link>
|
||||||
|
</MotionDiv>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
{/* Mobile menu */}
|
{/* Mobile Navigation Menu */}
|
||||||
|
<AnimatePresence>
|
||||||
{mobileMenuOpen && (
|
{mobileMenuOpen && (
|
||||||
<div className="lg:hidden">
|
<>
|
||||||
<div className="fixed inset-0 z-50">
|
<MotionDiv
|
||||||
<div className="fixed inset-y-0 right-0 z-50 w-full overflow-y-auto bg-white px-6 py-6 sm:max-w-sm sm:ring-1 sm:ring-gray-900/10">
|
initial={{ opacity: 0 }}
|
||||||
<div className="flex items-center justify-between">
|
animate={{ opacity: 1 }}
|
||||||
<Link href="/" className="-m-1.5 p-1.5">
|
exit={{ opacity: 0 }}
|
||||||
<span className="sr-only">FINLION</span>
|
className="fixed inset-0 bg-black/20 backdrop-blur-sm z-40"
|
||||||
<Image
|
|
||||||
className="h-8 w-auto"
|
|
||||||
src="/images/logo.jpg"
|
|
||||||
alt="FINLION Logo"
|
|
||||||
width={120}
|
|
||||||
height={32}
|
|
||||||
priority
|
|
||||||
/>
|
|
||||||
</Link>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="-m-2.5 rounded-md p-2.5 text-gray-700"
|
|
||||||
onClick={() => setMobileMenuOpen(false)}
|
onClick={() => setMobileMenuOpen(false)}
|
||||||
|
/>
|
||||||
|
<MotionDiv
|
||||||
|
className="fixed inset-0 z-50"
|
||||||
|
initial={{ x: '-100%' }}
|
||||||
|
animate={{ x: 0 }}
|
||||||
|
exit={{ x: '-100%' }}
|
||||||
|
transition={{ type: 'tween', duration: 0.3 }}
|
||||||
>
|
>
|
||||||
<span className="sr-only">Close menu</span>
|
<div className="fixed inset-y-0 w-full bg-white pt-24">
|
||||||
<X className="h-6 w-6" aria-hidden="true" />
|
<nav className="flex flex-col items-center space-y-8 bg-white pb-8">
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div className="mt-6 flow-root">
|
|
||||||
<div className="-my-6 divide-y divide-gray-500/10">
|
|
||||||
<div className="space-y-2 py-6">
|
|
||||||
{navigation.map((item) => (
|
{navigation.map((item) => (
|
||||||
<Link
|
<MotionDiv
|
||||||
key={item.name}
|
key={item.name}
|
||||||
|
whileHover={{ scale: 1.05 }}
|
||||||
|
whileTap={{ scale: 0.95 }}
|
||||||
|
>
|
||||||
|
<Link
|
||||||
href={item.href}
|
href={item.href}
|
||||||
className="-mx-3 block rounded-lg px-3 py-2 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50"
|
className="text-xl font-semibold text-blue-800 transition-colors px-4 py-2 w-full text-center"
|
||||||
onClick={() => setMobileMenuOpen(false)}
|
onClick={() => setMobileMenuOpen(false)}
|
||||||
>
|
>
|
||||||
{item.name}
|
{item.name}
|
||||||
</Link>
|
</Link>
|
||||||
|
</MotionDiv>
|
||||||
))}
|
))}
|
||||||
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
<div className="py-6">
|
</MotionDiv>
|
||||||
<Link
|
</>
|
||||||
href="/contact"
|
|
||||||
className="-mx-3 block rounded-lg px-3 py-2.5 text-base font-semibold leading-7 text-white bg-blue-800 hover:bg-blue-700 text-center"
|
|
||||||
onClick={() => setMobileMenuOpen(false)}
|
|
||||||
>
|
|
||||||
Get Started
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
</header>
|
</header>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue