feat: default language Swedish, modern mobile navigation menu, mobile optimizations & translations, shorten mobile hero banner to 4s
- Set 'sv' as default in LanguageProvider + layout (users can switch to 'en') - Completely revamped mobile drawer menu: slide animation (framer-motion), icons, active states with high-contrast text, large touch targets, better tap feedback - Horizontal snap-scrolling category filters on mobile (homepage + /menu) for thumb-friendly UX - Added active:scale / touch-manipulation + press states across cards, buttons, filters for better mobile tap visibility/feedback - Updated translations for menu page, locations, footer, experience (Swedish-first) - Made locations + footer language-aware - Trimmed banner_mobile.mp4 (raw + re-optimized) from 6s to 4s for faster load on mobile - Reordered languages so Svenska appears first in switcher - .gitignore already protects developer_instructions.txt (previous commit)
This commit is contained in:
+15
-11
@@ -15,8 +15,12 @@
|
||||
*/
|
||||
|
||||
import Link from "next/link";
|
||||
import { useLanguage } from "@/lib/language-context";
|
||||
import { getTranslation } from "@/lib/translations";
|
||||
|
||||
export default function Footer() {
|
||||
const { language } = useLanguage();
|
||||
const t = getTranslation(language);
|
||||
return (
|
||||
<footer className="bg-[#F5F1E9] border-t border-[#EDE6D9] pt-14 pb-10 text-[#6B665F]">
|
||||
<div className="max-w-7xl mx-auto px-6">
|
||||
@@ -34,13 +38,13 @@ export default function Footer() {
|
||||
<span className="text-[#2C2A26] font-medium tracking-[-0.3px]">Shahi Kitchen</span>
|
||||
</div>
|
||||
<p className="text-sm leading-relaxed">
|
||||
Authentic Indian & Pakistani cuisine in Gothenburg since 2016.
|
||||
{t.footer.tagline}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Contact - Both Locations */}
|
||||
<div>
|
||||
<div className="text-[#2C2A26] text-sm tracking-[1.5px] mb-4">OUR LOCATIONS</div>
|
||||
<div className="text-[#2C2A26] text-sm tracking-[1.5px] mb-4">{t.footer.locations}</div>
|
||||
<div className="space-y-4 text-sm">
|
||||
<div>
|
||||
<div className="font-medium text-[#2C2A26]">Shahi Kitchen (Askim / Sisjön)</div>
|
||||
@@ -63,7 +67,7 @@ export default function Footer() {
|
||||
|
||||
{/* Hours */}
|
||||
<div>
|
||||
<div className="text-[#2C2A26] text-sm tracking-[1.5px] mb-4">OPENING HOURS</div>
|
||||
<div className="text-[#2C2A26] text-sm tracking-[1.5px] mb-4">{language === 'sv' ? 'ÖPPETTIDER' : 'OPENING HOURS'}</div>
|
||||
<div className="text-sm space-y-1">
|
||||
<div><span className="font-medium">Askim:</span> Mon–Sun 11:00–21:00</div>
|
||||
<div><span className="font-medium">Backaplan:</span> Mon–Sun 11:00–21:00</div>
|
||||
@@ -72,15 +76,15 @@ export default function Footer() {
|
||||
|
||||
{/* Quick Links + Social */}
|
||||
<div>
|
||||
<div className="text-[#2C2A26] text-sm tracking-[1.5px] mb-4">EXPLORE</div>
|
||||
<div className="text-[#2C2A26] text-sm tracking-[1.5px] mb-4">{t.footer.explore}</div>
|
||||
<div className="flex flex-col gap-1.5 text-sm mb-8">
|
||||
<Link href="/" className="hover:text-[#B38B4D] transition-colors">Home</Link>
|
||||
<Link href="/menu" className="hover:text-[#B38B4D] transition-colors">Menu</Link>
|
||||
<Link href="/#experience" className="hover:text-[#B38B4D] transition-colors">Our Experience</Link>
|
||||
<Link href="/#contact" className="hover:text-[#B38B4D] transition-colors">Contact & Reserve</Link>
|
||||
<Link href="/" className="hover:text-[#B38B4D] transition-colors">{t.nav.home}</Link>
|
||||
<Link href="/menu" className="hover:text-[#B38B4D] transition-colors">{t.nav.menu}</Link>
|
||||
<Link href="/#experience" className="hover:text-[#B38B4D] transition-colors">{language === 'sv' ? 'Vår Upplevelse' : 'Our Experience'}</Link>
|
||||
<Link href="/#contact" className="hover:text-[#B38B4D] transition-colors">{language === 'sv' ? 'Kontakt & Boka' : 'Contact & Reserve'}</Link>
|
||||
</div>
|
||||
|
||||
<div className="text-[#2C2A26] text-sm tracking-[1.5px] mb-3">FOLLOW US</div>
|
||||
<div className="text-[#2C2A26] text-sm tracking-[1.5px] mb-3">{t.footer.follow}</div>
|
||||
<div className="flex gap-5 text-sm">
|
||||
<a
|
||||
href="https://www.instagram.com/Shahikitchen/"
|
||||
@@ -103,8 +107,8 @@ export default function Footer() {
|
||||
</div>
|
||||
|
||||
<div className="mt-14 pt-8 border-t border-[#EDE6D9] text-xs tracking-widest flex flex-col md:flex-row md:items-center justify-between gap-y-2 text-[#8A8478]">
|
||||
<div>© {new Date().getFullYear()} SHAHI KITCHEN • GOTHENBURG. ALL RIGHTS RESERVED.</div>
|
||||
<div>Made with tradition and heart.</div>
|
||||
<div>© {new Date().getFullYear()} SHAHI KITCHEN • GÖTEBORG. ALL RIGHTS RESERVED.</div>
|
||||
<div>{language === 'sv' ? 'Tillagat med tradition och hjärta.' : 'Made with tradition and heart.'}</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
+110
-59
@@ -3,11 +3,11 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import Link from "next/link";
|
||||
import { useCart } from "./CartContext";
|
||||
import { ShoppingBag, ArrowRight } from "lucide-react";
|
||||
import { ShoppingBag, ArrowRight, Home, UtensilsCrossed, MapPin, Star, Phone, X } from "lucide-react";
|
||||
import LanguageSwitcher from "./LanguageSwitcher";
|
||||
import { useLanguage } from "@/lib/language-context";
|
||||
import { getTranslation } from "@/lib/translations";
|
||||
import { motion } from "framer-motion";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import { usePathname } from "next/navigation";
|
||||
|
||||
/**
|
||||
@@ -147,19 +147,17 @@ export default function Navbar({ variant = "default" }: NavbarProps) {
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Mobile Hamburger */}
|
||||
<div className="md:hidden flex items-center gap-3">
|
||||
{/* MOBILE CART ICON (always visible even when hamburger is closed) */}
|
||||
{/* Mobile Hamburger + Cart (compact, high touch target) */}
|
||||
<div className="md:hidden flex items-center gap-2">
|
||||
{/* MOBILE CART ICON (always visible) */}
|
||||
<button
|
||||
onClick={openCart}
|
||||
className="relative flex items-center justify-center w-9 h-9 rounded-full hover:bg-[#F5F1E9] transition-colors"
|
||||
className="relative flex items-center justify-center w-10 h-10 rounded-full hover:bg-[#F5F1E9] active:bg-[#EDE6D9] transition-colors"
|
||||
aria-label="Open cart"
|
||||
>
|
||||
<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="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z" />
|
||||
</svg>
|
||||
<ShoppingBag className="h-5 w-5 text-[#101724]" />
|
||||
{totalItems > 0 && (
|
||||
<span className="absolute -top-1 -right-1 bg-[#B38B4D] text-white text-[10px] font-medium min-w-[16px] h-[16px] rounded-full flex items-center justify-center px-1">
|
||||
<span className="absolute -top-1 -right-1 bg-[#B38B4D] text-white text-[10px] font-bold min-w-[18px] h-[18px] rounded-full flex items-center justify-center px-1 tabular-nums">
|
||||
{totalItems}
|
||||
</span>
|
||||
)}
|
||||
@@ -167,69 +165,122 @@ export default function Navbar({ variant = "default" }: NavbarProps) {
|
||||
|
||||
<button
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
className="text-[#B38B4D] p-2 -mr-2"
|
||||
className="text-[#B38B4D] p-2 -mr-1 active:text-[#8C6B3A] transition-colors"
|
||||
aria-label="Toggle menu"
|
||||
aria-expanded={isOpen}
|
||||
>
|
||||
<div className="space-y-1.5">
|
||||
<span className={`block h-px w-6 bg-current transition-all ${isOpen ? "rotate-45 translate-y-1.5" : ""}`} />
|
||||
<span className={`block h-px w-6 bg-current transition-all ${isOpen ? "opacity-0" : ""}`} />
|
||||
<span className={`block h-px w-6 bg-current transition-all ${isOpen ? "-rotate-45 -translate-y-1.5" : ""}`} />
|
||||
<span className={`block h-px w-6 bg-current transition-all duration-200 ${isOpen ? "rotate-45 translate-y-1.5" : ""}`} />
|
||||
<span className={`block h-px w-6 bg-current transition-all duration-200 ${isOpen ? "opacity-0" : ""}`} />
|
||||
<span className={`block h-px w-6 bg-current transition-all duration-200 ${isOpen ? "-rotate-45 -translate-y-1.5" : ""}`} />
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Mobile Menu - Stunning Elegant Drawer */}
|
||||
{isOpen && (
|
||||
<div className="md:hidden fixed inset-0 z-[60] bg-[#101724]/60 backdrop-blur-md">
|
||||
<div className="ml-auto h-full w-[82%] max-w-[320px] bg-[#fbf7ef] p-8 shadow-2xl border-l border-[#c99a2e]/10">
|
||||
<div className="flex items-center justify-between mb-10">
|
||||
<div className="flex items-center gap-3">
|
||||
<img
|
||||
src="/images/logo/logo1.png"
|
||||
alt="Shahi Kitchen"
|
||||
className="h-12 w-12 rounded-xl object-contain"
|
||||
/>
|
||||
<span className="font-serif text-xl text-[#101724]">Shahi Kitchen</span>
|
||||
</div>
|
||||
<button onClick={closeMenu} className="grid h-10 w-10 place-items-center rounded-full bg-[#f3f5f7] text-[#101724]">
|
||||
<span className="text-2xl leading-none">×</span>
|
||||
</button>
|
||||
</div>
|
||||
{/* Modern Mobile Menu Drawer (slide-in, animated, high-contrast, touch-friendly) */}
|
||||
<AnimatePresence>
|
||||
{isOpen && (
|
||||
<div className="md:hidden fixed inset-0 z-[65]">
|
||||
{/* Backdrop */}
|
||||
<motion.div
|
||||
className="absolute inset-0 bg-[#101724]/70 backdrop-blur-md"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.15 }}
|
||||
onClick={closeMenu}
|
||||
/>
|
||||
|
||||
<div className="flex flex-col gap-5 text-xl font-medium text-[#101724]">
|
||||
{navLinks.map((link) => (
|
||||
<Link
|
||||
key={link.href}
|
||||
href={link.href}
|
||||
onClick={closeMenu}
|
||||
className="py-1 border-b border-[#e5e1d7] pb-4 hover:text-[#0f5a4a] transition-colors"
|
||||
{/* Sliding Panel - modern, full-bleed on small phones, elegant on larger */}
|
||||
<motion.div
|
||||
className="absolute right-0 top-0 bottom-0 w-[82%] max-w-[340px] bg-[#fbf7ef] shadow-2xl border-l border-[#c99a2e]/10 flex flex-col overflow-y-auto"
|
||||
initial={{ x: '100%' }}
|
||||
animate={{ x: 0 }}
|
||||
exit={{ x: '100%' }}
|
||||
transition={{ type: 'spring', stiffness: 320, damping: 32 }}
|
||||
>
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between p-6 border-b border-[#EDE6D9]">
|
||||
<div className="flex items-center gap-3">
|
||||
<img
|
||||
src="/images/logo/logo1.png"
|
||||
alt="Shahi Kitchen"
|
||||
className="h-10 w-10 rounded-xl object-contain"
|
||||
/>
|
||||
<div>
|
||||
<div className="font-serif text-[19px] leading-none text-[#101724]">Shahi Kitchen</div>
|
||||
<div className="text-[10px] uppercase tracking-[1.5px] text-[#8a6a25] -mt-0.5">Gothenburg</div>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={closeMenu}
|
||||
className="w-10 h-10 flex items-center justify-center rounded-full bg-white/70 active:bg-[#EDE6D9] text-[#101724] transition-colors"
|
||||
aria-label="Close menu"
|
||||
>
|
||||
{link.label}
|
||||
<X className="h-5 w-5" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Primary Nav Links - modern list with icons + active state for visibility */}
|
||||
<div className="px-3 py-4">
|
||||
{navLinks.map((link) => {
|
||||
const active = isActive(link.href);
|
||||
const Icon =
|
||||
link.href === '/' ? Home :
|
||||
link.href === '/menu' ? UtensilsCrossed :
|
||||
link.href === '/locations' ? MapPin :
|
||||
link.href.includes('experience') ? Star : Phone;
|
||||
|
||||
return (
|
||||
<Link
|
||||
key={link.href}
|
||||
href={link.href}
|
||||
onClick={closeMenu}
|
||||
className={`flex items-center gap-4 px-4 py-3.5 mx-1 my-0.5 rounded-2xl text-[17px] font-medium transition-all active:scale-[0.985] ${
|
||||
active
|
||||
? 'bg-[#101724] text-white shadow-sm'
|
||||
: 'text-[#101724] hover:bg-white active:bg-[#EDE6D9]'
|
||||
}`}
|
||||
>
|
||||
<Icon className={`h-5 w-5 flex-shrink-0 ${active ? 'text-[#c99a2e]' : 'text-[#B38B4D]'}`} />
|
||||
<span>{link.label}</span>
|
||||
{active && (
|
||||
<span className="ml-auto text-xs tracking-widest opacity-70">CURRENT</span>
|
||||
)}
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Secondary actions + Language */}
|
||||
<div className="mt-auto px-5 pb-8 pt-4 border-t border-[#EDE6D9] bg-white/40 space-y-3">
|
||||
<div className="px-1">
|
||||
<div className="text-[10px] uppercase tracking-[2px] text-[#8a6a25] mb-1.5 px-1">LANGUAGE</div>
|
||||
<LanguageSwitcher />
|
||||
</div>
|
||||
|
||||
<Link
|
||||
href="/#contact"
|
||||
onClick={closeMenu}
|
||||
className="block w-full rounded-2xl bg-gradient-to-r from-[#c99a2e] via-[#d4a73d] to-[#c99a2e] py-4 text-center text-[15px] font-bold text-[#241806] shadow active:scale-[0.985] transition-transform"
|
||||
>
|
||||
{t.reserve}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="mt-10 space-y-3">
|
||||
<LanguageSwitcher />
|
||||
<button
|
||||
onClick={() => { openCart(); closeMenu(); }}
|
||||
className="block w-full rounded-2xl border-2 border-[#c99a2e]/40 bg-white py-4 text-[15px] font-semibold text-[#101724] active:bg-[#F5F1E9] active:border-[#c99a2e] transition-all"
|
||||
>
|
||||
{t.cart} {totalItems > 0 && `(${totalItems})`}
|
||||
</button>
|
||||
|
||||
<Link
|
||||
href="/#contact"
|
||||
onClick={closeMenu}
|
||||
className="block w-full rounded-full bg-gradient-to-r from-[#c99a2e] to-[#d4a73d] py-4 text-center text-base font-bold text-[#241806] shadow-lg"
|
||||
>
|
||||
{t.reserve}
|
||||
</Link>
|
||||
<button
|
||||
onClick={() => { openCart(); closeMenu(); }}
|
||||
className="block w-full rounded-full border border-[#c99a2e]/40 bg-white py-4 text-base font-semibold text-[#101724]"
|
||||
>
|
||||
{t.cart} {totalItems > 0 && `(${totalItems})`}
|
||||
</button>
|
||||
</div>
|
||||
<p className="text-center text-[11px] text-[#8A8478] pt-1">Tap to open WhatsApp for orders & bookings</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user