feat(login): add password show/hide (eye) toggle on login form
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
7316cd99c5
commit
55a3114141
@ -31,6 +31,7 @@ export function LoginPage() {
|
|||||||
const [phase, setPhase] = useState<Phase>('login');
|
const [phase, setPhase] = useState<Phase>('login');
|
||||||
const [email, setEmail] = useState('');
|
const [email, setEmail] = useState('');
|
||||||
const [password, setPassword] = useState('');
|
const [password, setPassword] = useState('');
|
||||||
|
const [showPw, setShowPw] = useState(false);
|
||||||
const [remember, setRemember] = useState(false);
|
const [remember, setRemember] = useState(false);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [submitting, setSubmitting] = useState(false);
|
const [submitting, setSubmitting] = useState(false);
|
||||||
@ -157,15 +158,39 @@ export function LoginPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="kx-field">
|
<div className="kx-field">
|
||||||
<label htmlFor="password">{t('login.password')}</label>
|
<label htmlFor="password">{t('login.password')}</label>
|
||||||
<input
|
<div className="kx-field__pw">
|
||||||
id="password"
|
<input
|
||||||
type="password"
|
id="password"
|
||||||
autoComplete="current-password"
|
type={showPw ? 'text' : 'password'}
|
||||||
placeholder="••••••••"
|
autoComplete="current-password"
|
||||||
value={password}
|
placeholder="••••••••"
|
||||||
onChange={(e) => setPassword(e.target.value)}
|
value={password}
|
||||||
required
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
/>
|
required
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="kx-field__pw-toggle"
|
||||||
|
onClick={() => setShowPw((v) => !v)}
|
||||||
|
aria-label={showPw ? '비밀번호 숨기기' : '비밀번호 표시'}
|
||||||
|
aria-pressed={showPw}
|
||||||
|
tabIndex={-1}
|
||||||
|
>
|
||||||
|
{showPw ? (
|
||||||
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
|
||||||
|
<path d="M3 3l18 18" />
|
||||||
|
<path d="M10.6 10.6a2 2 0 0 0 2.8 2.8" />
|
||||||
|
<path d="M9.4 5.2A9.5 9.5 0 0 1 12 5c6 0 10 7 10 7a17.6 17.6 0 0 1-3 3.6" />
|
||||||
|
<path d="M6.1 6.7A17.4 17.4 0 0 0 2 12s4 7 10 7a9.3 9.3 0 0 0 3.6-.7" />
|
||||||
|
</svg>
|
||||||
|
) : (
|
||||||
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
|
||||||
|
<path d="M2 12s4-7 10-7 10 7 10 7-4 7-10 7-10-7-10-7z" />
|
||||||
|
<circle cx="12" cy="12" r="3" />
|
||||||
|
</svg>
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="kx-login__row">
|
<div className="kx-login__row">
|
||||||
|
|||||||
@ -364,6 +364,35 @@
|
|||||||
border-color: var(--color-primary-600);
|
border-color: var(--color-primary-600);
|
||||||
box-shadow: 0 0 0 3px rgba(0, 102, 179, 0.15);
|
box-shadow: 0 0 0 3px rgba(0, 102, 179, 0.15);
|
||||||
}
|
}
|
||||||
|
/* 비밀번호 표시/숨김 토글 (눈 아이콘) */
|
||||||
|
.kx-field__pw {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.kx-field__pw input {
|
||||||
|
width: 100%;
|
||||||
|
padding-right: 44px;
|
||||||
|
}
|
||||||
|
.kx-field__pw-toggle {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
right: 6px;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--color-neutral-500);
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
transition: color 0.15s ease, background 0.15s ease;
|
||||||
|
}
|
||||||
|
.kx-field__pw-toggle:hover {
|
||||||
|
color: var(--color-primary-600);
|
||||||
|
background: var(--color-neutral-050);
|
||||||
|
}
|
||||||
|
|
||||||
/* ── 워크스페이스 선택 ── */
|
/* ── 워크스페이스 선택 ── */
|
||||||
.kx-ws {
|
.kx-ws {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user