From 87c86623145675dd9a900dd03d12f38b6ab1b8a3 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sun, 12 Jul 2026 01:56:13 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20Add=20context=20to=20?= =?UTF-8?q?generic=20buttons=20in=20EditTableModal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 테이블 삭제, 복제, 취소, 저장, 컬럼 추가 등 모달 내의 제네릭한 버튼에 맥락을 제공하기 위해 대상 테이블 이름이 포함된 `aria-label`을 추가했습니다. - 이를 통해 스크린 리더 사용자가 해당 버튼이 어떤 테이블에 대한 작업을 수행하는지 명확히 인지할 수 있도록 접근성을 개선했습니다. --- .Jules/palette.md | 4 + .../src/components/modals/EditTableModal.tsx | 160 +++++++++++++----- 2 files changed, 119 insertions(+), 45 deletions(-) diff --git a/.Jules/palette.md b/.Jules/palette.md index 862e9a61..f9a8e36e 100644 --- a/.Jules/palette.md +++ b/.Jules/palette.md @@ -46,3 +46,7 @@ ## 2026-07-10 - Accessibility Anti-pattern: Excessive Tab Stops **Learning:** Adding `tabIndex={0}` to static, non-interactive text badges (like `abbr` or `span`) just to expose their `title` or `aria-label` attributes to keyboard users is an accessibility anti-pattern. It creates excessive tab stops and severely degrades keyboard navigation for users who rely on tab to move through actionable elements. **Action:** Never add `tabIndex={0}` to non-interactive elements unless they are specifically designed to be focusable for a functional reason. Use proper semantic HTML or let the screen reader read adjacent elements as part of natural navigation. + +## 2023-10-27 - Generic Dialog Buttons Need Full Context `aria-label` +**Learning:** Generic action buttons in dialogs (e.g., "Delete", "Duplicate", "Cancel", "Save") can be confusing to screen reader users if they lack context. In `EditTableModal.tsx`, we encountered generic action labels that were improved by explicitly including the target resource name (e.g., table name) in the `aria-label`. +**Action:** When adding generic action buttons like "Save" or "Delete" to modal dialogs, always inject contextual variables (like the item name) into their `aria-label` attribute (e.g., `aria-label={`${editingNode.data.title} 저장`}`) to ensure an unambiguous screen reader experience. diff --git a/frontend/src/components/modals/EditTableModal.tsx b/frontend/src/components/modals/EditTableModal.tsx index 5c605558..a71f8502 100644 --- a/frontend/src/components/modals/EditTableModal.tsx +++ b/frontend/src/components/modals/EditTableModal.tsx @@ -1,12 +1,14 @@ -import React from 'react'; +import React from "react"; import type { Node } from "@xyflow/react"; import type { TableNodeData } from "../../erd/convert"; -import { useDialogAccessibility } from './useDialogAccessibility'; +import { useDialogAccessibility } from "./useDialogAccessibility"; interface EditTableModalProps { isOpen: boolean; editingNode: Node | null; - setEditingNode: React.Dispatch | null>>; + setEditingNode: React.Dispatch< + React.SetStateAction | null> + >; setNodes: React.Dispatch[]>>; onEditTableCancel: () => void; onEditTableSubmit: (e: React.FormEvent) => void; @@ -22,19 +24,43 @@ export function EditTableModal({ onEditTableSubmit, onDeleteTable, }: EditTableModalProps) { - const dialogRef = useDialogAccessibility(isOpen && Boolean(editingNode), onEditTableCancel); + const dialogRef = useDialogAccessibility( + isOpen && Boolean(editingNode), + onEditTableCancel, + ); if (!isOpen || !editingNode) return null; return (
-
+

테이블 편집

- +
-
+
-
+

컬럼

- +