| import { NavLink, Link } from 'react-router-dom' |
| import { |
| Home, |
| MapPin, |
| SlidersHorizontal, |
| Banknote, |
| Settings, |
| X, |
| } from 'lucide-react' |
|
|
| const NAV_ITEMS = [ |
| { to: '/', label: 'Home', icon: Home, tourId: 'nav-home' }, |
| { to: '/zones', label: 'Neighborhoods', icon: MapPin, tourId: 'nav-zones' }, |
| { to: '/calibrate', label: 'Coverage', icon: SlidersHorizontal, tourId: 'nav-calibrate' }, |
| { to: '/disbursements', label: 'Disbursements', icon: Banknote, tourId: 'nav-disbursements' }, |
| { to: '/pipeline', label: 'How it works', icon: Settings, tourId: 'nav-pipeline' }, |
| ] |
|
|
| interface Props { |
| open: boolean |
| onClose: () => void |
| } |
|
|
| export default function Sidebar({ open, onClose }: Props) { |
| return ( |
| <> |
| {open && ( |
| <div |
| className="fixed inset-0 z-40 lg:hidden" |
| style={{ background: 'rgba(27, 30, 45, 0.4)' }} |
| onClick={onClose} |
| /> |
| )} |
| |
| <aside |
| className={` |
| fixed top-0 left-0 z-50 h-full w-56 |
| flex flex-col transition-transform duration-200 ease-in-out |
| lg:translate-x-0 |
| ${open ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'} |
| `} |
| style={{ background: '#1b1e2d' }} |
| > |
| {/* Brand */} |
| <div |
| className="flex items-center justify-between h-16 px-5" |
| style={{ borderBottom: '1px solid rgba(255,255,255,0.06)' }} |
| > |
| <Link to="/" className="flex items-baseline gap-2 no-underline"> |
| <span |
| style={{ |
| fontFamily: '"Source Serif 4", Georgia, serif', |
| fontSize: '18px', |
| fontWeight: 400, |
| color: '#fcfaf7', |
| letterSpacing: '-0.005em', |
| }} |
| > |
| Heat insurance |
| </span> |
| </Link> |
| <button |
| onClick={onClose} |
| aria-label="Close navigation menu" |
| className="lg:hidden p-1" |
| style={{ color: '#8d909e', background: 'none', border: 'none' }} |
| > |
| <X size={18} /> |
| </button> |
| </div> |
| |
| {/* Navigation */} |
| <nav className="flex-1 py-4 overflow-y-auto"> |
| {NAV_ITEMS.map(({ to, label, icon: Icon, tourId }) => ( |
| <NavLink |
| key={to} |
| to={to} |
| end={to === '/'} |
| data-tour={tourId} |
| onClick={onClose} |
| className="sidebar-link" |
| > |
| <Icon size={16} style={{ flexShrink: 0 }} /> |
| <span>{label}</span> |
| </NavLink> |
| ))} |
| </nav> |
| |
| <div |
| style={{ |
| padding: '12px 20px', |
| borderTop: '1px solid rgba(255,255,255,0.06)', |
| fontFamily: '"Space Grotesk", system-ui, sans-serif', |
| fontSize: '10px', |
| fontWeight: 500, |
| letterSpacing: '0.04em', |
| color: '#8d909e', |
| }} |
| > |
| Worker personas are simulated |
| </div> |
| |
| </aside> |
| |
| <style>{` |
| .sidebar-link { |
| display: flex; |
| align-items: center; |
| gap: 12px; |
| padding: 10px 20px; |
| font-family: "Space Grotesk", system-ui, sans-serif; |
| font-size: 13px; |
| font-weight: 500; |
| color: #8d909e; |
| border-left: 2px solid transparent; |
| text-decoration: none; |
| transition: color 0.15s ease, border-color 0.15s ease; |
| } |
| .sidebar-link:hover { |
| color: #fcfaf7; |
| } |
| .sidebar-link.active { |
| color: #fcfaf7; |
| border-left-color: #8a3d28; |
| } |
| `}</style> |
| </> |
| ) |
| } |
|
|