AvatarMenu
avatarmenu-1779378817574.tsx
'use client'
import { useState, useRef, useEffect } from 'react'
const MENU_ITEMS = [
{ label: 'Profile', icon: '👤', shortcut: null, divider: false },
{ label: 'Saved components', icon: '❤️', shortcut: null, divider: false },
{ label: 'API keys', icon: '🔑', shortcut: null, divider: false },
{ label: 'Billing', icon: '💳', shortcut: null, divider: true },
{ label: 'Keyboard shortcuts', icon: '⌨️', shortcut: '?', divider: false },
{ label: 'Documentation', icon: '📄', shortcut: null, divider: false },
{ label: 'Sign out', icon: '→', shortcut: null, divider: true, danger: true },
]
export default function AvatarMenu() {
const [open, setOpen] = useState(false)
const [focused, setFocused] = useState(-1)
const ref = useRef<HTMLDivElement>(null)
useEffect(() => {
const handler = (e: MouseEvent) => { if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false) }
document.addEventListener('mousedown', handler)
return () => document.removeEventListener('mousedown', handler)
}, [])
useEffect(() => {
if (!open) { setFocused(-1); return }
const handler = (e: KeyboardEvent) => {
if (e.key === 'Escape') { setOpen(false); return }
if (e.key === 'ArrowDown') setFocused(f => Math.min(f + 1, MENU_ITEMS.length - 1))
if (e.key === 'ArrowUp') setFocused(f => Math.max(f - 1, 0))
}
document.addEventListener('keydown', handler)
return () => document.removeEventListener('keydown', handler)
}, [open])
return (
<div style={{ background: '#0A0A0A', display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: 300, padding: 40 }}>
<div ref={ref} style={{ position: 'relative' }}>
<button onClick={() => setOpen(o => !o)} style={{ width: 40, height: 40, borderRadius: '50%', background: 'linear-gradient(135deg, #C9A84C, #6366f1)', border: open ? '2px solid #C9A84C' : '2px solid transparent', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 800, color: '#0A0A0A', fontSize: 14, transition: 'border-color 0.2s' }}>
AK
</button>
<span style={{ position: 'absolute', bottom: 0, right: 0, width: 10, height: 10, background: '#22c55e', borderRadius: '50%', border: '2px solid #0A0A0A' }} />
{open && (
<div style={{ position: 'absolute', top: 'calc(100% + 10px)', right: 0, width: 220, background: '#111', border: '1px solid rgba(255,255,255,0.1)', borderRadius: 12, overflow: 'hidden', boxShadow: '0 16px 48px rgba(0,0,0,0.6)', animation: 'dropDown 0.15s ease', zIndex: 9999 }}>
{/* Header */}
<div style={{ padding: '14px 16px', borderBottom: '1px solid rgba(255,255,255,0.06)' }}>
<div style={{ color: '#F5F5F0', fontSize: 14, fontWeight: 600 }}>Alex Kowalski</div>
<div style={{ color: 'rgba(255,255,255,0.4)', fontSize: 12, marginTop: 2 }}>alex@lemon.io</div>
<div style={{ marginTop: 8, display: 'inline-flex', background: 'rgba(201,168,76,0.12)', border: '1px solid rgba(201,168,76,0.25)', color: '#C9A84C', padding: '2px 8px', borderRadius: 12, fontSize: 11, fontWeight: 600 }}>Pro</div>
</div>
{/* Items */}
<div style={{ padding: '6px 0' }}>
{MENU_ITEMS.map((item, i) => (
<div key={item.label}>
{item.divider && i > 0 && <div style={{ height: 1, background: 'rgba(255,255,255,0.05)', margin: '4px 0' }} />}
<button onClick={() => setOpen(false)} style={{
width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'space-between',
padding: '8px 14px', background: focused === i ? 'rgba(255,255,255,0.05)' : 'transparent',
border: 'none', cursor: 'pointer', textAlign: 'left', transition: 'background 0.1s',
}} onMouseEnter={() => setFocused(i)} onMouseLeave={() => setFocused(-1)}>
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
<span style={{ fontSize: 14, width: 18 }}>{item.icon}</span>
<span style={{ color: (item as any).danger ? '#ef4444' : '#F5F5F0', fontSize: 13 }}>{item.label}</span>
</div>
{item.shortcut && <kbd style={{ background: 'rgba(255,255,255,0.08)', color: 'rgba(255,255,255,0.4)', border: '1px solid rgba(255,255,255,0.12)', borderRadius: 4, padding: '1px 5px', fontSize: 10 }}>{item.shortcut}</kbd>}
</button>
</div>
))}
</div>
</div>
)}
</div>
<style>{`@keyframes dropDown { from { opacity:0; transform:translateY(-6px) } to { opacity:1; transform:translateY(0) } }`}</style>
</div>
)
}Component info
CategoryNavigation
Frameworkreact
TierFREE
Views0
Copies0
About
User avatar dropdown menu with keyboard navigation, profile info, shortcuts, and sign out
More from Navigation
import * as React from 'react';
import * as ReactDOM from 'react-dom';
interface FloatingDockProps {
icons: { id: number; src: string; }[];
}
class FloatingDock extends React.Component<FloatingDockProps, {}> {
constructor(props: FloatingDockProFloatingDock
Navigation
'use client'
import { useState } from 'react'
const NAV = [
{ id: 'home', icon: '◉', label: 'Overview', shortcut: 'G H' },
{ id: 'components', icon: '⬡', label: 'Components', shortcut: 'G C', badge: 120, children: [
{ id: 'buttons', label: 'SidebarNav
Navigation
'use client';
import React from 'react';
interface PaginationNavProps {
currentPage: number;
totalPages: number;
onPageChange: (page: number) => void;
}
const PaginationNav: React.FC<PaginationNavProps> = ({ currentPage, totalPages, onPageChPaginationNav
Navigation
'use client';
import React, { useState } from 'react';
interface Tab {
id: number;
label: string;
}
const tabs: Tab[] = [
{ id: 1, label: 'Tab 1' },
{ id: 2, label: 'Tab 2' },
{ id: 3, label: 'Tab 3' },
{ id: 4, label: 'Tab 4' },
];
cTabsNav
Navigation