add of responsive design

This commit is contained in:
2025-11-02 23:41:24 +01:00
parent b4074f5880
commit cbd236fce5
2 changed files with 163 additions and 47 deletions
+71 -30
View File
@@ -1,10 +1,11 @@
import styles from "./Header.module.css"
import {Link, NavLink} from "react-router";
import {useEffect, useRef, useState} from "react";
import { Link, NavLink } from "react-router";
import { useEffect, useRef, useState } from "react";
function Header(){
function Header() {
const [notificationMenu, setnotificationMenu] = useState(false);
const [unreadNotification, setunreadNotification] = useState(true);
const [mobileMenu, setMobileMenu] = useState(false);
const notificationRef = useRef(null);
const [notifications, setNotifications] = useState([
@@ -15,7 +16,11 @@ function Header(){
useEffect(() => {
const handleClickOutside = (event) => {
if (notificationRef.current && !notificationRef.current.contains(event.target) && !event.target.closest(`.${styles.bellBtn}`)) {
if (
notificationRef.current &&
!notificationRef.current.contains(event.target) &&
!event.target.closest(`.${styles.bellBtn}`)
) {
setnotificationMenu(false);
}
};
@@ -26,55 +31,91 @@ function Header(){
};
}, []);
return (
<div className={styles.headerContainer}>
<header className={`${styles.header} ${"glassCard"}`} >
<nav className={styles.headerContent}>
<header className={`${styles.header} glassCard`}>
<nav className={`${mobileMenu ? styles.inactiveHeaderContent : styles.activeHeaderContent}`}>
<div className={styles.headerLeftContent}>
<NavLink className={styles.logoLink} to="/">
<img src="/src/assets/logo.png" alt="logo" className={styles.logo}/>
</NavLink>
<NavLink to="/" className={({ isActive }) => isActive ? styles.activeLink : styles.link}>
Accueil
</NavLink>
<NavLink to="/event" className={({ isActive }) => isActive ? styles.activeLink : styles.link}>
Evènements
</NavLink>
<NavLink to="/volunteers" className={({ isActive }) => isActive ? styles.activeLink : styles.link}>
Bénévoles
<img src="/src/assets/logo.png" alt="logo" className={styles.logo} />
</NavLink>
<div className={styles.navLinks}>
<NavLink to="/" className={({ isActive }) => isActive ? styles.activeLink : styles.link}>
Accueil
</NavLink>
<NavLink to="/event" className={({ isActive }) => isActive ? styles.activeLink : styles.link}>
Evènements
</NavLink>
<NavLink to="/volunteers" className={({ isActive }) => isActive ? styles.activeLink : styles.link}>
Bénévoles
</NavLink>
</div>
</div>
<div className={styles.headerRightContent}>
<button
className={`${styles.bellBtn} ${notificationMenu ? styles.activeBellBtn : ""}`}
onClick={() => {setnotificationMenu(!notificationMenu); setunreadNotification(false);}}>
className={`${styles.bellBtn} ${notificationMenu ? styles.activeBellBtn : ""}`}
onClick={() => {
setnotificationMenu(!notificationMenu);
setunreadNotification(false);
}}
>
<svg width="auto" height="30" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M34.325 52.5C33.8855 53.2577 33.2546 53.8866 32.4956 54.3238C31.7365 54.761 30.8759 54.9911 30 54.9911C29.1241 54.9911 28.2635 54.761 27.5044 54.3238C26.7454 53.8866 26.1145 53.2577 25.675 52.5M45 20C45 16.0218 43.4196 12.2064 40.6066 9.3934C37.7936 6.58035 33.9782 5 30 5C26.0218 5 22.2064 6.58035 19.3934 9.3934C16.5804 12.2064 15 16.0218 15 20C15 37.5 7.5 42.5 7.5 42.5H52.5C52.5 42.5 45 37.5 45 20Z" stroke="currentStroke"/>
<path d="M34.325 52.5C33.8855 53.2577 33.2546 53.8866 32.4956 54.3238C31.7365 54.761 30.8759 54.9911 30 54.9911C29.1241 54.9911 28.2635 54.761 27.5044 54.3238C26.7454 53.8866 26.1145 53.2577 25.675 52.5M45 20C45 16.0218 43.4196 12.2064 40.6066 9.3934C37.7936 6.58035 33.9782 5 30 5C26.0218 5 22.2064 6.58035 19.3934 9.3934C16.5804 12.2064 15 16.0218 15 20C15 37.5 7.5 42.5 7.5 42.5H52.5C52.5 42.5 45 37.5 45 20Z" stroke="currentStroke" />
</svg>
{unreadNotification ? <span className={styles.notificationBadge}></span> : null}
{unreadNotification && <span className={styles.notificationBadge}></span>}
</button>
<Link to="" className={styles.profileLink}>
<svg xmlns="http://www.w3.org/2000/svg" height="30px" viewBox="0 -960 960 960" width="auto" fill="currentFill">
<path d="M480-492.31q-57.75 0-98.87-41.12Q340-574.56 340-632.31q0-57.75 41.13-98.87 41.12-41.13 98.87-41.13 57.75 0 98.87 41.13Q620-690.06 620-632.31q0 57.75-41.13 98.88-41.12 41.12-98.87 41.12ZM180-187.69v-88.93q0-29.38 15.96-54.42 15.96-25.04 42.66-38.5 59.3-29.07 119.65-43.61 60.35-14.54 121.73-14.54t121.73 14.54q60.35 14.54 119.65 43.61 26.7 13.46 42.66 38.5Q780-306 780-276.62v88.93H180Zm60-60h480v-28.93q0-12.15-7.04-22.5-7.04-10.34-19.11-16.88-51.7-25.46-105.42-38.58Q534.7-367.69 480-367.69q-54.7 0-108.43 13.11-53.72 13.12-105.42 38.58-12.07 6.54-19.11 16.88-7.04 10.35-7.04 22.5v28.93Zm240-304.62q33 0 56.5-23.5t23.5-56.5q0-33-23.5-56.5t-56.5-23.5q-33 0-56.5 23.5t-23.5 56.5q0 33 23.5 56.5t56.5 23.5Zm0-80Zm0 384.62Z"/>
<path d="M480-492.31q-57.75 0-98.87-41.12Q340-574.56 340-632.31q0-57.75 41.13-98.87 41.12-41.13 98.87-41.13 57.75 0 98.87 41.13Q620-690.06 620-632.31q0 57.75-41.13 98.88-41.12 41.12-98.87 41.12ZM180-187.69v-88.93q0-29.38 15.96-54.42 15.96-25.04 42.66-38.5 59.3-29.07 119.65-43.61 60.35-14.54 121.73-14.54t121.73 14.54q60.35 14.54 119.65 43.61 26.7 13.46 42.66 38.5Q780-306 780-276.62v88.93H180Z" />
</svg>
</Link>
</div>
</nav>
<nav className={`${mobileMenu ? styles.activeMobileMenu : styles.inactiveMobileMenu}`}>
<NavLink to="/" className={({ isActive }) => isActive ? styles.activeLink : styles.link}>
Accueil
</NavLink>
<NavLink to="/event" className={({ isActive }) => isActive ? styles.activeLink : styles.link}>
Evènements
</NavLink>
<NavLink to="/volunteers" className={({ isActive }) => isActive ? styles.activeLink : styles.link}>
Bénévoles
</NavLink>
</nav>
<button
className={`${styles.burgerBtn} ${mobileMenu ? styles.activeBurgerBtn : ""}`}
onClick={() => setMobileMenu(!mobileMenu)}
>
<div className={styles.burgerBar}></div>
<div className={styles.burgerBar}></div>
<div className={styles.burgerBar}></div>
</button>
</header>
<div ref={notificationRef} className={`${styles.notificationDiv} ${"glassCard"} ${notificationMenu ? styles.activeNotificationDiv : ""}`}>
<div
ref={notificationRef}
className={`${styles.notificationDiv} glassCard ${notificationMenu ? styles.activeNotificationDiv : ""}`}
>
{notifications.length === 0 ? (
<p>Vous n'avez aucune notification !</p>
) : (
notifications.map((notification, index) => (
<div className={styles.notification}>
<p key={index}>{notification}</p>
<div className={styles.notification} key={index}>
<p>{notification}</p>
<button
className={styles.closeBtn}
onClick={() => setNotifications(prev => prev.filter((_, i) => i !== index))}>
<svg width="auto" height="30" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg">
<svg xmlns="http://www.w3.org/2000/svg" height="50px" viewBox="0 -960 960 960" width="50px" fill="#000000"><path d="m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z"/></svg>
onClick={() => setNotifications(prev => prev.filter((_, i) => i !== index))}
>
<svg xmlns="http://www.w3.org/2000/svg" height="20px" viewBox="0 -960 960 960" width="20px">
<path d="m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z" />
</svg>
</button>
</div>
@@ -82,7 +123,7 @@ function Header(){
)}
</div>
</div>
)
);
}
export default Header;
+92 -17
View File
@@ -11,14 +11,48 @@
padding: 0.8rem;
height: fit-content;
z-index: 2;
position: relative;
justify-content: space-between;
}
.headerContent {
.activeHeaderContent {
display: flex;
justify-content: space-between;
width: 100%;
opacity: 1;
transition: opacity 0.3s ease;
pointer-events: auto;
}
.inactiveHeaderContent{
opacity: 0;
pointer-events: none;
transition: opacity 0.3s ease;
position: absolute;
top: 0.8rem;
left: 0.8rem;
}
.inactiveMobileMenu{
max-height: 0;
position: absolute;
top: 100%;
left: 0;
}
.activeMobileMenu{
transition: max-height 3s ease;
max-height: 500px;
display: flex;
flex-direction: column;
align-items: start;
gap: 0.5rem;
}
.headerLeftContent {
display: flex;
@@ -32,18 +66,24 @@
width: fit-content;
display: flex;
align-items: center;
gap: 1rem;
}
.logo {
height: 4rem;
width: auto;
flex-shrink: 0;
}
.logoLink{
.logoLink {
display: inline-flex;
align-items: center;
justify-content: center;
width: fit-content;
height: fit-content;
flex-shrink: 0;
}
.link {
color: #000000;
width: fit-content;
@@ -65,17 +105,10 @@
border-bottom: 2px solid #019AFF;
}
svg {
width: fit-content;
}
.bellBtn, .profileLink {
display: flex;
align-items: center;
@@ -122,8 +155,6 @@ svg {
}
.profileLink:hover {
transform: translateY(-4px);
background: rgba(191, 191, 191, 0.5);
@@ -132,8 +163,6 @@ svg {
}
}
.bellBtn svg {
height: 28px;
}
@@ -142,9 +171,6 @@ svg {
height: 40px;
}
.notificationDiv {
position: absolute;
width: 250px;
@@ -166,6 +192,8 @@ svg {
.notification{
margin-bottom: 7%;
display: flex;
justify-content: space-between;
align-items: center;
}
.notificationBadge {
@@ -195,3 +223,50 @@ svg {
.closeBtn:focus-visible {
outline: 2px solid black;
}
.burgerBtn {
flex-direction: column;
justify-content: space-between;
width: 30px;
height: 22px;
border: none;
cursor: pointer;
display: none;
z-index: 10;
}
.burgerBar {
width: 100%;
height: 3px;
background-color: #000000;
border-radius: 2px;
transition: all 0.3s ease;
}
.activeBurgerBtn .burgerBar:nth-child(1) {
transform: translateY(10px) rotate(45deg);
}
.activeBurgerBtn .burgerBar:nth-child(2) {
opacity: 0;
}
.activeBurgerBtn .burgerBar:nth-child(3) {
transform: translateY(-9px) rotate(-45deg);
}
.navLinks{
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
}
@media screen and (max-width: 768px) {
.navLinks {
display: none;
}
.burgerBtn {
display: flex;
}
}