From d2f73327011573024eec5cb18b575761b6224e8c Mon Sep 17 00:00:00 2001 From: Kirko Date: Sat, 25 Apr 2026 13:10:10 +0300 Subject: [PATCH] feat: user dropdown in Header with theme picker and logout Replace static logout button with a dropdown triggered by clicking the username badge. Dropdown shows accent color presets and a logout button. Co-Authored-By: Claude Sonnet 4.6 --- apps/web/src/components/Header.tsx | 99 +++++++++++++++++++++++++----- 1 file changed, 83 insertions(+), 16 deletions(-) diff --git a/apps/web/src/components/Header.tsx b/apps/web/src/components/Header.tsx index e2ee817..eb6cb8a 100644 --- a/apps/web/src/components/Header.tsx +++ b/apps/web/src/components/Header.tsx @@ -1,15 +1,31 @@ -'use client' +'use client' import Link from 'next/link' import { usePathname, useRouter } from 'next/navigation' +import { useRef, useState, useEffect } from 'react' import { useAuthStore } from '@/store/authStore' +import { useThemeStore, ACCENT_PRESETS } from '@/store/themeStore' export default function Header() { const { user, clearAuth } = useAuthStore() + const { accentIdx, setAccent } = useThemeStore() const router = useRouter() const pathname = usePathname() + const [open, setOpen] = useState(false) + const dropdownRef = useRef(null) + + useEffect(() => { + const handler = (e: MouseEvent) => { + if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) { + setOpen(false) + } + } + if (open) document.addEventListener('mousedown', handler) + return () => document.removeEventListener('mousedown', handler) + }, [open]) const handleLogout = () => { + setOpen(false) clearAuth() router.push('/') } @@ -68,25 +84,76 @@ export default function Header() { )} -
-
- - {user.username[0].toUpperCase()} - -
- {user.username} + + {/* User badge with dropdown */} +
+ + {open && ( +
+ {/* Theme section */} +
+

+ Цвет темы +

+
+ {ACCENT_PRESETS.map((preset, i) => ( + + ))} +
+
+ +
+ + {/* Logout */} + +
+ )}
) : (