350 lines
11 KiB
TypeScript
350 lines
11 KiB
TypeScript
import { useState, type ReactNode } from "react";
|
||
|
||
import bgSection from "&/images/global/paysage.png";
|
||
import bgSectionWebp from "&/images/global/paysage.webp";
|
||
// Icons
|
||
import ico1 from "&/images/icons/logo1.svg";
|
||
import ico2 from "&/images/icons/logo2.svg";
|
||
import ico3 from "&/images/icons/logo3.png";
|
||
import ico4 from "&/images/icons/logo4.svg";
|
||
import arrowRight from "&/images/icons/next_arrow.svg";
|
||
import arrowLeft from "&/images/icons/prev_arrow.svg";
|
||
import pinValeur from "&/images/icons/valeur-simplicite.svg";
|
||
// Images valeur
|
||
import img4 from "&/images/valeurs/FIABILITE ET SINCERITE.jpg";
|
||
import img4Webp from "&/images/valeurs/FIABILITE ET SINCERITE.webp";
|
||
import img3 from "&/images/valeurs/HUMILITE ET BIENVEILLANCE.jpg";
|
||
import img3Webp from "&/images/valeurs/HUMILITE ET BIENVEILLANCE.webp";
|
||
import img2 from "&/images/valeurs/PROXIMITE ET ENGAGEMENT.jpg";
|
||
import img2Webp from "&/images/valeurs/PROXIMITE ET ENGAGEMENT.webp";
|
||
import img1 from "&/images/valeurs/SIMPLICITÉ ET GÉNÉROSITÉ.jpg";
|
||
import img1Webp from "&/images/valeurs/SIMPLICITÉ ET GÉNÉROSITÉ.webp";
|
||
|
||
import VideoFrame from "./videoFrame";
|
||
|
||
interface Valeur {
|
||
id: string;
|
||
label: string;
|
||
icon: ImageValeur;
|
||
titre: string;
|
||
sousTitre: string;
|
||
image: ImageValeur;
|
||
contenu: ReactNode;
|
||
}
|
||
|
||
interface ImageValeur {
|
||
value: string;
|
||
webp?: string;
|
||
alt: string;
|
||
title: string;
|
||
}
|
||
|
||
const RED = "#E01B1B";
|
||
|
||
const VALEURS: Valeur[] = [
|
||
{
|
||
id: "simplicite",
|
||
label: "Simplicité et générosité",
|
||
icon: {
|
||
value: ico1,
|
||
alt: "Icône représentant la simplicité",
|
||
title: "Simplicité",
|
||
},
|
||
titre: "SIMPLICITÉ ET GÉNÉROSITÉ",
|
||
sousTitre: "Le goût des plaisirs vrais",
|
||
image: {
|
||
value: img1,
|
||
webp: img1Webp,
|
||
alt: "Poulet rôti accompagné de pommes de terre",
|
||
title: "Recette de poulet Ker Chant",
|
||
},
|
||
contenu: (
|
||
<>
|
||
<p>
|
||
Nous mettons en avant le meilleur de notre <strong>terroir</strong>{" "}
|
||
pour offrir des <strong>produits accessibles et gourmands.</strong>
|
||
</p>
|
||
<p>
|
||
Parce que la volaille est au <strong>cœur des repas</strong> qui{" "}
|
||
<strong>rassemblent</strong>, nous croyons aux{" "}
|
||
<strong>plaisirs simples</strong> et aux{" "}
|
||
<strong>moments partagés</strong>.
|
||
</p>
|
||
</>
|
||
),
|
||
},
|
||
{
|
||
id: "proximite",
|
||
label: "PROXIMITÉ ET ENGAGEMENT",
|
||
icon: {
|
||
value: ico2,
|
||
alt: "Icône représentant la proximité",
|
||
title: "Proximité",
|
||
},
|
||
titre: "PROXIMITÉ ET ENGAGEMENT",
|
||
sousTitre: "Une filière qui vit ici",
|
||
image: {
|
||
value: img2,
|
||
webp: img2Webp,
|
||
alt: "Paysage de champ avec paille",
|
||
title: "Champ éleveur Ker Chant",
|
||
},
|
||
contenu: (
|
||
<>
|
||
<p>
|
||
Nous sommes{" "}
|
||
<strong>proches de nos éleveurs et de nos consommateurs.</strong>
|
||
</p>
|
||
<p>
|
||
{" "}
|
||
Nous défendons une filière qui participe à l’économie régionale et
|
||
nous <strong>nous engageons à préserver son dynamisme.</strong>
|
||
</p>
|
||
</>
|
||
),
|
||
},
|
||
{
|
||
id: "humilite",
|
||
label: "humilité et bienveillance",
|
||
icon: {
|
||
value: ico3,
|
||
alt: "Icône représentant la qualité",
|
||
title: "Qualité des volailles Ker Chant",
|
||
},
|
||
titre: "HUMILITÉ ET BIENVEILLANCE",
|
||
sousTitre: "Avancer ensemble",
|
||
image: {
|
||
value: img3,
|
||
webp: img3Webp,
|
||
alt: "Repas de famille avec plat de volaille",
|
||
title: "Repas de famille",
|
||
},
|
||
contenu: (
|
||
<>
|
||
<p>
|
||
Nous avançons avec simplicité, en écoutant et en respectant ceux qui
|
||
nous entourent.
|
||
</p>
|
||
<p>
|
||
Nous voulons être <strong>une marque qui accompagne</strong>, qui
|
||
rassure et qui améliore sans cesse ses pratiques pour{" "}
|
||
<strong>répondre aux attentes de chacun.</strong>
|
||
</p>
|
||
</>
|
||
),
|
||
},
|
||
{
|
||
id: "fiabilite",
|
||
label: "fiabilité et sincérité",
|
||
icon: {
|
||
value: ico4,
|
||
alt: "Icône représentant le savoir-faire",
|
||
title: "Savoir-faire Ker Chant",
|
||
},
|
||
titre: "FIABILITÉ ET SINCÉRITÉ",
|
||
sousTitre: "La transparence avant tout",
|
||
image: {
|
||
value: img4,
|
||
webp: img4Webp,
|
||
alt: "Eleveur dans son poulailler",
|
||
title: "Eleveur Ker Chant",
|
||
},
|
||
contenu: (
|
||
<>
|
||
<p>
|
||
<strong>Nous garantissons des volailles élevées avec soin</strong>,
|
||
dans le respect du <strong>bien-être animal.</strong>
|
||
</p>
|
||
<p>
|
||
Chaque produit Ker Chant est le fruit d’un{" "}
|
||
<strong>savoir-faire authentique</strong> et d’une{" "}
|
||
<strong>traçabilité irréprochable.</strong>
|
||
</p>
|
||
</>
|
||
),
|
||
},
|
||
];
|
||
|
||
export default function ValeursSection() {
|
||
const [index, setIndex] = useState(0);
|
||
const v = VALEURS[index];
|
||
|
||
const go = (i: number) => {
|
||
setIndex(((i % VALEURS.length) + VALEURS.length) % VALEURS.length);
|
||
};
|
||
|
||
return (
|
||
<section
|
||
id="nos-valeurs"
|
||
className="relative w-full pt-16 pb-12 font-baloo overflow-hidden"
|
||
>
|
||
<picture className="absolute inset-0 -z-10">
|
||
<source srcSet={bgSectionWebp} type="image/webp" />
|
||
<img
|
||
src={bgSection}
|
||
alt=""
|
||
aria-hidden="true"
|
||
className="h-full w-full object-cover"
|
||
/>
|
||
</picture>
|
||
<VideoFrame />
|
||
<div className="pointer-events-none absolute right-[26%] top-0 z-5 hidden h-full w-[5px] translate-x-1/2 bg-[#E01B1B] lg:block" />
|
||
<h2 className="my-10 flex justify-center sm:my-14">
|
||
<span
|
||
className="banner-clip px-10 py-4 text-xl font-extrabold uppercase tracking-wide text-white sm:text-2xl"
|
||
style={{ background: RED }}
|
||
>
|
||
Nos valeurs
|
||
</span>
|
||
</h2>
|
||
|
||
<div className="relative mx-auto w-[92%] max-w-[1020px] px-6 lg:px-0">
|
||
{/* Onglets */}
|
||
<div className="relative z-20 flex items-end md:justify-center justify-start">
|
||
{VALEURS.map((val, i) => {
|
||
const active = i === index;
|
||
const showDivider = i > 0 && i !== index && i - 1 !== index;
|
||
return (
|
||
<div key={val.id} className="flex items-stretch">
|
||
{showDivider && (
|
||
<span
|
||
className="my-2 w-px self-center h-8 bg-red-500/80"
|
||
aria-hidden="true"
|
||
/>
|
||
)}
|
||
<button
|
||
type="button"
|
||
onClick={() => {
|
||
go(i);
|
||
}}
|
||
aria-label={val.label}
|
||
aria-current={active ? "true" : undefined}
|
||
className={
|
||
"group flex h-16 w-22 md:w-30 cursor-pointer items-center justify-center rounded-t-2xl transition-colors " +
|
||
(active ? "" : "hover:bg-(--red)")
|
||
}
|
||
style={
|
||
{
|
||
"--red": RED,
|
||
background: active ? RED : undefined,
|
||
} as React.CSSProperties
|
||
}
|
||
>
|
||
<img
|
||
src={val.icon.value}
|
||
alt=""
|
||
className={
|
||
"sm:h-14 sm:w-14 h-11 w-11 object-contain transition-[filter] " +
|
||
(active
|
||
? "brightness-0 invert"
|
||
: "group-hover:brightness-0 group-hover:invert")
|
||
}
|
||
/>
|
||
</button>
|
||
</div>
|
||
);
|
||
})}
|
||
</div>
|
||
|
||
{/* card */}
|
||
<div className="relative z-10 min-h-[400px] rounded-b-3xl bg-white px-6 py-10 shadow-xl lg:h-[400px] lg:px-14 lg:py-12">
|
||
<div className="pointer-events-none absolute right-0 top-0 z-20 hidden h-full translate-x-1/2 lg:block">
|
||
<div className="absolute right-[40%] -top-1 z-30 hidden -translate-y-10 lg:block">
|
||
<div
|
||
className="flex h-30 w-30 items-center justify-center rounded-full"
|
||
style={{
|
||
background: "#1D1E1C",
|
||
boxShadow: "0 4px 4px rgba(0,0,0,.25)",
|
||
}}
|
||
>
|
||
<img src={pinValeur} alt="" className="h-32 w-24" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Prev */}
|
||
<button
|
||
type="button"
|
||
onClick={() => {
|
||
go(index - 1);
|
||
}}
|
||
aria-label="Valeur précédente"
|
||
className="absolute left-2 top-1/2 z-30 flex sm:h-10 sm:w-10 h-7 w-7 -translate-y-1/2 cursor-pointer items-center justify-center rounded-full bg-black text-white transition-transform hover:scale-105 hover:bg-[#E01B1B] md:-left-11 lg:-left-16"
|
||
>
|
||
<img
|
||
src={arrowLeft}
|
||
alt=""
|
||
className="sm:h-5 sm:w-5 h-3.5 w-3.5 object-contain"
|
||
/>
|
||
</button>
|
||
|
||
{/* Next */}
|
||
<button
|
||
type="button"
|
||
onClick={() => {
|
||
go(index + 1);
|
||
}}
|
||
aria-label="Valeur suivante"
|
||
className="absolute right-2 top-1/2 z-30 flex sm:h-10 sm:w-10 h-7 w-7 -translate-y-1/2 cursor-pointer items-center justify-center rounded-full bg-black text-white transition-transform hover:scale-105 hover:bg-[#E01B1B] md:-right-11 lg:-right-16"
|
||
>
|
||
<img
|
||
src={arrowRight}
|
||
alt=""
|
||
className="sm:h-5 sm:w-5 h-3.5 w-3.5 object-contain"
|
||
/>
|
||
</button>
|
||
|
||
{/* texte + image */}
|
||
<div className="flex flex-col items-center gap-8 lg:flex-row lg:gap-16">
|
||
<div className="flex-1">
|
||
<h3
|
||
className="text-xl font-extrabold uppercase lg:text-[36px]"
|
||
style={{ color: RED }}
|
||
>
|
||
{v.titre}
|
||
</h3>
|
||
<h4 className="-mt-2 text-xl font-bold text-neutral-900 lg:text-[28px]">
|
||
{v.sousTitre}
|
||
</h4>
|
||
<div className="mt-6 space-y-4 text-lg leading-snug text-neutral-800 lg:px-0 px-8 lg:max-w-[454px] lg:text-xl">
|
||
{v.contenu}
|
||
</div>
|
||
</div>
|
||
|
||
<picture>
|
||
<source srcSet={v.image.webp} type="image/webp" />
|
||
<img
|
||
src={v.image.value}
|
||
alt={v.image.alt}
|
||
title={v.image.title}
|
||
className="h-[168px] w-[234px] -rotate-2 object-cover lg:h-[270px] lg:w-[280px] lg:pt-18"
|
||
/>
|
||
</picture>
|
||
</div>
|
||
</div>
|
||
{/* Pagination */}
|
||
<div className="mx-auto mt-10 flex w-[280px] max-w-full items-center gap-0 overflow-hidden">
|
||
{VALEURS.map((val, i) => {
|
||
const active = i === index;
|
||
return (
|
||
<button
|
||
key={val.id}
|
||
type="button"
|
||
onClick={() => {
|
||
go(i);
|
||
}}
|
||
aria-label={`Aller à : ${val.label}`}
|
||
className="flex-1 rounded-full transition-all"
|
||
style={{
|
||
height: active ? "5px" : "2px",
|
||
background: active ? RED : "#1D1E1C",
|
||
opacity: active ? 1 : 0.7,
|
||
}}
|
||
/>
|
||
);
|
||
})}
|
||
</div>
|
||
</div>
|
||
</section>
|
||
);
|
||
}
|