nnuer
강희태@gmlxo9917

빛 번짐 테두리가 있는 소셜 + 이메일 로그인 카드

로그인/가입 블록

카드 뒤로 초록빛이 번지는 로그인 화면입니다. Google로 계속하기, 구분선, 이메일과 비밀번호 입력, 빈칸 오류 안내, 로딩 상태, 회원가입 안내가 있습니다.

#light#login#form#google#glow2026. 10. 16. 업데이트

블록 신고

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

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

export default function PlantShopLogin() {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [error, setError] = useState<string | null>(null);
  const [pending, setPending] = useState(false);

  return (
    <section className="w-full bg-stone-50 px-4 py-16 text-stone-900 sm:py-24">
      <div className="relative mx-auto max-w-[400px]">
        <div aria-hidden className="absolute -inset-px -z-0 rounded-[22px] bg-gradient-to-b from-emerald-400/50 via-lime-300/20 to-transparent blur-xl" />
        <div className="relative rounded-[20px] border border-stone-200 bg-white/95 p-8 text-center shadow-xl shadow-emerald-900/10 backdrop-blur">
          <div className="flex justify-center">
            <span className="flex h-10 w-10 items-center justify-center rounded-xl bg-gradient-to-br from-emerald-500 to-lime-400 text-white" aria-hidden>
              <svg width="20" height="20" viewBox="0 0 24 24" fill="none">
                <path d="M12 21V11M12 11c0-4 3-7 8-7 0 5-3 7-8 7ZM12 14c0-3-2.5-5.5-7-5.5 0 4 2.5 5.5 7 5.5Z" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
            </span>
          </div>
          <h1 className="mt-6 text-2xl font-semibold tracking-tight">Bloomly에 로그인</h1>
          <p className="mt-2 text-sm text-stone-500">찜한 식물과 주문 내역을 보려면 로그인하세요.</p>

          <button
            type="button"
            className="mt-6 flex h-11 w-full items-center justify-center gap-2.5 rounded-xl border border-stone-200 bg-white text-sm font-medium transition hover:border-stone-300 hover:bg-stone-50 active:scale-[0.99]"
          >
            <svg width="18" height="18" viewBox="0 0 48 48" aria-hidden>
              <path fill="#FFC107" d="M43.6 20.5H42V20H24v8h11.3C33.7 32.7 29.3 36 24 36c-6.6 0-12-5.4-12-12s5.4-12 12-12c3 0 5.8 1.1 7.9 3l5.7-5.7C34 6.1 29.3 4 24 4 12.9 4 4 12.9 4 24s8.9 20 20 20 20-8.9 20-20c0-1.3-.1-2.4-.4-3.5Z" />
              <path fill="#FF3D00" d="m6.3 14.7 6.6 4.8C14.7 15.1 19 12 24 12c3 0 5.8 1.1 7.9 3l5.7-5.7C34 6.1 29.3 4 24 4 16.3 4 9.7 8.3 6.3 14.7Z" />
              <path fill="#4CAF50" d="M24 44c5.2 0 9.9-2 13.4-5.2l-6.2-5.2C29.2 35.1 26.7 36 24 36c-5.2 0-9.6-3.3-11.3-8l-6.5 5C9.5 39.6 16.2 44 24 44Z" />
              <path fill="#1976D2" d="M43.6 20.5H42V20H24v8h11.3c-.8 2.2-2.2 4.2-4.1 5.6l6.2 5.2C37 39.2 44 34 44 24c0-1.3-.1-2.4-.4-3.5Z" />
            </svg>
            Google로 계속하기
          </button>

          <div className="my-5 flex items-center gap-3 text-xs text-stone-400">
            <span className="h-px flex-1 bg-stone-200" />
            또는 이메일로
            <span className="h-px flex-1 bg-stone-200" />
          </div>

          <form
            className="space-y-3 text-left"
            onSubmit={(e) => {
              e.preventDefault();
              if (!email.trim() || !password) {
                setError("이메일과 비밀번호를 모두 입력해 주세요.");
                return;
              }
              setError(null);
              setPending(true);
              setTimeout(() => setPending(false), 1200);
            }}
          >
            <div>
              <label htmlFor="login-email" className="mb-1.5 block text-[13px] font-medium text-stone-600">
                이메일
              </label>
              <input
                id="login-email"
                type="email"
                autoComplete="email"
                value={email}
                onChange={(e) => setEmail(e.target.value)}
                placeholder="you@example.com"
                className="h-11 w-full rounded-xl border border-stone-200 px-3.5 text-sm outline-none transition placeholder:text-stone-400 focus:border-emerald-500 focus:ring-4 focus:ring-emerald-100"
              />
            </div>
            <div>
              <div className="mb-1.5 flex items-center justify-between">
                <label htmlFor="login-password" className="text-[13px] font-medium text-stone-600">
                  비밀번호
                </label>
                <a href="#" className="text-xs text-stone-500 hover:text-emerald-700">
                  비밀번호를 잊었어요
                </a>
              </div>
              <input
                id="login-password"
                type="password"
                autoComplete="current-password"
                value={password}
                onChange={(e) => setPassword(e.target.value)}
                className="h-11 w-full rounded-xl border border-stone-200 px-3.5 text-sm outline-none transition focus:border-emerald-500 focus:ring-4 focus:ring-emerald-100"
              />
            </div>
            {error && (
              <p role="alert" className="rounded-lg border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-600">
                {error}
              </p>
            )}
            <button
              type="submit"
              disabled={pending}
              className="h-11 w-full rounded-xl bg-emerald-600 text-sm font-semibold text-white transition hover:bg-emerald-700 active:scale-[0.99] disabled:opacity-60"
            >
              {pending ? "로그인하는 중..." : "로그인"}
            </button>
          </form>
        </div>
        <p className="relative mt-6 text-center text-xs text-stone-500">
          처음이신가요? <a href="#" className="font-medium text-emerald-700 hover:underline">회원가입</a>하고 첫 주문 무료 배송을 받으세요.
        </p>
      </div>
    </section>
  );
}

적용 사이트 0

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

로그인하고 내 사이트 추가

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

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

재현 후기

v1 · 0개

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