Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | import React from 'react';
import { Link, useLocation } from 'react-router-dom';
import { X, LogOut } from 'lucide-react';
import Button from './Button';
interface SidebarProps {
isOpen: boolean;
onClose: () => void;
}
const navigation = [
{ name: 'Dashboard', path: '/dashboard', icon: '📊' },
{ name: 'Projects', path: '/projects', icon: '📁' },
{ name: 'Analytics', path: '/analytics', icon: '📈' },
{ name: 'Settings', path: '/settings', icon: '⚙️' },
{ name: 'Profile', path: '/profile', icon: '👤' },
];
const Sidebar: React.FC<SidebarProps> = ({ isOpen, onClose }) => {
const location = useLocation();
return (
<>
{/* Mobile Overlay */}
{isOpen && (
<div
className="fixed inset-0 bg-oxford-blue bg-opacity-50 lg:hidden z-30"
onClick={onClose}
aria-hidden="true"
/>
)}
{/* Sidebar */}
<aside
className={`fixed left-0 top-0 h-full w-64 bg-gradient-to-b from-oxford-blue to-sea-green border-r border-neon-blue border-opacity-20 transform transition-transform duration-300 ease-in-out z-40 lg:translate-x-0 ${isOpen ? 'translate-x-0' : '-translate-x-full'
}`}
aria-label="Main navigation"
>
{/* Logo */}
<div className="p-6 border-b border-neon-blue border-opacity-20">
<h1 className="text-2xl font-bold text-transparent bg-clip-text bg-gradient-right">
🚀 Heimdall
</h1>
<p className="text-sm text-french-gray mt-1">Analytics Platform</p>
</div>
{/* Navigation */}
<nav className="p-4 flex-1" aria-label="Primary navigation">
{navigation.map((item) => {
const isActive = location.pathname === item.path;
return (
<Link
key={item.path}
to={item.path}
className={`flex items-center gap-3 px-4 py-3 rounded-lg mb-2 transition-all duration-200 ${isActive
? 'bg-neon-blue bg-opacity-20 text-light-green border border-light-green border-opacity-50'
: 'text-french-gray hover:bg-sea-green hover:bg-opacity-10 hover:text-light-green'
}`}
aria-current={isActive ? 'page' : undefined}
>
<span className="text-lg" aria-hidden="true">{item.icon}</span>
<span className="font-medium">{item.name}</span>
</Link>
);
})}
</nav>
{/* Footer */}
<div className="p-4 border-t border-neon-blue border-opacity-20">
<Button
variant="danger"
size="sm"
className="w-full flex items-center justify-center gap-2"
aria-label="Logout from application"
>
<LogOut size={16} aria-hidden="true" />
Logout
</Button>
</div>
</aside>
{/* Close Button for Mobile */}
{isOpen && (
<button
onClick={onClose}
className="fixed top-4 right-4 lg:hidden z-50 p-2 bg-neon-blue rounded-lg"
aria-label="Close navigation menu"
>
<X size={24} aria-hidden="true" />
</button>
)}
</>
);
};
export default Sidebar;
|