diff --git a/.jules/palette.md b/.jules/palette.md index ea004e2d2..ef0f653f6 100644 --- a/.jules/palette.md +++ b/.jules/palette.md @@ -81,3 +81,7 @@ ## 2026-08-12 - Skip to Content Accessibility **Learning:** Screen reader and keyboard-only users experience significant friction when forced to navigate through repetitive header controls on every page load. **Action:** Keep a visible-on-focus skip link as the first interactive element, target a programmatically focusable main container, and give the focused link a high-contrast outline. + +## 2024-10-04 - 네이티브 파일 입력(Input File) 요소를 접근성 높은 프록시 버튼으로 대체 +**Learning:** `aria-hidden="true"`는 파일 입력 요소를 접근성 트리에서 제거(explicitly removes from the Accessibility Object Model)하며, 시각적으로 숨기기 위해 `class="sr-only" tabindex="-1"`을 함께 사용하여야 스크린 리더와 키보드 접근성을 유지하면서 커스텀 버튼 디자인을 노출시킬 수 있다는 사실을 확인했습니다. +**Action:** 향후 파일 업로드 UI를 개선할 때는 인라인 `onclick` 대신 명시적인 자바스크립트 이벤트 리스너를 바인딩하고 접근성 속성을 올바르게 적용합니다. diff --git a/scanner/dashboard/index.html b/scanner/dashboard/index.html index 132bc31b2..fbe642876 100644 --- a/scanner/dashboard/index.html +++ b/scanner/dashboard/index.html @@ -93,7 +93,8 @@ AppGuardrail no findings loaded - + +

@@ -388,6 +389,15 @@

Dashboard

if(isDeployBlocking(f)!==expect) console.error('selftest FAIL', f, 'expected', expect); } })(); + +(function() { + const headerBrowseFindings = document.getElementById('header-browse-findings'); + const fileInput = document.getElementById('file'); + if (headerBrowseFindings && fileInput) { + headerBrowseFindings.addEventListener('click', () => fileInput.click()); + } +})(); + \ No newline at end of file diff --git a/tests/test_dashboard_core.py b/tests/test_dashboard_core.py index 75a5809f8..e713eff04 100644 --- a/tests/test_dashboard_core.py +++ b/tests/test_dashboard_core.py @@ -77,7 +77,6 @@ def test_dashboard_rows_are_keyboard_accessible(): assert 'tabindex="0" role="button"' in html assert 'title="View details for finding"' in html assert "tbody tr:focus-visible" in html - assert "aria-label=\"Upload findings file\"" in html assert "aria-label=\"Search findings\"" in html assert "aria-label=\"Filter by severity\"" in html assert "tr.addEventListener('keydown'" in html @@ -302,3 +301,14 @@ def test_dashboard_search_escape_clears_input(): assert "e.key === 'Escape'" in html assert "query = '';" in html assert "render();" in html + +def test_file_upload_proxy_accessibility_contract(): + html = dashboard_index_path().read_text(encoding="utf-8") + assert 'class="sr-only"' in html and 'tabindex="-1"' in html and 'aria-hidden="true"' in html, "Hidden file input missing exact accessibility hiding attributes" + assert "headerBrowseFindings.addEventListener('click', () => fileInput.click())" in html, "Missing exact event listener wiring" + +def test_file_upload_proxy_accessibility_contract_is_documented_accurately(): + path = dashboard_index_path().parent.parent.parent / ".jules" / "palette.md" + assert path.exists(), "Journal missing" + content = path.read_text(encoding="utf-8") + assert '`aria-hidden="true"`는 파일 입력 요소를 접근성 트리에서 제거' in content, "Missing exact documentation statement"