Files
SkinbaseNova/resources/js/components/Topbar.jsx
2026-03-17 18:34:26 +01:00

78 lines
3.7 KiB
JavaScript

import React, { useState } from 'react'
import SearchBar from '../Search/SearchBar'
const DEFAULT_AVATAR = 'https://files.skinbase.org/default/avatar_default.webp'
export default function Topbar({ user = null }) {
const [menuOpen, setMenuOpen] = useState(false)
return (
<header className="fixed top-0 left-0 right-0 h-16 bg-neutral-900 border-b border-neutral-800 z-50">
<div className="h-full px-5 flex items-center justify-between gap-4">
<div className="flex items-center gap-4">
<button aria-label="Toggle menu" className="md:hidden text-neutral-200 hover:text-sky-400">
<i className="fas fa-bars text-lg" aria-hidden="true"></i>
</button>
<a href="/" className="text-sky-400 font-semibold text-xl">Skinbase</a>
</div>
<div className="hidden md:block flex-1 max-w-xl">
<SearchBar />
</div>
<div className="flex items-center gap-3 sm:gap-4">
<a href="/community/activity" className="hidden sm:inline text-sm text-neutral-300 hover:text-sky-400 transition-colors">Community</a>
<a href="/forum" className="hidden sm:inline text-sm text-neutral-300 hover:text-sky-400 transition-colors">Forum</a>
{user ? (
<div className="relative">
<button
onClick={() => setMenuOpen(o => !o)}
className="flex items-center gap-2 rounded-lg px-2 py-1 hover:bg-white/5 transition-colors"
aria-label="User menu"
>
<img
src={user.avatarUrl || DEFAULT_AVATAR}
alt={user.displayName}
className="w-7 h-7 rounded-full object-cover ring-1 ring-white/10"
onError={(e) => { e.currentTarget.src = DEFAULT_AVATAR }}
/>
<span className="hidden sm:inline text-sm text-white/90">{user.displayName}</span>
<i className="fas fa-chevron-down text-xs text-white/50" aria-hidden="true"></i>
</button>
{menuOpen && (
<div className="absolute right-0 mt-2 w-48 rounded-lg bg-neutral-800 border border-neutral-700 shadow-xl overflow-hidden z-50">
<a href={`/@${user.username}`} className="flex items-center gap-2 px-4 py-2 text-sm hover:bg-white/5">
<img
src={user.avatarUrl || DEFAULT_AVATAR}
alt={user.displayName}
className="w-6 h-6 rounded-full object-cover"
onError={(e) => { e.currentTarget.src = DEFAULT_AVATAR }}
/>
<span className="truncate">{user.displayName}</span>
</a>
<div className="border-t border-neutral-700" />
<a href={user.uploadUrl} className="block px-4 py-2 text-sm hover:bg-white/5">Upload</a>
<a href="/studio/artworks" className="block px-4 py-2 text-sm hover:bg-white/5">Studio</a>
<a href="/dashboard" className="block px-4 py-2 text-sm hover:bg-white/5">Dashboard</a>
<div className="border-t border-neutral-700" />
<a href="/logout" className="block px-4 py-2 text-sm text-red-400 hover:bg-white/5"
onClick={(e) => { e.preventDefault(); document.getElementById('logout-form')?.submit() }}>
Sign out
</a>
</div>
)}
</div>
) : (
<a href="/login" className="text-sm text-neutral-300 hover:text-sky-400 transition-colors">
<i className="fas fa-user" aria-hidden="true"></i>
</a>
)}
</div>
</div>
</header>
)
}