← Components/Navigation

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: FloatingDockPro
FloatingDock
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, onPageCh
PaginationNav
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' },
];

c
TabsNav
Navigation