From 5bdfa3272e7d2712360ad63a9df99a77947c3d97 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Thu, 16 Jul 2026 21:41:21 +0000 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20=ED=85=8C?= =?UTF-8?q?=EC=9D=B4=EB=B8=94=20=EC=95=A1=EC=85=98=20=EB=B2=84=ED=8A=BC?= =?UTF-8?q?=EC=97=90=20=EC=BB=A8=ED=85=8D=EC=8A=A4=ED=8A=B8=20=EA=B8=B0?= =?UTF-8?q?=EB=B0=98=20ARIA=20=EB=A0=88=EC=9D=B4=EB=B8=94=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 반복되는 테이블 액션 버튼(예: "Details", "Status JSON", "Open viewer")에 스크린 리더 사용자를 위한 컨텍스트 기반의 ARIA 레이블을 추가했습니다. 파일 이름(job.fileName)을 포함하도록 동적으로 레이블을 생성하여 사용자가 어떤 행에 대한 액션인지 명확히 인지할 수 있도록 접근성을 개선했습니다. --- .jules/palette.md | 4 ++++ src/main/resources/static/assets/viewer/demo.js | 16 +++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/.jules/palette.md b/.jules/palette.md index a34ea59..4ac22bf 100644 --- a/.jules/palette.md +++ b/.jules/palette.md @@ -13,3 +13,7 @@ ## 2026-07-13 - Async Table Actions UX **Learning:** Adding explicit loading and disabled states to table action buttons that invoke asynchronous processes helps prevent redundant API calls and visually assures the user that their request is being handled. **Action:** Consistently apply `disabled` state and `Loading...` text changes to inline table action buttons linked to async workflows, and carefully preserve underlying DOM structures with `Array.from(btn.childNodes)` during the loading cycle to avoid rendering regressions. + +## 2026-07-16 - Context-specific ARIA Labels for Table Actions +**Learning:** Screen reader users need context-specific labels for repetitive table actions like 'Details' or 'Open' to understand which row the action applies to. +**Action:** Add dynamically generated 'aria-label' attributes including row-specific identifiers (like file name) to inline action buttons/links. diff --git a/src/main/resources/static/assets/viewer/demo.js b/src/main/resources/static/assets/viewer/demo.js index 51466a8..679a16a 100644 --- a/src/main/resources/static/assets/viewer/demo.js +++ b/src/main/resources/static/assets/viewer/demo.js @@ -81,13 +81,16 @@ function updateJob(jobId, patch, { refreshKpisAfterUpdate = true } = {}) { } } -function createLink(href, label) { +function createLink(href, label, ariaLabel) { const link = document.createElement("a"); link.href = href; link.textContent = label; link.className = "table-link"; link.target = "_blank"; link.rel = "noopener noreferrer"; + if (ariaLabel) { + link.setAttribute("aria-label", ariaLabel); + } return link; } @@ -110,12 +113,15 @@ async function openJsonDocument(url, title) { : "Unable to load JSON evidence with the current tenant claim."; } -function createActionButton(label, onClick) { +function createActionButton(label, onClick, ariaLabel) { const button = document.createElement("button"); button.type = "button"; button.textContent = label; button.className = "btn btn-secondary btn-compact"; button.addEventListener("click", onClick); + if (ariaLabel) { + button.setAttribute("aria-label", ariaLabel); + } return button; } @@ -153,13 +159,13 @@ function renderHistory(history = loadHistory()) { btn.replaceChildren(...initialChildren); btn.disabled = false; }); - })); + }, `View details for ${job.fileName || "document"}`)); actionsCell.appendChild(createActionButton("Status JSON", () => { void openJsonDocument(job.statusUrl, "Clearfolio status JSON"); - })); + }, `Open status JSON for ${job.fileName || "document"}`)); } if (job.jobId) { - actionsCell.appendChild(createLink(`/viewer/${encodeURIComponent(job.jobId)}`, "Open viewer")); + actionsCell.appendChild(createLink(`/viewer/${encodeURIComponent(job.jobId)}`, "Open viewer", `Open viewer for ${job.fileName || "document"}`)); } row.append(fileCell, statusCell, submittedCell, actionsCell); From 094caf414d55566da9d83be3e9f44570b460293f Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Thu, 16 Jul 2026 21:57:28 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20=ED=85=8C?= =?UTF-8?q?=EC=9D=B4=EB=B8=94=20=EC=95=A1=EC=85=98=20=EB=B2=84=ED=8A=BC?= =?UTF-8?q?=EC=97=90=20=EC=BB=A8=ED=85=8D=EC=8A=A4=ED=8A=B8=20=EA=B8=B0?= =?UTF-8?q?=EB=B0=98=20ARIA=20=EB=A0=88=EC=9D=B4=EB=B8=94=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 반복되는 테이블 액션 버튼(예: "Details", "Status JSON", "Open viewer")에 스크린 리더 사용자를 위한 컨텍스트 기반의 ARIA 레이블을 추가했습니다. 파일 이름(job.fileName)을 포함하도록 동적으로 레이블을 생성하여 사용자가 어떤 행에 대한 액션인지 명확히 인지할 수 있도록 접근성을 개선했습니다.