/
aaronair
/
Test_task_rt_solution
Обзор
Документация
Войти
/
aaronair
/
Test_task_rt_solution
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/components/NavDropdown.tsx
76 строк
2 KB
Ilikedrinkpivo
first_commit
28 май 2026, 14:51
28 май 2026, 14:51
b4498fc
Код
Авторство
О чём код?
import { useEffect, useRef, useState } from "react"; import { NavLink } from "react-router-dom"; import { cn } from "@/lib/cn"; interface Item { to: string; label: string; } interface Props { label: string; items: Item[]; } export function NavDropdown({ label, items }: Props) { const [open, setOpen] = useState(false); const ref = useRef<HTMLDivElement>(null); useEffect(() => { if (!open) return; function onClick(e: MouseEvent) { if (ref.current && !ref.current.contains(e.target as Node)) { setOpen(false); } } document.addEventListener("mousedown", onClick); return () => document.removeEventListener("mousedown", onClick); }, [open]); return ( <div ref={ref} className="relative"> <button type="button" onClick={() => setOpen((p) => !p)} className={cn( "px-3 py-2 rounded-lg text-sm font-medium transition-colors inline-flex items-center gap-1", open ? "bg-primary-50 text-primary-700" : "text-ink-700 hover:bg-surface-muted", )} aria-expanded={open} aria-haspopup="true" > {label} <svg viewBox="0 0 12 12" className="h-3 w-3" aria-hidden> <path d="m2 4 4 4 4-4" fill="none" stroke="currentColor" strokeWidth="1.5" /> </svg> </button> {open && ( <div role="menu" className="absolute top-full left-0 mt-1 min-w-[12rem] rounded-lg border border-ink-300/60 bg-surface-card shadow-cardHover py-1 z-50" > {items.map((item) => ( <NavLink key={item.to} to={item.to} role="menuitem" className={({ isActive }) => cn( "block px-3 py-2 text-sm transition-colors", isActive ? "bg-primary-50 text-primary-700 font-medium" : "text-ink-700 hover:bg-surface-muted", ) } onClick={() => setOpen(false)} > {item.label} </NavLink> ))} </div> )} </div> ); }