fix: 로그인 입력칸이 포커스·오류에 반응하지 않던 문제 + 자동완성 배경 처리
FoxInput에 `state`를 넘긴 것이 원인이었다. `state`(=`data-state`)는 카탈로그처럼 상태를 눈으로 비교할 때 쓰는 **고정** 스위치라, 주는 순간 자동 규칙이 통째로 꺼진다 — form-field.scss의 자동 규칙이 `.fox-input:not([data-state])` 안에 들어 있다. 그래서 클릭해도 테두리가 굵어지지 않았고 오류 표시도 살아 있지 않았다. 오류는 `invalid`로 넘기는 것이 정식 경로이며 (`aria-invalid`가 되어 자동 규칙이 잡는다) 그렇게 고쳤다. 자동완성으로 채워진 칸은 Chrome이 자기 배경(연한 파랑)을 칠하는데 @fox에도 앱에도 `:-webkit-autofill` 처리가 없어 그대로 노출된다. 일반 CSS로는 못 덮으므로 표준 우회인 inset 그림자로 가리고 글자색은 `-webkit-text-fill-color`로 맞췄다. 우선 로그인 카드 안으로 범위를 좁혔다 — 모든 FoxInput이 같은 상태라 디자인시스템에 올릴지는 별도 판단이 필요하다. 검증 — data-state가 사라졌고, 포커스 시 테두리가 1px에서 2px #256ef4로, aria-invalid 시 2px #de3412로 바뀐다. autofill 우회 규칙이 스타일시트에 실린 것도 확인했다. Co-Authored-By: Claude Opus 5
@1d512866cfc5cba761f1ed33b80be3998f929783
--- app/(public)/login/_components/login-form.tsx
+++ app/(public)/login/_components/login-form.tsx
... | ... | @@ -24,6 +24,10 @@ |
| 24 | 24 |
* 오류 문구는 FoxInput의 `message`가 아니라 시안의 안내문 자리에 함께 둔다 — 어느 칸이 |
| 25 | 25 |
* 틀렸는지 알려주지 않는 것이 보안상 맞고(계정 존재 여부가 새지 않는다), 입력칸 아래에 |
| 26 | 26 |
* 메시지가 끼면 보기 토글의 세로 위치도 어긋난다. |
| 27 |
+ * |
|
| 28 |
+ * 오류는 `state`가 아니라 `invalid`로 넘긴다. `state`(=`data-state`)는 카탈로그처럼 상태를 |
|
| 29 |
+ * 눈으로 비교할 때 쓰는 **고정** 스위치라, 주는 순간 FoxInput의 자동 규칙(:focus-within 테두리 |
|
| 30 |
+ * 등)이 통째로 꺼진다 — 실제로 포커스해도 테두리가 굵어지지 않았다. |
|
| 27 | 31 |
*/ |
| 28 | 32 |
export function LoginForm() {
|
| 29 | 33 |
const [state, formAction, isPending] = useActionState(login, initialState); |
... | ... | @@ -40,7 +44,7 @@ |
| 40 | 44 |
autoComplete="username" |
| 41 | 45 |
placeholder="아이디를 입력하세요." |
| 42 | 46 |
required |
| 43 |
- state={state.error ? 'error' : 'default'}
|
|
| 47 |
+ invalid={Boolean(state.error)}
|
|
| 44 | 48 |
/> |
| 45 | 49 |
|
| 46 | 50 |
<div className={styles.passwordField}>
|
... | ... | @@ -53,7 +57,7 @@ |
| 53 | 57 |
autoComplete="current-password" |
| 54 | 58 |
placeholder="비밀번호를 입력하세요." |
| 55 | 59 |
required |
| 56 |
- state={state.error ? 'error' : 'default'}
|
|
| 60 |
+ invalid={Boolean(state.error)}
|
|
| 57 | 61 |
/> |
| 58 | 62 |
<button |
| 59 | 63 |
type="button" |
--- app/(public)/login/login.module.scss
+++ app/(public)/login/login.module.scss
... | ... | @@ -87,6 +87,19 @@ |
| 87 | 87 |
block-size: 100%; |
| 88 | 88 |
} |
| 89 | 89 |
|
| 90 |
+// 브라우저 자동완성이 채운 칸은 Chrome이 자기 배경(연한 파랑)을 칠한다 — 일반 CSS로는 못 |
|
| 91 |
+// 덮어서 `inset` 그림자로 가리는 것이 표준 우회다. 글자색은 `-webkit-text-fill-color`로만 |
|
| 92 |
+// 바꿀 수 있다. 전환을 길게 잡는 편법 대신 그림자를 쓰므로 애니메이션이 필요 없다. |
|
| 93 |
+// |
|
| 94 |
+// @fox에도 앱 어디에도 이 처리가 없어 모든 FoxInput이 같은 상태다 — 여기서는 로그인 카드 |
|
| 95 |
+// 안으로 범위를 좁혀 두었다. 디자인시스템에 올릴지는 별도 판단이 필요하다. |
|
| 96 |
+.card :global(.fox-input__field):autofill, |
|
| 97 |
+.card :global(.fox-input__field):-webkit-autofill {
|
|
| 98 |
+ box-shadow: inset 0 0 0 100rem fox.color(input-surface); |
|
| 99 |
+ -webkit-text-fill-color: fox.color(font-neutral-default); |
|
| 100 |
+ caret-color: fox.color(font-neutral-default); |
|
| 101 |
+} |
|
| 102 |
+ |
|
| 90 | 103 |
.helper {
|
| 91 | 104 |
inline-size: 100%; |
| 92 | 105 |
margin: 0; |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?