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:
Zeeshan Khan
2026-06-02 13:44:19 +02:00
parent 10d7555d31
commit 0b6cc1acae
11 changed files with 221 additions and 101 deletions
+20 -15
View File
@@ -11,6 +11,8 @@ import { ScrollTrigger } from "gsap/ScrollTrigger";
import Navbar from "@/components/Navbar";
import Footer from "@/components/Footer";
import { useCart } from "@/components/CartContext";
import { useLanguage } from "@/lib/language-context";
import { getTranslation } from "@/lib/translations";
gsap.registerPlugin(ScrollTrigger);
@@ -20,6 +22,8 @@ export default function MenuPage() {
const [showVegetarianOnly, setShowVegetarianOnly] = useState(false);
const { addToCart } = useCart();
const { language } = useLanguage();
const t = getTranslation(language);
// Sidebar categories
const sidebarCategories = [
@@ -71,9 +75,9 @@ export default function MenuPage() {
<div className="max-w-7xl mx-auto px-6 pt-14 pb-10">
<div className="max-w-3xl">
<div className="text-[#B38B4D] text-xs tracking-[3.5px] mb-4 font-medium">AUTHENTIC GENEROUS ROYAL</div>
<h1 className="text-6xl md:text-7xl tracking-[-2.8px] leading-none mb-5 text-[#101724]">Our Menu</h1>
<h1 className="text-6xl md:text-7xl tracking-[-2.8px] leading-none mb-5 text-[#101724]">{t.menu.title}</h1>
<p className="text-2xl text-[#4b5563] max-w-2xl">
Traditional recipes. Generous portions. Made with heart.
{t.menu.subtitle}
</p>
</div>
</div>
@@ -90,7 +94,8 @@ export default function MenuPage() {
<h3 className="font-serif text-3xl tracking-tight">Signature Categories</h3>
</div>
<div className="space-y-1 pr-4">
{/* Modern mobile-first category menu: horizontal scroller on phones/tablets, vertical sidebar on desktop */}
<div className="flex lg:flex-col gap-2 overflow-x-auto pb-3 lg:pb-0 pr-1 lg:pr-4 snap-x snap-mandatory [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden">
{sidebarCategories.map((cat) => {
const isActive = activeCategory === cat.id;
const itemCount = cat.id === "All"
@@ -101,16 +106,16 @@ export default function MenuPage() {
<button
key={cat.id}
onClick={() => handleCategorySelect(cat.id)}
className={`w-full flex items-center justify-between px-5 py-3.5 rounded-2xl text-left transition-all group ${
className={`flex-shrink-0 snap-start min-w-[140px] lg:min-w-0 lg:w-full flex items-center justify-between px-5 py-3 lg:py-3.5 rounded-2xl text-left transition-all active:scale-[0.985] group ${
isActive
? "bg-[#101724] text-white shadow-lg"
: "hover:bg-white hover:shadow-sm text-[#101724] border border-transparent hover:border-[#e5e1d7]"
: "hover:bg-white hover:shadow-sm active:bg-[#EDE6D9] text-[#101724] border border-transparent hover:border-[#e5e1d7]"
}`}
>
<span className={`font-medium tracking-[-0.1px] ${isActive ? "" : "group-hover:text-[#0f5a4a]"}`}>
<span className={`font-medium tracking-[-0.1px] text-sm lg:text-base ${isActive ? "" : "group-hover:text-[#0f5a4a]"}`}>
{cat.name}
</span>
<span className={`text-xs px-2.5 py-0.5 rounded-full font-mono tabular-nums ${
<span className={`text-[10px] lg:text-xs px-2 py-0.5 rounded-full font-mono tabular-nums ${
isActive ? "bg-white/20" : "bg-[#e5e1d7] text-[#68717f]"
}`}>
{itemCount}
@@ -128,7 +133,7 @@ export default function MenuPage() {
<div className="mb-8 flex flex-col md:flex-row gap-4 items-center">
<input
type="text"
placeholder="Search dishes..."
placeholder={t.menu.searchPlaceholder}
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="w-full md:w-80 rounded-2xl border border-[#e5e1d7] bg-white px-5 py-3 text-sm placeholder:text-[#8A8478] focus:border-[#c99a2e] focus:ring-2 focus:ring-[#c99a2e]/20 transition-all"
@@ -136,13 +141,13 @@ export default function MenuPage() {
<button
onClick={() => setShowVegetarianOnly(!showVegetarianOnly)}
className={`px-6 py-3 rounded-2xl text-sm font-medium border transition-all ${
className={`px-6 py-3 rounded-2xl text-sm font-medium border transition-all active:scale-[0.985] ${
showVegetarianOnly
? "bg-[#0f5a4a] text-white border-[#0f5a4a]"
: "border-[#e5e1d7] hover:border-[#c99a2e] text-[#101724] bg-white"
}`}
>
{showVegetarianOnly ? "Vegetarian Only" : "Show Vegetarian"}
{showVegetarianOnly ? t.menu.vegetarianOnly : t.menu.showVegetarian}
</button>
{(searchQuery || showVegetarianOnly || activeCategory !== "All") && (
@@ -152,9 +157,9 @@ export default function MenuPage() {
setShowVegetarianOnly(false);
setActiveCategory("All");
}}
className="text-sm font-medium text-[#c99a2e] hover:text-[#8f6b22]"
className="text-sm font-medium text-[#c99a2e] hover:text-[#8f6b22] active:underline"
>
Clear filters
{t.menu.clearFilters}
</button>
)}
</div>
@@ -162,7 +167,7 @@ export default function MenuPage() {
{/* Menu Items */}
{filteredCategories.length === 0 ? (
<div className="text-center py-16 text-[#6B665F]">
No dishes found matching your filters.
{t.menu.noResults}
</div>
) : (
filteredCategories.map((category) => (
@@ -171,7 +176,7 @@ export default function MenuPage() {
<div className="text-3xl tracking-[-1px] text-[#101724]">{category.name}</div>
<div className="flex-1 h-px bg-gradient-to-r from-[#e5e1d7] to-transparent" />
<div className="text-sm font-medium text-[#68717f] tracking-widest">
{category.items.length} dishes
{category.items.length} {t.menu.dishes}
</div>
</div>
@@ -179,7 +184,7 @@ export default function MenuPage() {
{category.items.map((item) => (
<div
key={item.id}
className="menu-card group bg-white border border-[#EDE6D9] rounded-2xl overflow-hidden flex flex-col hover:border-[#c99a2e]/40 transition-all duration-300 cursor-pointer"
className="menu-card group bg-white border border-[#EDE6D9] rounded-2xl overflow-hidden flex flex-col hover:border-[#c99a2e]/40 active:border-[#c99a2e] active:scale-[0.985] transition-all duration-150 cursor-pointer touch-manipulation"
onClick={() => addToCart({ id: item.id, name: item.name, price: item.price, image: item.image })}
>
{/* Media - Restored Premium Video Hover + Poster Logic */}