nnuer
강희태@gmlxo9917

아바타를 누르면 열리는 계정 메뉴가 있는 상단 헤더

내비게이션 블록

로고, 메뉴, 새 문서 버튼, 아바타가 있는 헤더 바입니다. 아바타를 누르면 이름과 이메일, 메뉴 항목, 로그아웃이 있는 드롭다운이 열리고 바깥을 누르거나 Esc로 닫힙니다.

블록 신고

운영자가 확인한 뒤 필요하면 블록을 숨깁니다.

사유
Claude Code · claude-opus-5-5 · React (TSX)
결과 코드펼치기
import { useEffect, useRef, useState } from "react";

export default function HeaderAccountMenu() {
  const [open, setOpen] = useState(false);
  const [signedOut, setSignedOut] = useState(false);
  const root = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (!open) return;
    const onPointer = (e: PointerEvent) => {
      if (root.current && !root.current.contains(e.target as Node)) setOpen(false);
    };
    const onKey = (e: KeyboardEvent) => e.key === "Escape" && setOpen(false);
    document.addEventListener("pointerdown", onPointer);
    document.addEventListener("keydown", onKey);
    return () => {
      document.removeEventListener("pointerdown", onPointer);
      document.removeEventListener("keydown", onKey);
    };
  }, [open]);

  const item = "block w-full rounded-md px-3 py-2 text-left text-zinc-400 transition-colors hover:bg-zinc-700/60 hover:text-zinc-100";

  return (
    <section className="w-full bg-zinc-950 px-4 pb-72 pt-8 text-zinc-100 sm:px-8">
      <header className="mx-auto flex h-14 max-w-6xl items-center gap-3 rounded-xl border border-zinc-800 bg-zinc-900/70 px-4 backdrop-blur">
        <span className="flex items-center gap-2 font-semibold tracking-tight">
          <span className="flex h-6 w-6 items-center justify-center rounded-md bg-lime-400 text-[13px] font-bold text-zinc-900" aria-hidden>
            F
          </span>
          Fieldnote
        </span>
        <nav aria-label="주요 메뉴" className="ml-6 hidden gap-1 text-sm text-zinc-400 md:flex">
          {["문서", "템플릿", "공유됨"].map((n, i) => (
            <a key={n} href="#" className={`rounded-md px-3 py-1.5 transition-colors hover:text-zinc-100 ${i === 0 ? "bg-zinc-800 text-zinc-100" : ""}`}>
              {n}
            </a>
          ))}
        </nav>
        <div className="ml-auto flex items-center gap-2">
          <a href="#" className="hidden h-8 items-center gap-1.5 rounded-lg bg-zinc-100 px-3 text-[13px] font-medium text-zinc-900 hover:bg-white sm:flex">
            <svg width="14" height="14" viewBox="0 0 16 16" fill="none" aria-hidden>
              <path d="M8 3v10M3 8h10" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" />
            </svg>
            새 문서
          </a>
          {signedOut ? (
            <button type="button" onClick={() => setSignedOut(false)} className="h-8 rounded-lg border border-zinc-700 px-3 text-[13px] hover:bg-zinc-800">
              로그인
            </button>
          ) : (
            <div ref={root} className="relative">
              <button
                type="button"
                aria-label="계정 메뉴"
                aria-haspopup="menu"
                aria-expanded={open}
                onClick={() => setOpen((v) => !v)}
                className="flex items-center rounded-full ring-2 ring-transparent transition hover:ring-zinc-600"
              >
                <span className="flex h-8 w-8 items-center justify-center rounded-full bg-gradient-to-br from-lime-400 to-emerald-500 text-[13px] font-semibold text-zinc-900">
                  하
                </span>
              </button>
              {open && (
                <div role="menu" className="absolute right-0 z-10 mt-2 w-56 overflow-hidden rounded-xl border border-zinc-700 bg-zinc-800 p-1.5 text-sm shadow-2xl shadow-black/50">
                  <div className="px-3 py-2">
                    <div className="truncate font-medium">한지우</div>
                    <div className="truncate text-xs text-zinc-500">jiwoo@fieldnote.app</div>
                  </div>
                  <div className="my-1 h-px bg-zinc-700" />
                  {["내 프로필", "내 문서", "즐겨찾기", "설정"].map((m) => (
                    <a key={m} role="menuitem" href="#" className={item} onClick={() => setOpen(false)}>
                      {m}
                    </a>
                  ))}
                  <div className="my-1 h-px bg-zinc-700" />
                  <button
                    role="menuitem"
                    type="button"
                    className={item}
                    onClick={() => {
                      setOpen(false);
                      setSignedOut(true);
                    }}
                  >
                    로그아웃
                  </button>
                </div>
              )}
            </div>
          )}
        </div>
      </header>
    </section>
  );
}

적용 사이트 0

이 블록이 실제로 쓰인 사이트입니다.

로그인하고 내 사이트 추가

아직 등록된 사이트가 없습니다. 이 블록을 쓴 사이트가 있다면 알려 주세요.

로그인하고 재현 결과 올리기

재현 후기

v1 · 0개

아직 이 버전의 프롬프트로 직접 만들어 본 사람이 없습니다. 첫 번째로 재현해 보세요.