Refine contact and trust UI
This commit is contained in:
@@ -24,6 +24,7 @@ All notable changes to the New Optic website will be documented in this file.
|
||||
|
||||
### Changed
|
||||
|
||||
- Refined contact and trust UI: stat labels are now accented above values, French WhatsApp CTA says "Discuter sur WhatsApp", hours information is emphasized, and mobile navbar shows WhatsApp without opening the menu.
|
||||
- Updated customer-corrected business facts: New Optic is active since around 2004, does not offer eye exams, and offers contact lenses plus colored contact lenses.
|
||||
- Optimized mobile rendering by disabling heavy blur, fixed backgrounds, ambient animations, and WebGL glass below desktop widths.
|
||||
- Changed mobile CSS to reference only the compressed mobile background by default, keeping the full PNG desktop-only.
|
||||
|
||||
@@ -29,7 +29,7 @@ export default function ContactSection({ t, whatsappUrl }: { t: Messages; whatsa
|
||||
<Info label={t.contact.phoneLabel} value={business.phone} icon={<Phone size={18} />} />
|
||||
<Info label={t.contact.whatsappLabel} value={business.whatsapp} icon={<Phone size={18} />} />
|
||||
<Info label={t.contact.addressLabel} value={business.displayAddress} icon={<MapPin size={18} />} wide />
|
||||
<Info label={t.contact.hoursLabel} value={t.contact.hoursValue} icon={<QrCode size={18} />} />
|
||||
<Info label={t.contact.hoursLabel} value={t.contact.hoursValue} icon={<QrCode size={18} />} wide accent />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -48,14 +48,14 @@ export default function ContactSection({ t, whatsappUrl }: { t: Messages; whatsa
|
||||
);
|
||||
}
|
||||
|
||||
function Info({ label, value, icon, wide = false }: { label: string; value: string; icon: React.ReactNode; wide?: boolean }) {
|
||||
function Info({ label, value, icon, wide = false, accent = false }: { label: string; value: string; icon: React.ReactNode; wide?: boolean; accent?: boolean }) {
|
||||
return (
|
||||
<div className={`rounded-[1.6rem] border border-ink/8 bg-smoke/80 p-5 ${wide ? "sm:col-span-2" : ""}`}>
|
||||
<div className={`rounded-[1.6rem] border p-5 ${wide ? "sm:col-span-2" : ""} ${accent ? "border-optical/20 bg-optical/10 sm:p-6" : "border-ink/8 bg-smoke/80"}`}>
|
||||
<div className="mb-3 flex items-center gap-2 text-optical">
|
||||
{icon}
|
||||
<p className="text-xs font-semibold uppercase tracking-[0.18em]">{label}</p>
|
||||
</div>
|
||||
<p className="text-sm font-semibold leading-7 text-ink/72">{value}</p>
|
||||
<p className={`${accent ? "text-lg leading-8 text-ink sm:text-xl" : "text-sm leading-7 text-ink/72"} font-semibold`}>{value}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -24,12 +24,12 @@ export default function Navbar({ locale, onLocaleChange, t, whatsappUrl }: { loc
|
||||
|
||||
return (
|
||||
<header className="fixed inset-x-0 top-0 z-50 px-4 pt-4 sm:px-6">
|
||||
<nav className="glass mx-auto flex max-w-7xl items-center justify-between rounded-full px-4 py-3 sm:px-5" aria-label="Main navigation">
|
||||
<nav className="glass mx-auto flex max-w-7xl items-center justify-between gap-2 rounded-full px-3 py-3 sm:px-5" aria-label="Main navigation">
|
||||
<a href="#home" onClick={(event) => scrollToSection(event, "#home")} className="relative z-[3] flex items-center gap-3" aria-label="New Optic home">
|
||||
<span className="relative grid size-10 place-items-center overflow-hidden rounded-full bg-white shadow-sm">
|
||||
<Image src={business.assets.logo} alt="New Optic logo" fill sizes="40px" className="object-contain p-1" priority />
|
||||
</span>
|
||||
<span className="text-sm font-semibold tracking-[-0.02em]">{business.name}</span>
|
||||
<span className="hidden text-sm font-semibold tracking-[-0.02em] xs:inline sm:inline">{business.name}</span>
|
||||
</a>
|
||||
|
||||
<div className="relative z-[3] hidden items-center gap-7 lg:flex">
|
||||
@@ -47,9 +47,14 @@ export default function Navbar({ locale, onLocaleChange, t, whatsappUrl }: { loc
|
||||
</PhysicsButton>
|
||||
</div>
|
||||
|
||||
<button type="button" onClick={() => setOpen((value) => !value)} className="relative z-[3] grid size-11 place-items-center rounded-full bg-white/70 text-ink md:hidden" aria-label={t.nav.menu} aria-expanded={open}>
|
||||
{open ? <X size={18} /> : <Menu size={18} />}
|
||||
</button>
|
||||
<div className="relative z-[3] flex items-center gap-2 md:hidden">
|
||||
<PhysicsButton href={whatsappUrl} external className="rounded-full bg-ink px-4 py-2.5 text-xs font-semibold text-white shadow-soft transition-colors hover:bg-optical sm:px-5 sm:text-sm">
|
||||
{t.nav.cta}
|
||||
</PhysicsButton>
|
||||
<button type="button" onClick={() => setOpen((value) => !value)} className="grid size-11 place-items-center rounded-full bg-white/70 text-ink" aria-label={t.nav.menu} aria-expanded={open}>
|
||||
{open ? <X size={18} /> : <Menu size={18} />}
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<AnimatePresence>
|
||||
@@ -70,9 +75,6 @@ export default function Navbar({ locale, onLocaleChange, t, whatsappUrl }: { loc
|
||||
</div>
|
||||
<div className="mt-4 flex items-center justify-between gap-3">
|
||||
<LanguageSwitcher locale={locale} onLocaleChange={onLocaleChange} />
|
||||
<PhysicsButton href={whatsappUrl} external className="rounded-full bg-ink px-5 py-3 text-sm font-semibold text-white">
|
||||
{t.nav.cta}
|
||||
</PhysicsButton>
|
||||
</div>
|
||||
</motion.div>
|
||||
) : null}
|
||||
|
||||
@@ -11,8 +11,8 @@ export default function TrustSection({ t }: { t: Messages }) {
|
||||
<motion.div className="mt-12 grid gap-4 md:grid-cols-3" initial={false} whileInView="show" viewport={{ once: true, amount: 0.08 }} variants={{ show: { transition: { staggerChildren: 0.12 } } }}>
|
||||
{t.trust.stats.map((stat) => (
|
||||
<motion.div key={stat.value} variants={{ show: { opacity: 1, y: 0, scale: 1 } }} transition={{ duration: 0.65, ease: [0.22, 1, 0.36, 1] }} whileHover={{ y: -6 }} className="rounded-[2rem] border border-white/10 bg-white/[0.06] p-6 text-center backdrop-blur">
|
||||
<p className="mb-4 text-xs font-semibold uppercase tracking-[0.22em] text-optical/90">{stat.label}</p>
|
||||
<p className="text-5xl font-semibold tracking-[-0.06em] text-white">{stat.value}</p>
|
||||
<p className="mt-3 text-sm leading-6 text-white/58">{stat.label}</p>
|
||||
</motion.div>
|
||||
))}
|
||||
</motion.div>
|
||||
|
||||
@@ -68,9 +68,9 @@ export const en = {
|
||||
eyebrow: "Reputation",
|
||||
title: "A neighborhood optician with lasting standards.",
|
||||
stats: [
|
||||
{ value: "2004", label: "local presence since around" },
|
||||
{ value: "100%", label: "authentic frames" },
|
||||
{ value: "360°", label: "guidance, lenses, frames and support" }
|
||||
{ value: "2004", label: "Local presence since around" },
|
||||
{ value: "100%", label: "Authentic frames" },
|
||||
{ value: "360°", label: "Guidance, lenses, frames and support" }
|
||||
],
|
||||
body: "No exaggerated claims. New Optic earns trust through guidance, consistent service and a selection of authentic products."
|
||||
},
|
||||
|
||||
@@ -68,9 +68,9 @@ export const fr = {
|
||||
eyebrow: "Reputation",
|
||||
title: "Un opticien de quartier avec une exigence durable.",
|
||||
stats: [
|
||||
{ value: "2004", label: "presence locale depuis autour de" },
|
||||
{ value: "100%", label: "montures originales" },
|
||||
{ value: "360°", label: "conseil, verres, montures et suivi" }
|
||||
{ value: "2004", label: "Présence locale depuis autour de" },
|
||||
{ value: "100%", label: "Montures originales" },
|
||||
{ value: "360°", label: "Conseil, verres, montures et suivi" }
|
||||
],
|
||||
body: "Pas de promesses exagérées. New Optic construit la relation par le conseil, la régularité du service et une sélection de produits authentiques."
|
||||
},
|
||||
@@ -78,7 +78,7 @@ export const fr = {
|
||||
eyebrow: "Contact",
|
||||
title: "Passez en magasin ou contactez-nous directement.",
|
||||
body: "Une question sur vos verres, une reparation ou une nouvelle monture ? Envoyez un message WhatsApp, appelez, ou venez nous voir a Massira 1, Temara.",
|
||||
whatsapp: "Ecrire sur WhatsApp",
|
||||
whatsapp: "Discuter sur WhatsApp",
|
||||
call: "Appeler maintenant",
|
||||
visit: "Ouvrir l'itineraire",
|
||||
qr: "Scannez pour ouvrir l'adresse",
|
||||
@@ -86,7 +86,7 @@ export const fr = {
|
||||
whatsappLabel: "WhatsApp",
|
||||
addressLabel: "Adresse",
|
||||
hoursLabel: "Horaires",
|
||||
hoursValue: "Horaires non publies en ligne. Contactez le magasin avant de vous deplacer.",
|
||||
hoursValue: "Horaires non publiés en ligne. Contactez le magasin avant de vous déplacer.",
|
||||
whatsappMessage: "Bonjour New Optic, je souhaite avoir des informations sur vos lunettes et services."
|
||||
},
|
||||
footer: {
|
||||
|
||||
Reference in New Issue
Block a user