diff --git a/.Jules/palette.md b/.Jules/palette.md index 7577a1ca7..21eedca70 100644 --- a/.Jules/palette.md +++ b/.Jules/palette.md @@ -56,3 +56,7 @@ ## 2024-07-14 - Native Keyboard Submission with Forms for Modals **Learning:** Modals designed with plain `
` elements as wrappers instead of `
` lack native keyboard submission support, forcing users to switch from keyboard to mouse to confirm actions like "Save". **Action:** When designing modals or popups containing inputs, always use a `` element to wrap the content, handle the `onSubmit` event (calling `e.preventDefault()`), and set the primary confirmation button to `type="submit"` to enable seamless Enter-key submission for keyboard users. + +## 2024-05-15 - Contextual ARIA Labels for Generic Dialog Actions +**Learning:** Generic action buttons like "Delete", "Cancel", or "Save" in dialogs lose context when read by a screen reader out of visual sequence. Screen reader users navigating by buttons hear a list of "Cancel", "Save", "Cancel", "Save". +**Action:** Always provide full context via `aria-label` on generic action buttons in modals (e.g., `aria-label="Delete relationship A to B"`) to prevent ambiguous screen reader experiences. diff --git a/frontend/src/components/modals/EditEdgeModal.tsx b/frontend/src/components/modals/EditEdgeModal.tsx index c34b7e555..6ee3ab35d 100644 --- a/frontend/src/components/modals/EditEdgeModal.tsx +++ b/frontend/src/components/modals/EditEdgeModal.tsx @@ -83,14 +83,16 @@ export function EditEdgeModal({ type="button" onClick={onRelDelete} style={{ color: "#b91c1c", borderColor: "#fca5a5" }} + aria-label={`${editingEdge.source}에서 ${editingEdge.target}으로의 관계 삭제`} > 삭제
- + diff --git a/frontend/src/components/modals/ModalCoverage.test.tsx b/frontend/src/components/modals/ModalCoverage.test.tsx index aa9dac53a..4c13cb942 100644 --- a/frontend/src/components/modals/ModalCoverage.test.tsx +++ b/frontend/src/components/modals/ModalCoverage.test.tsx @@ -116,9 +116,9 @@ describe('modal behavior coverage', () => { fireEvent.change(screen.getByLabelText('제약조건 이름 (Label)'), { target: { value: 'fk_changed' }, }) - fireEvent.click(screen.getByRole('button', { name: '삭제' })) - fireEvent.click(screen.getByRole('button', { name: '취소' })) - fireEvent.click(screen.getByRole('button', { name: '저장' })) + fireEvent.click(screen.getByRole('button', { name: 'a에서 b으로의 관계 삭제' })) + fireEvent.click(screen.getByRole('button', { name: '관계 편집 취소' })) + fireEvent.click(screen.getByRole('button', { name: 'a에서 b으로의 관계 저장' })) expect(setRelLabel).toHaveBeenCalledWith('fk_changed') expect(onDelete).toHaveBeenCalledOnce() expect(onCancel).toHaveBeenCalledOnce()