From 5c74d95b1bfabec4bd07ce0bed53c8bc9054efb6 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Thu, 3 Sep 2026 13:51:03 +0000 Subject: [PATCH 1/9] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20[=EC=A0=91?= =?UTF-8?q?=EA=B7=BC=EC=84=B1]=20=EB=82=B4=EB=B3=B4=EB=82=B4=EA=B8=B0=20?= =?UTF-8?q?=EB=AA=A8=EB=8B=AC=20=EB=82=B4=20=EB=B9=84=ED=99=9C=EC=84=B1?= =?UTF-8?q?=ED=99=94=EB=90=9C=20=EB=B2=84=ED=8A=BC=20=EB=B0=9C=EA=B2=AC?= =?UTF-8?q?=EC=84=B1=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ExportModal 내 접근 관리 버튼의 `disabled` 속성을 `aria-disabled={true}`와 `onClick={(e) => e.preventDefault()}`로 대체하여 키보드 포커스 유지 - `exportModal__disabledHintButton` 클래스에 불투명도 및 커서 스타일을 수동으로 추가하여 시각적 피드백 유지 - ExportModal.test.tsx에서 `toBeDisabled` 검증을 `aria-disabled`와 포커스 확인으로 변경하여 접근성 검증 강화 --- .jules/palette.md | 3 +++ frontend/src/components/modals/ExportModal.test.tsx | 4 +++- frontend/src/components/modals/ExportModal.tsx | 3 ++- frontend/src/styles.css | 3 ++- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.jules/palette.md b/.jules/palette.md index bd0f73248..c206151b1 100644 --- a/.jules/palette.md +++ b/.jules/palette.md @@ -57,3 +57,6 @@ ## 2026-07-30 - Add window.confirm for destructive actions **Learning:** Destructive actions like deleting groups and edge relationships previously occurred immediately without user confirmation. **Action:** Always wrap delete operations with window.confirm() dialogs and ensure corresponding tests successfully mock window.confirm. +## 2024-09-03 - Accessible Disabled Buttons +**Learning:** By default, native disabled attributes remove buttons from the focus tab order, making it impossible for screen reader users or keyboard navigators to hear associated aria-describedby tooltips. +**Action:** When adding helper text to a disabled button, use `aria-disabled="true"` to keep it focusable while explicitly handling the event (`e.preventDefault()`). Make sure to manually add `opacity` and `cursor: not-allowed` in CSS to preserve visual indicators. diff --git a/frontend/src/components/modals/ExportModal.test.tsx b/frontend/src/components/modals/ExportModal.test.tsx index bd89c5384..2b27d8f9c 100644 --- a/frontend/src/components/modals/ExportModal.test.tsx +++ b/frontend/src/components/modals/ExportModal.test.tsx @@ -176,7 +176,9 @@ describe('ExportModal', () => { expect(screen.getByText('접근 권한 관리는 프로젝트 권한 설정에서 처리합니다.')).toBeInTheDocument(); const accessManagementButton = screen.getByRole('button', { name: '접근 관리' }); - expect(accessManagementButton).toBeDisabled(); + expect(accessManagementButton).toHaveAttribute('aria-disabled', 'true'); + accessManagementButton.focus(); + expect(accessManagementButton).toHaveFocus(); expect(accessManagementButton).toHaveAttribute('aria-describedby', 'share-export-access-hint'); expect(accessManagementButton).not.toHaveAttribute('title'); }); diff --git a/frontend/src/components/modals/ExportModal.tsx b/frontend/src/components/modals/ExportModal.tsx index 995393ceb..9ccda8ad9 100644 --- a/frontend/src/components/modals/ExportModal.tsx +++ b/frontend/src/components/modals/ExportModal.tsx @@ -202,7 +202,8 @@ export function ExportModal({ )}