Initial commit
This commit is contained in:
159
src/components/home/AppPromo.tsx
Normal file
159
src/components/home/AppPromo.tsx
Normal file
@@ -0,0 +1,159 @@
|
||||
import Image from "next/image";
|
||||
import { MaterialIcon } from "@/components/ui/MaterialIcon";
|
||||
|
||||
const FEATURES = [
|
||||
{
|
||||
title: "Eco-Friendly Routing",
|
||||
desc: "Our routing software matches you to stores within 2km to minimize delivery times and energy.",
|
||||
icon: "near_me",
|
||||
},
|
||||
{
|
||||
title: "Live Courier Tracking",
|
||||
desc: "See your neighborhood runner on a live map as they collect your essentials and ride to your gate.",
|
||||
icon: "map",
|
||||
},
|
||||
{
|
||||
title: "Secure Digital Payments",
|
||||
desc: "Enjoy quick checkouts via UPI, credit/debit cards, and integrated wallet coins with cashbacks.",
|
||||
icon: "payments",
|
||||
},
|
||||
];
|
||||
|
||||
export function AppPromo() {
|
||||
return (
|
||||
<section
|
||||
id="download"
|
||||
className="py-24 px-margin-mobile md:px-margin-desktop bg-brand-cream overflow-hidden border-t border-outline-variant/10"
|
||||
>
|
||||
<div className="max-w-container-max mx-auto relative">
|
||||
{/* Background Dot pattern */}
|
||||
<div
|
||||
className="absolute inset-0 opacity-[0.03] pointer-events-none"
|
||||
style={{
|
||||
backgroundImage: "radial-gradient(#120217 2px, transparent 2px)",
|
||||
backgroundSize: "24px 24px",
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="grid md:grid-cols-12 gap-12 items-center relative z-10">
|
||||
|
||||
{/* Left Column: Typography, benefits, download actions (7 cols) */}
|
||||
<div className="md:col-span-7">
|
||||
<span className="text-label-sm text-primary uppercase tracking-widest font-black bg-primary/5 px-3.5 py-1.5 rounded-full border border-primary/10">
|
||||
Download Nearle Mobile
|
||||
</span>
|
||||
|
||||
<h2 className="text-display text-brand-dark mt-6 mb-6 leading-[1.1] tracking-tight">
|
||||
Get More With Our <br />
|
||||
<span className="text-primary font-black">Mobile Application</span>
|
||||
</h2>
|
||||
|
||||
<p className="text-body-lg text-on-surface-variant mb-10 max-w-lg leading-relaxed">
|
||||
Experience the fastest way to order groceries, hot food, and emergency home maintenance. Download the app today for live updates and community coins.
|
||||
</p>
|
||||
|
||||
{/* Benefit Bullets */}
|
||||
<div className="space-y-6 mb-10">
|
||||
{FEATURES.map((item) => (
|
||||
<div key={item.title} className="flex gap-4">
|
||||
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-brand-accent/20 flex items-center justify-center">
|
||||
<MaterialIcon icon={item.icon} size={18} className="text-brand-dark" />
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="text-label-md font-bold text-brand-dark">{item.title}</h4>
|
||||
<p className="text-body-md text-on-surface-variant mt-0.5 leading-relaxed">
|
||||
{item.desc}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Store Badges */}
|
||||
<div className="flex flex-wrap gap-4 mt-8">
|
||||
<a
|
||||
href="https://apps.apple.com"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="h-14 border border-brand-dark/20 rounded-2xl hover:bg-brand-dark hover:text-white transition-all duration-300 px-6 py-2 flex items-center gap-3 group hover:-translate-y-1 hover:shadow-lg bg-white"
|
||||
>
|
||||
<svg viewBox="0 0 24 24" className="w-6 h-6 shrink-0 fill-current text-brand-dark group-hover:text-white transition-colors" fill="currentColor">
|
||||
<path d="M17.537 12.625c-.023-2.949 2.398-4.37 2.506-4.44-1.364-2.008-3.48-2.282-4.227-2.307-1.79-.186-3.504 1.064-4.413 1.064-.918 0-2.323-1.04-3.827-1.01-1.963.028-3.788 1.146-4.796 2.91-2.06 3.587-.526 8.9 1.466 11.808.98 1.428 2.147 3.035 3.685 2.975 1.47-.059 2.03-.964 3.807-.964 1.767 0 2.266.964 3.818.932 1.58-.03 2.58-1.453 3.536-2.89 1.116-1.628 1.57-3.21 1.596-3.29-.035-.016-3.057-1.18-3.087-4.678l.036-.002zM14.87 4.058c.821-.99 1.375-2.361 1.223-3.733-1.184.05-2.618.784-3.47 1.77-.762.875-1.43 2.28-1.25 3.623 1.327.102 2.673-.668 3.497-1.66z" />
|
||||
</svg>
|
||||
<div className="text-left leading-tight">
|
||||
<div className="text-[9px] opacity-75 font-semibold tracking-wider uppercase">
|
||||
Download on the
|
||||
</div>
|
||||
<div className="text-headline-md font-black -mt-0.5">
|
||||
App Store
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="https://play.google.com/store/apps/details?id=com.nearle.gear"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="h-14 border border-brand-dark/20 rounded-2xl hover:bg-brand-dark hover:text-white transition-all duration-300 px-6 py-2 flex items-center gap-3 group hover:-translate-y-1 hover:shadow-lg bg-white"
|
||||
>
|
||||
<svg viewBox="0 0 24 24" className="w-6 h-6 shrink-0 fill-current text-brand-dark group-hover:text-white transition-colors" fill="currentColor">
|
||||
<path d="M3.609 1.814L13.414 12 3.609 22.186c-.244-.178-.395-.466-.395-.786V2.6c0-.32.151-.608.395-.786zM14.244 12.83l2.705 2.688-4.073 2.276-4.073 2.276L14.244 12.83zm1-1.66l2.838-2.8 4.153 2.336c.464.26.464.688 0 .948l-4.153 2.336-2.838-2.82zM8.803 4.93l4.073 2.276 4.073 2.276-2.705 2.688L8.803 4.93z" />
|
||||
</svg>
|
||||
<div className="text-left leading-tight">
|
||||
<div className="text-[9px] opacity-75 font-semibold tracking-wider uppercase">
|
||||
GET IT ON
|
||||
</div>
|
||||
<div className="text-headline-md font-black -mt-0.5">
|
||||
Google Play
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right Column: Phone Mockup showcase (5 cols) */}
|
||||
<div className="md:col-span-5 flex justify-center md:justify-end relative">
|
||||
{/* Background glowing circle */}
|
||||
<div className="absolute w-80 h-80 bg-brand-accent/10 rounded-full blur-2xl pointer-events-none -right-10 top-10" />
|
||||
|
||||
<div className="relative w-full max-w-[270px] animate-float">
|
||||
{/* iPhone style phone container */}
|
||||
<div className="bg-[#120217] w-full aspect-[9/18.5] rounded-[3rem] border-[6px] border-brand-dark-surface shadow-2xl relative overflow-hidden ring-4 ring-outline-variant/15">
|
||||
{/* Speaker notch */}
|
||||
<div className="absolute top-2.5 left-1/2 -translate-x-1/2 w-24 h-4 bg-black rounded-full z-20 flex items-center justify-center">
|
||||
<div className="w-12 h-1 bg-zinc-800 rounded-full" />
|
||||
</div>
|
||||
|
||||
<Image
|
||||
src="/images/app-mockup.png"
|
||||
alt="Nearle mobile app interface showing neighborhood services"
|
||||
width={360}
|
||||
height={760}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Overlapping alert bubble */}
|
||||
<div className="absolute -left-10 top-1/4 bg-white/95 backdrop-blur-md p-4 rounded-2xl shadow-2xl border border-outline-variant/20 hidden lg:block hover:scale-105 transition-transform duration-300">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-8 h-8 rounded-full bg-secondary-fixed flex items-center justify-center">
|
||||
<MaterialIcon
|
||||
icon="check_circle"
|
||||
size={18}
|
||||
className="text-secondary"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-label-md font-black text-brand-dark">Order Dispatched</p>
|
||||
<p className="text-[10px] text-on-surface-variant font-medium">Runner is arriving in 4 mins</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
162
src/components/home/BusinessSection.tsx
Normal file
162
src/components/home/BusinessSection.tsx
Normal file
@@ -0,0 +1,162 @@
|
||||
import Image from "next/image";
|
||||
import { MaterialIcon } from "@/components/ui/MaterialIcon";
|
||||
|
||||
const FEATURES = [
|
||||
{
|
||||
title: "Direct Customer Relationship",
|
||||
desc: "Build long-term direct ties with nearby families. Own your neighborhood presence.",
|
||||
},
|
||||
{
|
||||
title: "Managed Instant Delivery Fleet",
|
||||
desc: "We supply professional, verified moped couriers. Focus on your business, not hiring drivers.",
|
||||
},
|
||||
{
|
||||
title: "Neighborhood Demand Trends",
|
||||
desc: "Use Nearle's analytic insights to track demand, optimize your stock, and launch promos.",
|
||||
},
|
||||
];
|
||||
|
||||
const STATS = [
|
||||
{
|
||||
value: "40%+",
|
||||
label: "Average Revenue Rise",
|
||||
icon: "trending_up",
|
||||
style: "bg-primary text-white",
|
||||
},
|
||||
{
|
||||
value: "12k+",
|
||||
label: "Daily Neighborhood Orders",
|
||||
icon: "shopping_bag",
|
||||
style: "bg-brand-accent text-brand-dark",
|
||||
},
|
||||
{
|
||||
value: "5k+",
|
||||
label: "Verified Retail Partners",
|
||||
icon: "storefront",
|
||||
style: "bg-[#faf8f5] border border-outline-variant/20 text-primary",
|
||||
},
|
||||
{
|
||||
value: "24/7",
|
||||
label: "Partner Helpdesk Support",
|
||||
icon: "support_agent",
|
||||
style: "bg-[#de96f9]/20 text-primary border border-primary/10",
|
||||
},
|
||||
];
|
||||
|
||||
export function BusinessSection() {
|
||||
return (
|
||||
<section className="py-24 px-margin-mobile md:px-margin-desktop bg-white">
|
||||
<div className="max-w-container-max mx-auto">
|
||||
|
||||
{/* Merchant Section Grid */}
|
||||
<div className="grid lg:grid-cols-12 gap-16 items-center">
|
||||
|
||||
{/* Left Column: Feature copywriting (7 cols) */}
|
||||
<div className="lg:col-span-7">
|
||||
<span className="text-label-sm text-secondary uppercase tracking-widest font-black bg-secondary/5 px-3.5 py-1.5 rounded-full border border-secondary/15">
|
||||
Merchant Partnerships
|
||||
</span>
|
||||
<h2 className="text-display text-brand-dark mt-6 mb-6 leading-tight">
|
||||
Grow your local brand in the <span className="text-secondary">Neighborhood.</span>
|
||||
</h2>
|
||||
<p className="text-body-lg text-on-surface-variant mb-12 max-w-xl leading-relaxed">
|
||||
Unlock delivery, loyalty programs, and localized promotions. Join over 5,000 neighborhood partners who are digitizing their community sales channels.
|
||||
</p>
|
||||
|
||||
<div className="space-y-8 mb-12">
|
||||
{FEATURES.map((feat) => (
|
||||
<div key={feat.title} className="flex gap-4 group">
|
||||
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-secondary/10 border border-secondary/20 flex items-center justify-center group-hover:bg-secondary group-hover:text-white transition-all duration-300">
|
||||
<MaterialIcon
|
||||
icon="check"
|
||||
size={18}
|
||||
className="text-secondary group-hover:text-white transition-colors"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="text-headline-md font-black text-brand-dark group-hover:text-primary transition-colors">
|
||||
{feat.title}
|
||||
</h4>
|
||||
<p className="text-body-md text-on-surface-variant mt-1.5 leading-relaxed">
|
||||
{feat.desc}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<button className="bg-primary hover:bg-primary-container text-white font-black px-10 py-4 rounded-full text-label-md hover:shadow-xl hover:-translate-y-0.5 active:translate-y-0 active:scale-95 transition-all duration-200 cursor-pointer">
|
||||
Register as Merchant Partner
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Right Column: Premium Bento Stats Grid (5 cols) */}
|
||||
<div className="lg:col-span-5 grid grid-cols-2 gap-6">
|
||||
{STATS.map((stat, idx) => (
|
||||
<div
|
||||
key={stat.value}
|
||||
className={`p-6 rounded-[2rem] flex flex-col justify-between aspect-square hover:-translate-y-2 hover:shadow-xl transition-all duration-300 ${stat.style} ${idx % 2 === 1 ? "translate-y-6 md:translate-y-8" : ""}`}
|
||||
>
|
||||
<div className="w-10 h-10 rounded-full bg-white/20 flex items-center justify-center">
|
||||
<MaterialIcon icon={stat.icon} size={22} />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-4xl font-display font-black tracking-tight">
|
||||
{stat.value}
|
||||
</p>
|
||||
<p className="text-label-sm font-semibold mt-1 opacity-90 leading-tight">
|
||||
{stat.label}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* CURVED PROMO BANNER: Inspired by GoMoto Hottest Pizza Banner */}
|
||||
<div className="mt-32 relative overflow-hidden bg-brand-accent rounded-[3.5rem] p-8 md:p-16 flex flex-col md:flex-row justify-between items-center gap-12 border border-brand-accent/20 shadow-2xl">
|
||||
{/* Decorative background vectors */}
|
||||
<div className="absolute right-0 top-0 w-[400px] h-[400px] bg-white/10 rounded-full blur-3xl pointer-events-none" />
|
||||
<div className="absolute left-10 bottom-0 w-[200px] h-[200px] bg-brand-dark/5 rounded-full blur-2xl pointer-events-none" />
|
||||
|
||||
{/* Left copy column */}
|
||||
<div className="md:w-3/5 z-10 text-brand-dark">
|
||||
<span className="text-[10px] font-black uppercase tracking-widest bg-brand-dark/15 px-3.5 py-1.5 rounded-full">
|
||||
Piping Hot & Fresh
|
||||
</span>
|
||||
<h3 className="text-display mt-6 mb-4 leading-[1.1] font-black">
|
||||
Always the Hottest Meals <br />& Freshest Groceries.
|
||||
</h3>
|
||||
<p className="text-body-lg text-brand-dark/80 mb-8 max-w-md font-semibold leading-relaxed">
|
||||
Our advanced insulation packs guarantee your hot food stays steaming, and frozen goods stay completely frozen until handed to you.
|
||||
</p>
|
||||
<a
|
||||
href="#"
|
||||
className="bg-brand-dark hover:bg-brand-dark/90 text-white font-black px-8 py-3.5 rounded-full text-label-md hover:shadow-2xl transition-all hover:-translate-y-0.5 active:translate-y-0 active:scale-95 duration-200 inline-block shadow-md"
|
||||
>
|
||||
Order Meals Now
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* Right visual column */}
|
||||
<div className="md:w-2/5 relative flex justify-center items-center">
|
||||
{/* Soft background shape */}
|
||||
<div className="absolute w-[260px] h-[260px] bg-brand-dark/10 rounded-full pointer-events-none scale-110" />
|
||||
|
||||
<div className="relative w-full max-w-[280px] aspect-square rounded-[2rem] overflow-hidden border-4 border-white shadow-2xl rotate-3 hover:rotate-0 transition-transform duration-500">
|
||||
<Image
|
||||
src="/images/cat-hot-food.png"
|
||||
alt="Hot meals from Nearle local kitchen partners"
|
||||
width={400}
|
||||
height={400}
|
||||
className="w-full h-full object-cover scale-105"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
252
src/components/home/Hero.tsx
Normal file
252
src/components/home/Hero.tsx
Normal file
@@ -0,0 +1,252 @@
|
||||
import Image from "next/image";
|
||||
import { MaterialIcon } from "@/components/ui/MaterialIcon";
|
||||
|
||||
const QUICK_LINKS = [
|
||||
{
|
||||
name: "Hot Meals",
|
||||
icon: "fastfood",
|
||||
label: "Quick & tasty",
|
||||
},
|
||||
{
|
||||
name: "Daily Groceries",
|
||||
icon: "shopping_basket",
|
||||
label: "Fresh & On-Time",
|
||||
},
|
||||
{
|
||||
name: "Health & Care",
|
||||
icon: "medical_services",
|
||||
label: "Essential & Trusted",
|
||||
},
|
||||
{
|
||||
name: "More Services",
|
||||
icon: "grid_view",
|
||||
label: "Explore More",
|
||||
},
|
||||
];
|
||||
|
||||
export function Hero() {
|
||||
return (
|
||||
<div className="hero">
|
||||
|
||||
{/* ─── Base Dark Background Panel (Clipped diagonally) ─── */}
|
||||
<div className="hero-dark-panel select-none pointer-events-none">
|
||||
|
||||
{/* Flat Dotted World Map Layer */}
|
||||
<div className="hero-map-layer select-none mix-blend-screen">
|
||||
<Image
|
||||
src="/images/slider-glob.png"
|
||||
alt="Dotted World Map"
|
||||
fill
|
||||
sizes="(max-width: 768px) 100vw, 75vw"
|
||||
className="object-contain object-left"
|
||||
priority
|
||||
/>
|
||||
|
||||
{/* Animated Route Lines & Glowing Location Nodes */}
|
||||
<svg
|
||||
className="absolute inset-0 w-full h-full opacity-85 pointer-events-none"
|
||||
viewBox="0 0 1000 800"
|
||||
preserveAspectRatio="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<defs>
|
||||
<filter id="heroRouteGlow" x="-50%" y="-50%" width="200%" height="200%">
|
||||
<feGaussianBlur stdDeviation="5" result="blur" />
|
||||
<feMerge>
|
||||
<feMergeNode in="blur" />
|
||||
<feMergeNode in="SourceGraphic" />
|
||||
</feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
{/* Glowing nodes */}
|
||||
<circle cx="150" cy="180" r="8" className="fill-[#bd34fe] opacity-70 animate-pulse" filter="url(#heroRouteGlow)" />
|
||||
<circle cx="150" cy="180" r="2.5" className="fill-white" />
|
||||
|
||||
<circle cx="350" cy="110" r="8" className="fill-[#bd34fe] opacity-70 animate-pulse" filter="url(#heroRouteGlow)" />
|
||||
<circle cx="350" cy="110" r="2.5" className="fill-white" />
|
||||
|
||||
<circle cx="280" cy="300" r="8" className="fill-[#bd34fe] opacity-70 animate-pulse" filter="url(#heroRouteGlow)" />
|
||||
<circle cx="280" cy="300" r="2.5" className="fill-white" />
|
||||
|
||||
<circle cx="480" cy="220" r="8" className="fill-[#bd34fe] opacity-70 animate-pulse" filter="url(#heroRouteGlow)" />
|
||||
<circle cx="480" cy="220" r="2.5" className="fill-white" />
|
||||
|
||||
<circle cx="650" cy="165" r="8" className="fill-[#bd34fe] opacity-70 animate-pulse" filter="url(#heroRouteGlow)" />
|
||||
<circle cx="650" cy="165" r="2.5" className="fill-white" />
|
||||
|
||||
<circle cx="780" cy="250" r="8" className="fill-[#bd34fe] opacity-70 animate-pulse" filter="url(#heroRouteGlow)" />
|
||||
<circle cx="780" cy="250" r="2.5" className="fill-white" />
|
||||
|
||||
<circle cx="580" cy="140" r="8" className="fill-[#bd34fe] opacity-70 animate-pulse" filter="url(#heroRouteGlow)" />
|
||||
<circle cx="580" cy="140" r="2.5" className="fill-white" />
|
||||
|
||||
{/* Arc dashed lines with moving stroke-dash animation */}
|
||||
<path
|
||||
d="M150,180 Q250,120 350,110"
|
||||
fill="none"
|
||||
stroke="#c02cff"
|
||||
strokeWidth="2"
|
||||
strokeDasharray="6,6"
|
||||
className="animate-route opacity-70"
|
||||
filter="url(#heroRouteGlow)"
|
||||
/>
|
||||
<path
|
||||
d="M150,180 Q200,240 280,300"
|
||||
fill="none"
|
||||
stroke="#c02cff"
|
||||
strokeWidth="2"
|
||||
strokeDasharray="6,6"
|
||||
className="animate-route opacity-70"
|
||||
filter="url(#heroRouteGlow)"
|
||||
/>
|
||||
<path
|
||||
d="M350,110 Q420,165 480,220"
|
||||
fill="none"
|
||||
stroke="#c02cff"
|
||||
strokeWidth="2"
|
||||
strokeDasharray="6,6"
|
||||
className="animate-route opacity-70"
|
||||
filter="url(#heroRouteGlow)"
|
||||
/>
|
||||
<path
|
||||
d="M280,300 Q380,250 480,220"
|
||||
fill="none"
|
||||
stroke="#c02cff"
|
||||
strokeWidth="2"
|
||||
strokeDasharray="6,6"
|
||||
className="animate-route opacity-70"
|
||||
filter="url(#heroRouteGlow)"
|
||||
/>
|
||||
<path
|
||||
d="M480,220 Q520,180 580,140 Q630,120 650,165"
|
||||
fill="none"
|
||||
stroke="#c02cff"
|
||||
strokeWidth="2"
|
||||
strokeDasharray="6,6"
|
||||
className="animate-route opacity-70"
|
||||
filter="url(#heroRouteGlow)"
|
||||
/>
|
||||
<path
|
||||
d="M480,220 Q620,250 780,250"
|
||||
fill="none"
|
||||
stroke="#c02cff"
|
||||
strokeWidth="2"
|
||||
strokeDasharray="6,6"
|
||||
className="animate-route opacity-70"
|
||||
filter="url(#heroRouteGlow)"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
{/* Soft purple radial glow behind the bike near the diagonal edge (clipped) */}
|
||||
<div className="absolute right-0 top-1/4 z-0 h-[60%] w-[45%] rounded-full bg-primary/45 blur-[120px] opacity-50 pointer-events-none" />
|
||||
</div>
|
||||
|
||||
{/* ─── Main Content Wrapper ─── */}
|
||||
<div className="hero-stage relative w-full flex flex-col z-10 md:justify-center md:items-start">
|
||||
|
||||
{/* Left Column: Text & Search Content */}
|
||||
<div className="hero-content text-white select-none">
|
||||
<span className="inline-block text-label-sm text-brand-accent font-black tracking-widest uppercase mb-4 bg-brand-accent/10 px-4 py-1.5 rounded-full border border-brand-accent/20">
|
||||
Express Services
|
||||
</span>
|
||||
|
||||
<h1 className="text-5xl lg:text-[82px] font-display font-black leading-[0.98] tracking-tight mb-7">
|
||||
Express
|
||||
<br />
|
||||
<span className="text-brand-accent drop-shadow-md">Neighborhood</span>
|
||||
</h1>
|
||||
|
||||
<p className="text-body-lg md:text-[20px] md:leading-8 text-white/80 mb-11 leading-relaxed max-w-2xl">
|
||||
Get groceries, hot meals, daily essentials, and local professional services delivered from trusted partners within <span className="text-brand-accent font-bold">25-30 minutes</span>.
|
||||
</p>
|
||||
|
||||
{/* Search Input Bar */}
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex items-center bg-white p-2 rounded-full shadow-2xl border border-white/10 focus-within:ring-4 focus-within:ring-brand-accent/30 transition-all duration-300 max-w-[620px]">
|
||||
<MaterialIcon
|
||||
icon="location_on"
|
||||
size={22}
|
||||
className="ml-4 text-brand-accent animate-pulse-subtle"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Enter your neighbourhood or delivery location..."
|
||||
className="w-full border-none focus:ring-0 focus:outline-none text-body-md text-on-surface font-semibold placeholder-on-surface-variant/50 px-3 py-2 bg-transparent"
|
||||
/>
|
||||
<button className="bg-brand-accent hover:bg-brand-accent/90 text-brand-dark font-black px-6 py-3 rounded-full text-label-sm hover:shadow-lg transition-all active:scale-95 duration-200 whitespace-nowrap cursor-pointer">
|
||||
Find Shops
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Popular tags below */}
|
||||
<div className="flex gap-3 items-center flex-wrap px-4 mt-2">
|
||||
<span className="text-label-sm text-white/40 uppercase tracking-widest font-black text-[10px]">
|
||||
Popular:
|
||||
</span>
|
||||
{["Fresh Produce", "African Bakery", "Pet Care"].map((tag) => (
|
||||
<a
|
||||
key={tag}
|
||||
href="#"
|
||||
className="text-label-sm text-brand-accent-light hover:text-brand-accent transition-colors font-bold"
|
||||
>
|
||||
{tag}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right Column: Dominant Purple Scooter Rider (Overlapping) */}
|
||||
<div className="hero-bike select-none pointer-events-none">
|
||||
<div className="relative w-full h-full flex items-end">
|
||||
<Image
|
||||
src="/images/slider-courier-mask-purple-v4.png"
|
||||
alt="Nearle Delivery Courier"
|
||||
fill
|
||||
sizes="(max-width: 768px) 95vw, 48vw"
|
||||
className="object-contain object-bottom drop-shadow-2xl"
|
||||
priority
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* Overlapping Quick Category Links (Anchored at the bottom edge) */}
|
||||
<div className="hero-cards absolute bottom-0 left-0 right-0 transform translate-y-[50%] z-20">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
{QUICK_LINKS.map((item) => (
|
||||
<div
|
||||
key={item.name}
|
||||
className="flex items-center gap-4 bg-white p-5 rounded-2xl border border-outline-variant/15 shadow-xl hover:shadow-2xl premium-card cursor-pointer group"
|
||||
>
|
||||
<div className="flex-shrink-0 w-12 h-12 rounded-full bg-brand-accent/10 flex items-center justify-center group-hover:bg-brand-accent/20 transition-colors">
|
||||
<MaterialIcon
|
||||
icon={item.icon}
|
||||
size={24}
|
||||
className="text-brand-accent"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-grow">
|
||||
<h3 className="text-label-md font-extrabold text-brand-dark group-hover:text-primary transition-colors">
|
||||
{item.name}
|
||||
</h3>
|
||||
<p className="text-[11px] text-on-surface-variant font-medium mt-0.5 leading-tight">
|
||||
{item.label}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-surface-container flex items-center justify-center opacity-0 group-hover:opacity-100 group-hover:translate-x-1 transition-all duration-300">
|
||||
<MaterialIcon
|
||||
icon="arrow_forward"
|
||||
size={16}
|
||||
className="text-primary"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
129
src/components/home/HyperlocalFeatures.tsx
Normal file
129
src/components/home/HyperlocalFeatures.tsx
Normal file
@@ -0,0 +1,129 @@
|
||||
import Image from "next/image";
|
||||
import { MaterialIcon } from "@/components/ui/MaterialIcon";
|
||||
|
||||
const FEATURES = [
|
||||
{
|
||||
title: "Verified Community Partners",
|
||||
icon: "verified_user",
|
||||
desc: "Every merchant on Nearle is manually verified for food hygiene, service quality, and local licensing.",
|
||||
},
|
||||
{
|
||||
title: "Eco-Friendly 2KM Logistics",
|
||||
icon: "electric_moped",
|
||||
desc: "By capping deliveries at 2km, we run a fast, eco-friendly moped fleet that reduces emissions and saves fuel.",
|
||||
},
|
||||
{
|
||||
title: "Exclusive Society Discounting",
|
||||
icon: "local_activity",
|
||||
desc: "We coordinate with housing societies to negotiate collective discount rates and free scheduled delivery runs.",
|
||||
},
|
||||
];
|
||||
|
||||
export function HyperlocalFeatures() {
|
||||
return (
|
||||
<section className="py-20 bg-surface-container-low border-y border-outline-variant/10 relative overflow-hidden">
|
||||
{/* Background soft blur */}
|
||||
<div className="absolute -left-20 top-1/3 w-80 h-80 bg-primary/5 rounded-full blur-3xl pointer-events-none" />
|
||||
|
||||
<div className="max-w-container-max mx-auto px-margin-mobile md:px-margin-desktop">
|
||||
<div className="grid lg:grid-cols-12 gap-12 items-center">
|
||||
|
||||
{/* Left Column: Visual Storytelling (5 cols) */}
|
||||
<div className="lg:col-span-5 relative">
|
||||
<div className="relative aspect-[4/5] w-full max-w-[420px] mx-auto rounded-[3rem] overflow-hidden border-4 border-white shadow-2xl">
|
||||
<Image
|
||||
src="/images/cat-daily-essentials.png"
|
||||
alt="Fresh groceries and goods delivered at home"
|
||||
width={500}
|
||||
height={600}
|
||||
className="w-full h-full object-cover group-hover:scale-102 transition-transform duration-500"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/50 via-transparent to-transparent" />
|
||||
|
||||
{/* Floating Badge */}
|
||||
<div className="absolute bottom-6 left-6 right-6 bg-white/95 backdrop-blur-md p-5 rounded-2xl border border-outline-variant/20 shadow-xl">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 rounded-full bg-brand-accent/20 flex items-center justify-center">
|
||||
<MaterialIcon icon="eco" className="text-brand-accent" size={22} />
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="text-label-md font-black text-brand-dark">100% Eco-Friendly</h4>
|
||||
<p className="text-[11px] text-on-surface-variant font-semibold mt-0.5">Reducing neighbor carbon footprint</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Background Decorative Circle */}
|
||||
<div className="absolute -bottom-8 -right-8 w-32 h-32 bg-brand-accent/10 rounded-full blur-xl pointer-events-none" />
|
||||
</div>
|
||||
|
||||
{/* Right Column: Dark Feature Panel (7 cols) */}
|
||||
<div className="lg:col-span-7">
|
||||
<div className="bg-brand-dark text-white p-8 md:p-16 rounded-[3rem] shadow-2xl relative overflow-hidden border border-white/5">
|
||||
{/* Internal vector decor */}
|
||||
<div className="absolute right-0 top-0 w-64 h-64 bg-brand-accent/5 rounded-full blur-3xl pointer-events-none" />
|
||||
<div className="absolute -left-16 -bottom-16 w-48 h-48 bg-primary/10 rounded-full blur-2xl pointer-events-none" />
|
||||
|
||||
<div className="relative z-10">
|
||||
<span className="text-label-sm text-brand-accent uppercase tracking-widest font-black bg-brand-accent/10 px-3.5 py-1.5 rounded-full border border-brand-accent/20">
|
||||
Care & Quality
|
||||
</span>
|
||||
|
||||
<h3 className="text-display mt-6 mb-8 leading-tight tracking-tight">
|
||||
Relax at Home,<br />
|
||||
<span className="text-brand-accent font-black">We Care.</span>
|
||||
</h3>
|
||||
|
||||
<p className="text-body-lg text-white/70 mb-10 max-w-lg leading-relaxed">
|
||||
Nearle connects you to local, trusted neighborhood shops, bringing you the best essentials while taking care of the logistics and safety standards.
|
||||
</p>
|
||||
|
||||
{/* Features List */}
|
||||
<div className="space-y-8">
|
||||
{FEATURES.map((item) => (
|
||||
<div key={item.title} className="flex gap-5 group">
|
||||
<div className="flex-shrink-0 w-12 h-12 rounded-full bg-brand-accent/15 border border-brand-accent/30 flex items-center justify-center group-hover:bg-brand-accent group-hover:text-brand-dark transition-colors duration-300">
|
||||
<MaterialIcon
|
||||
icon={item.icon}
|
||||
className="text-brand-accent group-hover:text-brand-dark transition-colors"
|
||||
size={22}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="text-headline-md font-black text-white group-hover:text-brand-accent transition-colors">
|
||||
{item.title}
|
||||
</h4>
|
||||
<p className="text-body-md text-white/60 mt-1 leading-relaxed">
|
||||
{item.desc}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Onboarding Call to Action */}
|
||||
<div className="mt-12 flex flex-wrap gap-4 items-center">
|
||||
<a
|
||||
href="#download"
|
||||
className="bg-brand-accent hover:bg-brand-accent/90 text-brand-dark font-black px-8 py-3.5 rounded-full text-label-md hover:shadow-lg hover:-translate-y-0.5 active:translate-y-0 active:scale-95 transition-all duration-200"
|
||||
>
|
||||
Get Nearle App
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
className="text-white hover:text-brand-accent font-bold text-label-md flex items-center gap-1 group py-2"
|
||||
>
|
||||
Partner Code of Ethics
|
||||
<MaterialIcon icon="arrow_forward" size={16} className="transition-transform group-hover:translate-x-1" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
148
src/components/home/ServiceCategories.tsx
Normal file
148
src/components/home/ServiceCategories.tsx
Normal file
@@ -0,0 +1,148 @@
|
||||
import Image from "next/image";
|
||||
import { MaterialIcon } from "@/components/ui/MaterialIcon";
|
||||
|
||||
const CATEGORIES = [
|
||||
{
|
||||
name: "Hot Food",
|
||||
image: "/images/cat-hot-food.png",
|
||||
tag: "Popular",
|
||||
tagStyle: "bg-brand-accent text-brand-dark",
|
||||
desc: "Fresh meals, bakes & street favorites",
|
||||
stats: "★ 4.8 (250+ kitchens)",
|
||||
cta: "Order Now",
|
||||
},
|
||||
{
|
||||
name: "Daily Essentials",
|
||||
image: "/images/cat-daily-essentials.png",
|
||||
tag: "15 Mins",
|
||||
tagStyle: "bg-secondary text-white",
|
||||
desc: "Groceries, fresh fruits & veggies",
|
||||
stats: "★ 4.9 (180+ stores)",
|
||||
cta: "Shop Fresh",
|
||||
},
|
||||
{
|
||||
name: "Health & Wellness",
|
||||
image: "/images/cat-health-wellness.png",
|
||||
tag: "24/7 Delivery",
|
||||
tagStyle: "bg-primary text-white",
|
||||
desc: "Medicines & daily health supplies",
|
||||
stats: "★ 4.7 (95+ pharmacies)",
|
||||
cta: "Order Meds",
|
||||
},
|
||||
{
|
||||
name: "Home Services",
|
||||
image: "/images/cat-home-services.png",
|
||||
tag: "Verified Professionals",
|
||||
tagStyle: "bg-blue-600 text-white",
|
||||
desc: "Electricians, cleaning & repairs",
|
||||
stats: "★ 4.9 (340+ experts)",
|
||||
cta: "Book Service",
|
||||
},
|
||||
{
|
||||
name: "Pet Essentials",
|
||||
image: "/images/cat-pet-essentials.png",
|
||||
tag: "Express",
|
||||
tagStyle: "bg-orange-500 text-white",
|
||||
desc: "Pet food, toys & grooming care",
|
||||
stats: "★ 4.8 (60+ partners)",
|
||||
cta: "Shop Pet",
|
||||
},
|
||||
{
|
||||
name: "More Services",
|
||||
image: null,
|
||||
tag: "Hyperlocal",
|
||||
tagStyle: "bg-surface-variant text-on-surface",
|
||||
desc: "Laundry, car wash, tailoring & more",
|
||||
stats: "★ 5.0 (500+ services)",
|
||||
cta: "Explore All",
|
||||
},
|
||||
];
|
||||
|
||||
export function ServiceCategories() {
|
||||
return (
|
||||
<section className="bg-background pt-28 pb-16 px-margin-mobile md:px-margin-desktop">
|
||||
<div className="max-w-container-max mx-auto">
|
||||
{/* Header Section */}
|
||||
<div className="flex flex-col md:flex-row justify-between items-start md:items-end mb-12 gap-4">
|
||||
<div>
|
||||
<span className="text-label-sm text-primary uppercase tracking-widest font-black bg-primary/5 px-3 py-1 rounded-full">
|
||||
Neighborhood Offerings
|
||||
</span>
|
||||
<h2 className="text-display text-brand-dark mt-3 leading-tight">
|
||||
Popular Services <span className="text-primary font-normal">Near You</span>
|
||||
</h2>
|
||||
<p className="text-body-lg text-on-surface-variant mt-2 max-w-xl">
|
||||
From fresh groceries to emergency services, everything in your 2km radius delivered instantly.
|
||||
</p>
|
||||
</div>
|
||||
<a
|
||||
href="#"
|
||||
className="text-primary text-label-md font-black flex items-center gap-1 hover:gap-2 transition-all group"
|
||||
>
|
||||
View All Categories
|
||||
<MaterialIcon icon="arrow_forward" size={18} className="transition-transform group-hover:translate-x-1" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* Categories Premium Grid */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
{CATEGORIES.map((cat) => (
|
||||
<div
|
||||
key={cat.name}
|
||||
className="bg-white rounded-[2rem] border border-outline-variant/10 shadow-lg overflow-hidden premium-card flex flex-col group h-full"
|
||||
>
|
||||
{/* Image Container */}
|
||||
<div className="relative aspect-[4/3] w-full overflow-hidden bg-surface-container/30">
|
||||
{cat.image ? (
|
||||
<Image
|
||||
src={cat.image}
|
||||
alt={cat.name}
|
||||
width={400}
|
||||
height={300}
|
||||
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-500"
|
||||
/>
|
||||
) : (
|
||||
<div className="w-full h-full bg-gradient-to-br from-primary/10 to-brand-accent/15 flex flex-col items-center justify-center text-primary">
|
||||
<div className="w-16 h-16 rounded-full bg-white/80 shadow-md flex items-center justify-center animate-pulse-subtle">
|
||||
<MaterialIcon icon="grid_view" size={32} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Overlaid Badge */}
|
||||
<div className={`absolute top-4 left-4 text-[10px] font-black uppercase tracking-wider px-3.5 py-1.5 rounded-full shadow-md z-10 ${cat.tagStyle}`}>
|
||||
{cat.tag}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Card Body */}
|
||||
<div className="p-6 flex flex-col flex-grow">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<h3 className="text-headline-md font-black text-brand-dark group-hover:text-primary transition-colors">
|
||||
{cat.name}
|
||||
</h3>
|
||||
<span className="text-[11px] font-bold text-on-surface-variant bg-surface-container px-2.5 py-1 rounded-full">
|
||||
{cat.stats}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-body-md text-on-surface-variant mb-6 flex-grow leading-relaxed">
|
||||
{cat.desc}
|
||||
</p>
|
||||
|
||||
{/* Interactive Action Button */}
|
||||
<div className="flex items-center justify-between pt-4 border-t border-dashed border-outline-variant/25">
|
||||
<span className="text-label-sm text-primary font-black uppercase tracking-wider group-hover:underline">
|
||||
{cat.cta}
|
||||
</span>
|
||||
<div className="w-10 h-10 rounded-full bg-brand-dark text-white flex items-center justify-center group-hover:bg-brand-accent group-hover:text-brand-dark transition-colors duration-300 shadow-md">
|
||||
<MaterialIcon icon="chevron_right" size={20} className="font-bold" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
146
src/components/layout/Footer.tsx
Normal file
146
src/components/layout/Footer.tsx
Normal file
@@ -0,0 +1,146 @@
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import { MaterialIcon } from "@/components/ui/MaterialIcon";
|
||||
|
||||
const COMPANY = [
|
||||
{ label: "About Us", href: "/about" },
|
||||
{ label: "Careers", href: "#" },
|
||||
{ label: "Press & News", href: "#" },
|
||||
{ label: "Help Center", href: "#" },
|
||||
];
|
||||
|
||||
const PARTNERSHIPS = [
|
||||
{ label: "Merchant Partner", href: "/businesses" },
|
||||
{ label: "Delivery Partner", href: "#" },
|
||||
{ label: "Corporate Gifting", href: "#" },
|
||||
{ label: "Local Real Estate", href: "#" },
|
||||
];
|
||||
|
||||
const LEGAL = [
|
||||
{ label: "Privacy Policy", href: "#" },
|
||||
{ label: "Terms of Service", href: "#" },
|
||||
{ label: "Cookie Policy", href: "#" },
|
||||
{ label: "Sitemap", href: "#" },
|
||||
];
|
||||
|
||||
export function Footer() {
|
||||
return (
|
||||
<footer className="relative bg-brand-dark text-white border-t border-white/5 pt-28 pb-12 w-full mt-24">
|
||||
{/* Overlapping Contact Helpdesk Card */}
|
||||
<div className="absolute top-0 left-0 right-0 transform -translate-y-1/2 z-20 max-w-container-max mx-auto px-margin-mobile md:px-margin-desktop">
|
||||
<div className="bg-brand-accent p-6 md:p-8 rounded-[2.5rem] flex flex-col md:flex-row justify-between items-center gap-6 shadow-2xl border border-brand-accent/20">
|
||||
<div className="flex items-center gap-4 text-brand-dark">
|
||||
<div className="w-12 h-12 rounded-full bg-brand-dark text-brand-accent flex items-center justify-center shadow-lg">
|
||||
<MaterialIcon icon="headset_mic" size={24} />
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="text-headline-md font-black">24/7 Neighborhood Helpdesk</h4>
|
||||
<p className="text-[11px] font-bold text-brand-dark/80 mt-0.5">
|
||||
Need immediate assistance with an order or local service?
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<a
|
||||
href="tel:+918049123456"
|
||||
className="flex items-center gap-3 bg-brand-dark hover:bg-brand-dark/90 text-brand-accent font-black px-8 py-3.5 rounded-full text-label-md shadow-2xl active:scale-95 duration-200 transition-all"
|
||||
>
|
||||
<MaterialIcon icon="phone" size={20} className="animate-pulse-subtle" />
|
||||
<span>+91 80 4912 3456</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="max-w-container-max mx-auto px-margin-mobile md:px-margin-desktop">
|
||||
{/* Footer Link Grid */}
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-gutter mb-16 pt-4">
|
||||
{/* Brand Column */}
|
||||
<div className="col-span-2 md:col-span-1">
|
||||
<Link
|
||||
href="/"
|
||||
className="hover:scale-[1.02] transition-transform active:scale-95 duration-200 mb-6 inline-block"
|
||||
>
|
||||
<Image
|
||||
src="/logo-v2.png"
|
||||
alt="Nearle"
|
||||
width={140}
|
||||
height={23}
|
||||
style={{ height: "auto" }}
|
||||
className="h-7 w-auto object-contain"
|
||||
/>
|
||||
</Link>
|
||||
<p className="text-body-sm text-white/60 max-w-xs mb-8 leading-relaxed">
|
||||
India's leading hyperlocal neighborhood network, empowering communities and verified local businesses within 2km.
|
||||
</p>
|
||||
{/* Social Links */}
|
||||
<div className="flex gap-4">
|
||||
<a
|
||||
href="#"
|
||||
className="w-10 h-10 rounded-full bg-white/5 border border-white/10 flex items-center justify-center hover:bg-brand-accent hover:text-brand-dark hover:scale-105 transition-all"
|
||||
aria-label="Share"
|
||||
>
|
||||
<MaterialIcon icon="share" size={18} />
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
className="w-10 h-10 rounded-full bg-white/5 border border-white/10 flex items-center justify-center hover:bg-brand-accent hover:text-brand-dark hover:scale-105 transition-all"
|
||||
aria-label="Website"
|
||||
>
|
||||
<MaterialIcon icon="public" size={18} />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Company Links */}
|
||||
<FooterCol title="Company" links={COMPANY} />
|
||||
|
||||
{/* Partnerships Links */}
|
||||
<FooterCol title="Partnerships" links={PARTNERSHIPS} />
|
||||
|
||||
{/* Legal Links */}
|
||||
<FooterCol title="Legal" links={LEGAL} />
|
||||
</div>
|
||||
|
||||
{/* Bottom Bar */}
|
||||
<div className="border-t border-white/10 pt-8 flex flex-col md:flex-row justify-between items-center gap-4">
|
||||
<p className="text-body-sm text-white/40">
|
||||
© {new Date().getFullYear()} Nearle. All rights reserved.
|
||||
</p>
|
||||
<div className="flex items-center gap-2 text-white/40 text-body-sm">
|
||||
<span>Designed for neighborhoods in</span>
|
||||
<span className="flex items-center gap-1 font-bold text-white/80">
|
||||
India 🇮🇳
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
|
||||
function FooterCol({
|
||||
title,
|
||||
links,
|
||||
}: {
|
||||
title: string;
|
||||
links: { label: string; href: string }[];
|
||||
}) {
|
||||
return (
|
||||
<div>
|
||||
<h5 className="text-label-sm font-black text-brand-accent uppercase tracking-widest mb-6">
|
||||
{title}
|
||||
</h5>
|
||||
<ul className="space-y-3">
|
||||
{links.map((l) => (
|
||||
<li key={l.label}>
|
||||
<Link
|
||||
href={l.href}
|
||||
className="text-body-sm text-white/60 hover:text-brand-accent hover:translate-x-1.5 transition-all duration-300 inline-block"
|
||||
>
|
||||
{l.label}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
93
src/components/layout/Navbar.tsx
Normal file
93
src/components/layout/Navbar.tsx
Normal file
@@ -0,0 +1,93 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import { useState } from "react";
|
||||
import { MaterialIcon } from "@/components/ui/MaterialIcon";
|
||||
|
||||
const NAV_LINKS = [
|
||||
{ label: "Home", href: "/" },
|
||||
{ label: "Nearle for Business", href: "/businesses" },
|
||||
{ label: "Nearle for People", href: "/people" },
|
||||
{ label: "About", href: "/about" },
|
||||
{ label: "Contact", href: "/contact" },
|
||||
];
|
||||
|
||||
export function Navbar() {
|
||||
const [mobileOpen, setMobileOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<nav className="sticky top-0 z-50 w-full bg-white/95 backdrop-blur-md border-b border-outline-variant/20 transition-all duration-300">
|
||||
<div className="grid w-full grid-cols-[auto_auto] md:grid-cols-[auto_1fr_auto] items-center gap-4 md:gap-8 px-margin-mobile md:px-16 xl:px-24 py-3">
|
||||
{/* Left: Brand */}
|
||||
<div className="flex items-center">
|
||||
<Link
|
||||
href="/"
|
||||
className="flex items-center hover:scale-[1.02] transition-transform active:scale-95 duration-200"
|
||||
>
|
||||
<Image
|
||||
src="/logo-purple-v2.png"
|
||||
alt="Nearle"
|
||||
width={140}
|
||||
height={23}
|
||||
style={{ height: "auto" }}
|
||||
className="h-7 w-auto object-contain"
|
||||
priority
|
||||
/>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Center: Navigation */}
|
||||
<div className="hidden md:flex items-center justify-center gap-8 xl:gap-10">
|
||||
{NAV_LINKS.map((link) => (
|
||||
<Link
|
||||
key={link.label}
|
||||
href={link.href}
|
||||
className="relative py-1 text-[15px] font-bold leading-5 text-on-surface-variant hover:text-primary transition-all duration-200 group whitespace-nowrap"
|
||||
>
|
||||
{link.label}
|
||||
<span className="absolute bottom-0 left-0 w-0 h-0.5 bg-primary transition-all duration-300 group-hover:w-full" />
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Right: Actions */}
|
||||
<div className="flex items-center justify-end gap-3">
|
||||
<Link
|
||||
href="/#download"
|
||||
className="hidden md:inline-flex bg-primary hover:bg-primary-container text-on-primary font-bold px-7 py-3 rounded-full text-label-md hover:shadow-lg transition-all duration-300 hover:-translate-y-0.5 active:translate-y-0 active:scale-95 whitespace-nowrap"
|
||||
>
|
||||
Get App
|
||||
</Link>
|
||||
|
||||
{/* Mobile menu toggle */}
|
||||
<button
|
||||
className="md:hidden flex items-center justify-center w-10 h-10 rounded-full hover:bg-surface-container transition-all active:scale-90 cursor-pointer"
|
||||
onClick={() => setMobileOpen(!mobileOpen)}
|
||||
aria-label="Toggle menu"
|
||||
>
|
||||
<MaterialIcon icon={mobileOpen ? "close" : "menu"} size={22} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Mobile Drawer */}
|
||||
{mobileOpen && (
|
||||
<div className="md:hidden bg-surface-container-lowest border-t border-outline-variant">
|
||||
<div className="max-w-container-max mx-auto px-margin-mobile py-stack-md flex flex-col gap-2">
|
||||
{NAV_LINKS.map((link) => (
|
||||
<Link
|
||||
key={link.label}
|
||||
href={link.href}
|
||||
className="px-3 py-2.5 text-body-md text-on-surface-variant hover:text-primary hover:bg-surface-container-low rounded-lg transition-colors"
|
||||
onClick={() => setMobileOpen(false)}
|
||||
>
|
||||
{link.label}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
25
src/components/ui/MaterialIcon.tsx
Normal file
25
src/components/ui/MaterialIcon.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
type MaterialIconProps = {
|
||||
icon: string;
|
||||
size?: number;
|
||||
fill?: boolean;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export function MaterialIcon({
|
||||
icon,
|
||||
size = 24,
|
||||
fill = false,
|
||||
className = "",
|
||||
}: MaterialIconProps) {
|
||||
return (
|
||||
<span
|
||||
className={`material-symbols-outlined ${className}`}
|
||||
style={{
|
||||
fontSize: size,
|
||||
fontVariationSettings: `'FILL' ${fill ? 1 : 0}, 'wght' 400, 'GRAD' 0, 'opsz' ${size}`,
|
||||
}}
|
||||
>
|
||||
{icon}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user