Files
gaea21-v2-web/assets/components/ProfileCards.jsx
MohamedLoum1001 d3b9318dee feat(ui): modularisation du css et fidélisation des composants à la maquette figma
- découpage du css par composant (navbar, hero, footer, global)
- ajustement pixel-perfect du footer (newsletter full-bleed, alignements, typographies)
- documentation et commentaires détaillés du code react et css
2026-09-23 17:27:05 +02:00

147 lines
7.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 1. IMPORTATIONS DES MODULES ET DES ASSETS
import React from 'react';
// Webpack Encore gère l'empreinte de hachage (hashing) et le chemin public des images
import individusImg from '../img/individus.png';
import entrepriseImg from '../img/entreprise.png';
import institutionsImg from '../img/institutions.png';
import coachImg from '../img/coach.png';
/**
* 2. STRUCTURE DE DONNÉES STATIQUE : LISTE DES PROFILS CIBLES
* Externaliser les données hors du composant évite de recréer
* ce tableau en mémoire à chaque nouveau rendu (re-render) de React.
*/
const PROFILES = [
{
id: 1,
title: 'Individus',
image: individusImg,
href: '#individus', // Ancre ou future route vers le parcours Individus
},
{
id: 2,
title: 'Entreprises',
image: entrepriseImg,
href: '#entreprises',
},
{
id: 3,
title: 'Institutions',
image: institutionsImg,
href: '#institutions',
},
{
id: 4,
// Le caractère d'échappement '\n' force un saut de ligne contrôlé dans le titre
title: 'Université /\nCentre de recherche',
// Fallback d'image en attendant l'asset spécifique de l'université
image: institutionsImg,
href: '#universite',
},
{
id: 5,
title: 'Coach ou\nPraticien',
image: coachImg,
href: '#coach',
},
];
/**
* 3. COMPOSANT PRINCIPAL : ProfileCards
* Affiche la section de choix de profil utilisateur (« Qui êtes-vous ? »)
* sous forme d'une grille interactive de cartes verticales avec effet glass/hover.
*/
export default function ProfileCards() {
return (
/*
Balise sémantique <section> :
- py-20 : grand espacement vertical (padding-top & padding-bottom)
- px-6 sm:px-12 : padding horizontal adaptatif selon la taille d'écran
- bg-white : fond blanc assurant la continuité visuelle
*/
<section className="py-20 px-6 sm:px-12 bg-white">
{/*
Conteneur centré borné à 1380px max (conforme au Figma)
mx-auto permet de centrer horizontalement le conteneur dans la page
*/}
<div className="max-w-[1380px] mx-auto text-center">
{/* =========================================================
A. EN-TÊTE DE SECTION (Surtitre + Titre principal)
========================================================= */}
{/* Surtitre en majuscules avec espacement étendu entre les lettres (tracking) */}
<span className="text-[0.72rem] tracking-[0.22em] font-bold text-slate-400 uppercase block mb-3">
QUI ÊTES-VOUS ?
</span>
{/* Titre principal centré avec largeur maximale contrôlée (max-w-xl) */}
<h2 className="text-xl sm:text-2xl md:text-3xl font-semibold text-slate-800 leading-snug max-w-xl mx-auto mb-14">
Chaque profil est une porte d’entrée <br />
vers un écosystème de transformation
</h2>
{/* =========================================================
B. GRILLE RESPONSIVE DES 5 CARTES
- 2 colonnes sur mobile (grid-cols-2)
- 3 colonnes sur tablette (sm:grid-cols-3)
- 5 colonnes alignées sur desktop (md:grid-cols-5)
- Gouttières (gap) dynamiques
========================================================= */}
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-5 gap-3.5 sm:gap-4 lg:gap-5 justify-center">
{PROFILES.map((profile) => (
/*
Chaque carte est un lien interactif cliquable <a> :
- key={profile.id} : clé unique obligatoire pour l'algorithme de réconciliation de React
- group : permet aux éléments enfants (image, overlay) de réagir au survol du parent
- relative + overflow-hidden : indispensable pour contraindre l'image zoomée à l'arrondi (rounded-xl)
- h-[...] : hauteurs fixes échelonnées par breakpoint pour garder un ratio portrait élancé
- transform hover:-translate-y-1.5 : translation douce vers le haut au survol pour donner du relief
*/
<a
key={profile.id}
href={profile.href}
className="group relative block w-full h-[360px] sm:h-[420px] md:h-[460px] rounded-xl overflow-hidden shadow-sm hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1.5"
>
{/*
CALQUE 1 (Fond) : Photographie du profil
- object-cover : l'image remplit tout le conteneur sans se déformer
- group-hover:scale-105 : léger zoom cinématographique quand la souris survole la carte
- transition-transform duration-500 : animation fluide du zoom
*/}
<img
src={profile.image}
alt={profile.title.replace('\n', ' ')} // Remplace le saut de ligne par un espace pour l'accessibilité SEO
className="w-full h-full object-cover object-center group-hover:scale-105 transition-transform duration-500 ease-out"
/>
{/*
CALQUE 2 (Intermédiaire) : Dégradé sombre pour la lisibilité
- bg-gradient-to-t : dégradé vertical partant du bas vers le haut
- from-black/85 via-black/30 to-transparent : foncé en bas pour le texte, transparent en haut
- pointer-events-none : empêche ce calque décoratif de bloquer les clics
*/}
<div className="absolute inset-0 bg-gradient-to-t from-black/85 via-black/30 to-transparent pointer-events-none" />
{/*
CALQUE 3 (Premier plan) : Titre textuel de la carte
- absolute inset-x-0 bottom-0 : positionné en bas de la carte sur toute la largeur
- flex items-end justify-center : aligne le texte en bas et au centre
*/}
<div className="absolute inset-x-0 bottom-0 p-4 pb-6 flex items-end justify-center text-center">
{/*
- whitespace-pre-line : interprète les retours à la ligne '\n' définis dans le tableau PROFILES
- drop-shadow-md : ombre portée sur le texte pour garantir un contraste optimal
*/}
<span className="text-white text-base sm:text-lg font-bold leading-snug whitespace-pre-line tracking-tight drop-shadow-md">
{profile.title}
</span>
</div>
</a>
))}
</div>
</div>
</section>
);
}