임동욱 임동욱 08-18
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
+++ app/(public)/login/_components/login-form.tsx
@@ -24,6 +24,10 @@
  * 오류 문구는 FoxInput의 `message`가 아니라 시안의 안내문 자리에 함께 둔다 — 어느 칸이
  * 틀렸는지 알려주지 않는 것이 보안상 맞고(계정 존재 여부가 새지 않는다), 입력칸 아래에
  * 메시지가 끼면 보기 토글의 세로 위치도 어긋난다.
+ *
+ * 오류는 `state`가 아니라 `invalid`로 넘긴다. `state`(=`data-state`)는 카탈로그처럼 상태를
+ * 눈으로 비교할 때 쓰는 **고정** 스위치라, 주는 순간 FoxInput의 자동 규칙(:focus-within 테두리
+ * 등)이 통째로 꺼진다 — 실제로 포커스해도 테두리가 굵어지지 않았다.
  */
 export function LoginForm() {
   const [state, formAction, isPending] = useActionState(login, initialState);
@@ -40,7 +44,7 @@
         autoComplete="username"
         placeholder="아이디를 입력하세요."
         required
-        state={state.error ? 'error' : 'default'}
+        invalid={Boolean(state.error)}
       />
 
       <div className={styles.passwordField}>
@@ -53,7 +57,7 @@
           autoComplete="current-password"
           placeholder="비밀번호를 입력하세요."
           required
-          state={state.error ? 'error' : 'default'}
+          invalid={Boolean(state.error)}
         />
         <button
           type="button"
app/(public)/login/login.module.scss
--- app/(public)/login/login.module.scss
+++ app/(public)/login/login.module.scss
@@ -87,6 +87,19 @@
   block-size: 100%;
 }
 
+// 브라우저 자동완성이 채운 칸은 Chrome이 자기 배경(연한 파랑)을 칠한다 — 일반 CSS로는 못
+// 덮어서 `inset` 그림자로 가리는 것이 표준 우회다. 글자색은 `-webkit-text-fill-color`로만
+// 바꿀 수 있다. 전환을 길게 잡는 편법 대신 그림자를 쓰므로 애니메이션이 필요 없다.
+//
+// @fox에도 앱 어디에도 이 처리가 없어 모든 FoxInput이 같은 상태다 — 여기서는 로그인 카드
+// 안으로 범위를 좁혀 두었다. 디자인시스템에 올릴지는 별도 판단이 필요하다.
+.card :global(.fox-input__field):autofill,
+.card :global(.fox-input__field):-webkit-autofill {
+  box-shadow: inset 0 0 0 100rem fox.color(input-surface);
+  -webkit-text-fill-color: fox.color(font-neutral-default);
+  caret-color: fox.color(font-neutral-default);
+}
+
 .helper {
   inline-size: 100%;
   margin: 0;
Add a comment
List