- 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
119 lines
5.2 KiB
JavaScript
119 lines
5.2 KiB
JavaScript
// 1. IMPORTATION DES MODULES ET ASSETS
|
|
import React, { useState } from 'react';
|
|
|
|
// Import du logo gaea21 via Webpack Encore (gestion du hashing et du chemin public)
|
|
import logo from '../img/logo_gaea21.png';
|
|
|
|
/**
|
|
* 2. COMPOSANT PRINCIPAL : Header
|
|
*
|
|
* Rôle fonctionnel :
|
|
* - Fournit la barre de navigation principale (Navbar) fixée ou relative en haut de page.
|
|
* - Gère l'affichage responsive : menu étendu sur desktop, tiroir repliable (drawer) sur mobile.
|
|
* - Propose un bouton d'action principal (« Participer ») pour convertir le visiteur.
|
|
*/
|
|
export default function Header() {
|
|
/**
|
|
* ÉTAT LOCAL (State) : isOpen
|
|
* - false : le menu mobile est fermé
|
|
* - true : le menu mobile est ouvert (déroulé/visible)
|
|
*/
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
|
|
return (
|
|
/*
|
|
Balise sémantique HTML5 <header> :
|
|
- navbar-container : gère le fond, la bordure inférieure éventuelle,
|
|
la hauteur fixe et le z-index pour rester au-dessus du contenu de la page.
|
|
*/
|
|
<header className="navbar-container">
|
|
|
|
{/*
|
|
Conteneur interne centré :
|
|
- navbar-content : applique un flexbox (justify-content: space-between, align-items: center)
|
|
et borne la largeur maximale avec un padding latéral propre.
|
|
*/}
|
|
<div className="navbar-content">
|
|
|
|
{/* =========================================================
|
|
A. LOGO DE LA MARQUE
|
|
========================================================= */}
|
|
<a href="/" className="navbar-logo" aria-label="Retour à l'accueil gaea21">
|
|
<img src={logo} alt="Logo gaea21" />
|
|
</a>
|
|
|
|
{/* =========================================================
|
|
B. BOUTON BURGER (Affiché uniquement sur écrans mobiles)
|
|
========================================================= */}
|
|
<button
|
|
type="button"
|
|
/*
|
|
Basculement dynamique de la classe 'active' :
|
|
Permet en CSS d'animer les 3 barres pour former une croix 'X' quand isOpen vaut true.
|
|
*/
|
|
className={`hamburger ${isOpen ? 'active' : ''}`}
|
|
/* Inverse la valeur booléenne au clic (ouvre ou ferme le menu) */
|
|
onClick={() => setIsOpen(!isOpen)}
|
|
/* Attributs d'accessibilité ARIA pour les lecteurs d'écran */
|
|
aria-label={isOpen ? 'Fermer le menu de navigation' : 'Ouvrir le menu de navigation'}
|
|
aria-expanded={isOpen}
|
|
>
|
|
{/* Les 3 barres horizontales du burger dessinées en CSS */}
|
|
<span></span>
|
|
<span></span>
|
|
<span></span>
|
|
</button>
|
|
|
|
{/* =========================================================
|
|
C. MENU DE NAVIGATION (DESKTOP & TIROIR MOBILE)
|
|
========================================================= */}
|
|
{/*
|
|
La classe 'open' est ajoutée conditionnellement pour déclencher
|
|
l'apparition du tiroir de navigation en version mobile.
|
|
*/}
|
|
<nav className={`navbar-nav ${isOpen ? 'open' : ''}`}>
|
|
|
|
{/* Liste ordonnée des ancres de navigation */}
|
|
<ul className="nav-links">
|
|
<li>
|
|
{/* Le onClick={() => setIsOpen(false)} referme automatiquement le menu mobile après le clic */}
|
|
<a href="#parcours" onClick={() => setIsOpen(false)}>
|
|
Parcours
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="#projet" onClick={() => setIsOpen(false)}>
|
|
Projet
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="#ecosysteme" onClick={() => setIsOpen(false)}>
|
|
Écosystème
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="#contact" onClick={() => setIsOpen(false)}>
|
|
Contact
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
|
|
{/* =========================================================
|
|
D. BOUTON D'ACTION PRINCIPAL (CALL-TO-ACTION)
|
|
========================================================= */}
|
|
<div className="navbar-action">
|
|
<a
|
|
href="#participer"
|
|
className="btn-participer"
|
|
// Ferme le menu mobile si cliqué
|
|
onClick={() => setIsOpen(false)}
|
|
>
|
|
Participer
|
|
</a>
|
|
</div>
|
|
|
|
</nav>
|
|
</div>
|
|
</header>
|
|
);
|
|
} |