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:
+1
-1
@@ -91,7 +91,7 @@ export default function RootLayout({
|
||||
}>) {
|
||||
return (
|
||||
<html
|
||||
lang="en"
|
||||
lang="sv"
|
||||
className={`${playfair.variable} ${geistSans.variable} ${geistMono.variable} h-full antialiased`}
|
||||
>
|
||||
<body className="min-h-full flex flex-col bg-[#F8F5F0] text-[#2C2A26]">
|
||||
|
||||
@@ -16,10 +16,16 @@
|
||||
* - Both branches now have the same opening hours.
|
||||
*/
|
||||
|
||||
'use client';
|
||||
|
||||
import Navbar from "@/components/Navbar";
|
||||
import Footer from "@/components/Footer";
|
||||
import { useLanguage } from "@/lib/language-context";
|
||||
import { getTranslation } from "@/lib/translations";
|
||||
|
||||
export default function LocationsPage() {
|
||||
const { language } = useLanguage();
|
||||
const t = getTranslation(language);
|
||||
return (
|
||||
<div className="min-h-screen bg-[#F8F5F0] text-[#2C2A26]">
|
||||
<Navbar />
|
||||
@@ -27,15 +33,15 @@ export default function LocationsPage() {
|
||||
<div className="max-w-5xl mx-auto px-6 pt-20 pb-16">
|
||||
<div className="text-center mb-12">
|
||||
<div className="text-[#B38B4D] text-xs tracking-[3px] mb-3">WHERE TO FIND US</div>
|
||||
<h1 className="text-6xl md:text-7xl tracking-[-2.5px] leading-none mb-4">Our Locations</h1>
|
||||
<h1 className="text-6xl md:text-7xl tracking-[-2.5px] leading-none mb-4">{language === 'sv' ? 'Våra Platser' : 'Our Locations'}</h1>
|
||||
<p className="text-xl text-[#6B665F] max-w-md mx-auto">
|
||||
Two branches in Gothenburg — both serving authentic flavors with the same royal hospitality.
|
||||
{language === 'sv' ? 'Två restauranger i Göteborg — båda serverar autentiska smaker med samma kungliga gästfrihet.' : 'Two branches in Gothenburg — both serving authentic flavors with the same royal hospitality.'}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-center mb-8">
|
||||
<a href="/#contact" className="btn-primary px-8 py-3 rounded-full text-sm tracking-[0.5px]">
|
||||
Make a Reservation
|
||||
{t.reserve}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
+20
-15
@@ -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 */}
|
||||
|
||||
+13
-9
@@ -233,13 +233,13 @@ export default function ShahiKitchenHomepage() {
|
||||
<p className="max-w-md text-lg font-medium text-[#4b5563]">{t.signatureMenu.subtitle}</p>
|
||||
</div>
|
||||
|
||||
{/* Filters */}
|
||||
<div className="mb-8 flex flex-wrap gap-2">
|
||||
{/* Filters - modern horizontal scroller on mobile for easy thumb use */}
|
||||
<div className="mb-8 -mx-1 px-1 flex gap-2 overflow-x-auto snap-x snap-mandatory pb-2 [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden">
|
||||
{["All", "Rice", "Curry", "Meat", "Street", "Roll", "Sweet"].map((cat) => (
|
||||
<button
|
||||
key={cat}
|
||||
onClick={() => setMenuFilter(cat as any)}
|
||||
className={`rounded-full px-6 py-3 text-sm font-bold transition-all ${menuFilter === cat ? "bg-[#101724] text-white" : "border border-[#e5e1d7] bg-white text-[#182235] hover:border-[#c99a2e] hover:bg-[#fff6dc]"}`}
|
||||
className={`flex-shrink-0 snap-start rounded-full px-5 py-2.5 text-sm font-bold transition-all active:scale-[0.97] touch-manipulation ${menuFilter === cat ? "bg-[#101724] text-white" : "border border-[#e5e1d7] bg-white text-[#182235] hover:border-[#c99a2e] hover:bg-[#fff6dc] active:bg-[#fff6dc]"}`}
|
||||
>
|
||||
{cat}
|
||||
</button>
|
||||
@@ -254,7 +254,7 @@ export default function ShahiKitchenHomepage() {
|
||||
key={dish.id}
|
||||
layout
|
||||
onClick={() => addDish(dish)}
|
||||
className="signature-card group flex cursor-pointer flex-col overflow-hidden rounded-[2rem] border border-[#EDE6D9] bg-white"
|
||||
className="signature-card group flex cursor-pointer flex-col overflow-hidden rounded-[2rem] border border-[#EDE6D9] bg-white active:scale-[0.985] active:border-[#c99a2e]/60 transition-transform touch-manipulation"
|
||||
>
|
||||
<div className="relative h-48 overflow-hidden bg-[#F2EDE4]">
|
||||
<img
|
||||
@@ -277,7 +277,7 @@ export default function ShahiKitchenHomepage() {
|
||||
|
||||
<button
|
||||
onClick={(e) => { e.stopPropagation(); addDish(dish); }}
|
||||
className="mt-5 w-full py-3 text-sm tracking-[0.6px] border border-[#B38B4D] text-[#B38B4D] rounded-full hover:bg-[#B38B4D] hover:text-white font-medium transition-all"
|
||||
className="mt-5 w-full py-3.5 text-sm tracking-[0.6px] border border-[#B38B4D] text-[#B38B4D] rounded-full hover:bg-[#B38B4D] hover:text-white active:bg-[#8C6B3A] active:text-white active:scale-[0.985] font-medium transition-all touch-manipulation"
|
||||
>
|
||||
{t.signatureMenu.addToTable}
|
||||
</button>
|
||||
@@ -299,16 +299,20 @@ export default function ShahiKitchenHomepage() {
|
||||
<section id="experience" className="section bg-white border-y border-[#EDE6D9]">
|
||||
<div className="max-w-6xl mx-auto px-6">
|
||||
<div className="text-center mb-14">
|
||||
<div className="text-[#B38B4D] text-xs tracking-[3px] mb-3">THE SHAHI WAY</div>
|
||||
<h3 className="text-5xl md:text-6xl tracking-[-2px]">More than a meal.<br />A moment of royalty.</h3>
|
||||
<div className="text-[#B38B4D] text-xs tracking-[3px] mb-3">{language === 'sv' ? 'SHAHI-SÄTTET' : 'THE SHAHI WAY'}</div>
|
||||
<h3 className="text-5xl md:text-6xl tracking-[-2px]">{language === 'sv' ? 'Mer än en måltid.\nEtt ögonblick av kunglighet.' : 'More than a meal.\nA moment of royalty.'}</h3>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-3 gap-6">
|
||||
{[
|
||||
{(language === 'sv' ? [
|
||||
{ title: "Den Legendariska Buffén", desc: "Vår berömda lunchbuffé har över 20 roterande rätter — curry, biryani, färsk naan och sötsaker." },
|
||||
{ title: "Shahi Sötsaker", desc: "Hemgjord mithai dagligen. Från färsk jalebi till rasmalai — det perfekta söta avslutet." },
|
||||
{ title: "Varm Gästfrihet", desc: "Oavsett om du är här för en snabb lunch eller familjefest, behandlas du alltid som kunglighet." },
|
||||
] : [
|
||||
{ title: "The Legendary Buffet", desc: "Our famous lunch buffet features over 20 rotating dishes — curries, biryanis, fresh naan, and sweets." },
|
||||
{ title: "Shahi Sweets", desc: "Homemade mithai made daily. From fresh Jalebi to Rasmalai — the perfect sweet ending." },
|
||||
{ title: "Warm Hospitality", desc: "Whether you're here for a quick lunch or a family celebration, you will always be treated like royalty." },
|
||||
].map((item, index) => (
|
||||
]).map((item, index) => (
|
||||
<div key={index} className="experience-card group relative border border-[#EDE6D9] p-9 rounded-2xl bg-[#F8F5F0] overflow-hidden">
|
||||
<div className="text-[#B38B4D] text-6xl font-light mb-9 tracking-[-2px]">0{index + 1}</div>
|
||||
<h4 className="text-[29px] tracking-[-0.8px] mb-5 text-[#2C2A26] leading-tight">{item.title}</h4>
|
||||
|
||||
Reference in New Issue
Block a user