Something went wrong. Try again.
FlockOff is a mass-block tool for the Atmosphere flockoff.app
Something went wrong. Try again.
2.0 kB · 62 lines
TSX
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263'use client'
import { useState, useRef, useEffect } from 'react'import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
interface UserMenuProps { handle?: string avatar?: string}
export function UserMenu({ handle, avatar }: UserMenuProps) { const [open, setOpen] = useState(false) const ref = useRef<HTMLDivElement>(null)
useEffect(() => { function handleOutsideClick(e: MouseEvent) { if (ref.current && !ref.current.contains(e.target as Node)) { setOpen(false) } } document.addEventListener('mousedown', handleOutsideClick) return () => document.removeEventListener('mousedown', handleOutsideClick) }, [])
const initials = handle?.charAt(0).toUpperCase() ?? '?'
return ( <div ref={ref} className="relative"> <button onClick={() => setOpen((prev) => !prev)} className="rounded-full ring-2 ring-transparent hover:ring-border focus:ring-border transition-all outline-none" aria-label="Account menu" > <Avatar className="h-8 w-8"> <AvatarImage src={avatar} alt={handle ? `@${handle}` : 'Account'} /> <AvatarFallback className="text-xs bg-[var(--fo-ember)] text-white">{initials}</AvatarFallback> </Avatar> </button>
{open && ( <div className="absolute right-0 top-10 w-52 bg-card border border-border rounded-lg shadow-lg overflow-hidden z-50"> {/* Identity */} <div className="px-3 py-2.5 border-b border-border"> <p className="text-sm font-medium truncate"> {handle ? `@${handle}` : 'Account'} </p> </div>
{/* Sign out */} <form action="/api/oauth/logout" method="POST"> <button type="submit" className="w-full text-left px-3 py-2 text-sm hover:bg-muted transition-colors" > Sign out </button> </form> </div> )} </div> )}