From 3f2760f8fe5d1bd1dc03d977a4df4f906137ec15 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sat, 4 Jul 2026 14:34:53 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20=EC=9D=B8=EB=9D=BC?= =?UTF-8?q?=EC=9D=B8=20=ED=8F=BC=20=EC=9C=A0=ED=9A=A8=EC=84=B1=20=EA=B2=80?= =?UTF-8?q?=EC=82=AC=20=EC=8B=9C=EA=B0=81=EC=A0=81=20=ED=94=BC=EB=93=9C?= =?UTF-8?q?=EB=B0=B1=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `styles.css`에 `aria-invalid="true"` 속성을 가진 입력 및 선택 필드에 대한 테두리와 포커스 스타일 추가 - `.jules/palette.md`에 접근성 관련 학습 내용 기록 --- .jules/palette.md | 3 +++ styles.css | 15 +++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/.jules/palette.md b/.jules/palette.md index 7f3a0941..bd9309de 100644 --- a/.jules/palette.md +++ b/.jules/palette.md @@ -101,3 +101,6 @@ ## 2026-06-30 - Restore keyboard focus after synchronous DOM replacement **Learning:** In applications that rely on replacing large chunks of the DOM tree (e.g., calling `renderAll()` on every state change), elements that triggered the change (like dropdowns or toggle buttons) get destroyed and recreated. This causes the browser to reset focus to the `` element, completely breaking keyboard navigation and forcing screen reader users to start over. **Action:** When implementing interactions that trigger a full re-render, identify the element that triggered the change (e.g., using its ID or data attributes), and use `requestAnimationFrame` to manually call `.focus()` on the newly rendered equivalent element after the DOM has been updated. +## 2026-07-04 - 인라인 폼 유효성 검사 시각적 피드백 추가 +**Learning:** `aria-invalid` 속성만 추가하고 시각적인 피드백을 제공하지 않으면, 시각적 사용자가 오류가 발생한 위치를 직관적으로 파악하기 어렵습니다. +**Action:** `aria-invalid="true"`가 설정된 폼 필드에 테두리와 포커스 스타일을 추가하여 명확한 시각적 오류 피드백을 제공하도록 합니다. diff --git a/styles.css b/styles.css index f26c9768..7e65802d 100644 --- a/styles.css +++ b/styles.css @@ -469,6 +469,21 @@ select[data-inline-progress]:focus { outline: none; } +.editor-field input[aria-invalid="true"], +.editor-field select[aria-invalid="true"], +select[data-inline-progress][aria-invalid="true"] { + border-color: var(--danger); + box-shadow: 0 0 0 1px var(--danger); +} + +.editor-field input[aria-invalid="true"]:focus, +.editor-field select[aria-invalid="true"]:focus, +select[data-inline-progress][aria-invalid="true"]:focus { + border-color: var(--danger); + box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.15); + outline: none; +} + .editor-actions { margin-top: 24px; display: flex;