evg_ultimate_team / frontend /src /components /layout /BottomNavigation.tsx
clementpep's picture
feat: add bottom nav bar and improve responsive design
cddecd3
/**
* BottomNavigation Component - Mobile navigation bar
*
* Fixed bottom navigation for mobile devices (< md breakpoint - 768px)
* Features:
* - 4 navigation items: Home, Team, Challenges, Packs
* - Icons from react-icons/io5
* - Active state indicator with gold highlight
* - PSG/FIFA themed styling
* - Accessible with proper ARIA labels
*/
import React from 'react';
import { Link, useLocation } from 'react-router-dom';
import { IoHome, IoPeople, IoTrophy, IoGift } from 'react-icons/io5';
import clsx from 'clsx';
interface NavItemConfig {
to: string;
icon: React.ComponentType<{ className?: string }>;
label: string;
ariaLabel: string;
}
export const BottomNavigation: React.FC = () => {
const location = useLocation();
const navItems: NavItemConfig[] = [
{
to: '/',
icon: IoHome,
label: 'Accueil',
ariaLabel: "Aller à l'accueil",
},
{
to: '/team',
icon: IoPeople,
label: 'Team',
ariaLabel: "Voir l'équipe",
},
{
to: '/challenges',
icon: IoTrophy,
label: 'Défis',
ariaLabel: 'Voir les défis',
},
{
to: '/packs',
icon: IoGift,
label: 'Packs',
ariaLabel: 'Voir les packs',
},
];
const isActive = (path: string) => {
return location.pathname === path;
};
return (
<nav
className="fixed bottom-0 left-0 right-0 z-40 md:hidden"
style={{
background: 'rgba(10, 22, 40, 0.95)',
borderTop: '1px solid rgba(255, 255, 255, 0.1)',
backdropFilter: 'blur(10px)',
WebkitBackdropFilter: 'blur(10px)',
}}
role="navigation"
aria-label="Navigation principale mobile"
>
<div className="flex items-center justify-around h-16 px-2">
{navItems.map(({ to, icon: Icon, label, ariaLabel }) => {
const active = isActive(to);
return (
<Link
key={to}
to={to}
className={clsx(
'relative flex flex-col items-center justify-center',
'min-w-[60px] h-full px-3 py-1',
'transition-all duration-200',
'focus:outline-none focus:ring-2 focus:ring-fifa-gold focus:ring-inset',
'rounded-lg',
active ? 'text-fifa-gold' : 'text-white/70'
)}
aria-label={ariaLabel}
aria-current={active ? 'page' : undefined}
>
{/* Icon */}
<Icon
className={clsx(
'text-2xl mb-1 transition-all duration-200',
active && 'drop-shadow-[0_0_8px_rgba(212,175,55,0.8)]'
)}
/>
{/* Label */}
<span
className={clsx(
'text-[10px] font-semibold uppercase tracking-wide transition-all duration-200',
active && 'text-fifa-gold'
)}
>
{label}
</span>
{/* Active indicator */}
{active && (
<div
className="absolute bottom-0 left-1/2 -translate-x-1/2 w-8 h-1 rounded-t-full"
style={{
background: 'linear-gradient(135deg, #D4AF37 0%, #FFD700 100%)',
boxShadow: '0 -2px 10px rgba(212, 175, 55, 0.6)',
}}
/>
)}
</Link>
);
})}
</div>
{/* Safe area for iPhone notch */}
<div className="h-[env(safe-area-inset-bottom)]" style={{ background: 'inherit' }} />
</nav>
);
};