- dark: 클래스를 class 기반으로 전환 (다크모드 비활성화) - color-scheme: light 강제 - surface 색상 토큰 추가 (카드/패널용) - 리스트/사이드바 배경 bg-surface로 통일 - 텍스트 대비 강화 (gray-400 → gray-500/700) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
61 lines
2.1 KiB
TypeScript
61 lines
2.1 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import { createPortal } from "react-dom";
|
|
import { GoogleLogin } from "@react-oauth/google";
|
|
|
|
interface LoginMenuProps {
|
|
onGoogleSuccess: (credential: string) => void;
|
|
}
|
|
|
|
export default function LoginMenu({ onGoogleSuccess }: LoginMenuProps) {
|
|
const [open, setOpen] = useState(false);
|
|
|
|
return (
|
|
<>
|
|
<button
|
|
onClick={() => setOpen(true)}
|
|
className="px-3 py-1.5 text-sm font-medium text-gray-600 dark:text-gray-300 hover:text-brand-600 dark:hover:text-brand-400 border border-gray-300 dark:border-gray-600 hover:border-brand-400 dark:hover:border-brand-500 rounded-lg transition-colors"
|
|
>
|
|
로그인
|
|
</button>
|
|
|
|
{open && createPortal(
|
|
<div
|
|
className="fixed inset-0 flex items-center justify-center bg-black/40 backdrop-blur-sm"
|
|
style={{ zIndex: 99999 }}
|
|
onClick={(e) => { if (e.target === e.currentTarget) setOpen(false); }}
|
|
>
|
|
<div className="bg-surface rounded-2xl shadow-2xl p-6 mx-4 w-full max-w-xs space-y-4">
|
|
<div className="flex items-center justify-between">
|
|
<h3 className="text-base font-semibold dark:text-gray-100">로그인</h3>
|
|
<button
|
|
onClick={() => setOpen(false)}
|
|
className="text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 text-lg leading-none"
|
|
>
|
|
✕
|
|
</button>
|
|
</div>
|
|
<p className="text-xs text-gray-400 dark:text-gray-500">소셜 계정으로 간편 로그인</p>
|
|
<div className="flex flex-col items-center gap-3">
|
|
<GoogleLogin
|
|
onSuccess={(res) => {
|
|
if (res.credential) {
|
|
onGoogleSuccess(res.credential);
|
|
setOpen(false);
|
|
}
|
|
}}
|
|
onError={() => console.error("Google login failed")}
|
|
size="large"
|
|
width="260"
|
|
text="signin_with"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>,
|
|
document.body,
|
|
)}
|
|
</>
|
|
);
|
|
}
|