From 1346ff2a140fedf352578a3a8b4b5a6b56c5adde Mon Sep 17 00:00:00 2001 From: AashishH15 <121846193+AashishH15@users.noreply.github.com> Date: Sat, 6 Jun 2026 13:18:06 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20Add=20dynamic=20aria-?= =?UTF-8?q?labels=20to=20icon-only=20buttons?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .Jules/palette.md | 3 +++ ui/components/NodeEditor.tsx | 1 + ui/components/NodeEditorExpanded.tsx | 1 + ui/components/SpatialWorkspace.tsx | 24 ++++++++++++++++++++++++ 4 files changed, 29 insertions(+) create mode 100644 .Jules/palette.md diff --git a/.Jules/palette.md b/.Jules/palette.md new file mode 100644 index 0000000..6d1ad99 --- /dev/null +++ b/.Jules/palette.md @@ -0,0 +1,3 @@ +## 2024-06-06 - Dynamic Accessibility Labels in React +**Learning:** Found a pattern where interactive elements (like the SpatialWorkspace delete buttons) use a two-step confirm process managed entirely via local React state without text labels. If aria-labels don't adapt to the current UI state, screen readers will hear "Delete" even when the visual UI says "Confirm?". +**Action:** Always bind `aria-label`s to the same state variable that drives the text or icon conditional rendering so accessibility state perfectly mirrors visual state. \ No newline at end of file diff --git a/ui/components/NodeEditor.tsx b/ui/components/NodeEditor.tsx index 6510592..592e83c 100644 --- a/ui/components/NodeEditor.tsx +++ b/ui/components/NodeEditor.tsx @@ -915,6 +915,7 @@ function NodeEditor({ ? "Unfreeze — allow auto-optimize" : "Freeze — protect from auto-optimize" } + aria-label={editFrozen ? "Unfreeze priority" : "Freeze priority"} > ❄️ diff --git a/ui/components/NodeEditorExpanded.tsx b/ui/components/NodeEditorExpanded.tsx index 6a68b66..ecccc00 100644 --- a/ui/components/NodeEditorExpanded.tsx +++ b/ui/components/NodeEditorExpanded.tsx @@ -944,6 +944,7 @@ export default function NodeEditorExpanded({ ? "Unfreeze — auto-optimize priority" : "Freeze — protect from auto-optimize" } + aria-label={editFrozen ? "Unfreeze priority" : "Freeze priority"} > ❄️ diff --git a/ui/components/SpatialWorkspace.tsx b/ui/components/SpatialWorkspace.tsx index b442d5f..7a499b9 100644 --- a/ui/components/SpatialWorkspace.tsx +++ b/ui/components/SpatialWorkspace.tsx @@ -1450,6 +1450,7 @@ export default function SpatialWorkspace({ setEditingItemType("vault"); setEditValue(vault.name); }} + aria-label={`Edit ${vault.name}`} > ✏️ @@ -1459,6 +1460,11 @@ export default function SpatialWorkspace({ className={`spatial-card-action-btn ${deleteArmedId === vault.id ? "delete-armed" : ""}`} onClick={(e) => handleArmDelete(e, vault.id)} title="Click twice to delete vault card" + aria-label={ + deleteArmedId === vault.id + ? `Confirm delete ${vault.name}` + : `Delete ${vault.name}` + } > {deleteArmedId === vault.id ? "Confirm?" : "🗑️"} @@ -1575,6 +1581,7 @@ export default function SpatialWorkspace({ setEditingItemType("node"); setEditValue(node.title); }} + aria-label={`Edit ${node.title}`} > ✏️ @@ -1586,6 +1593,11 @@ export default function SpatialWorkspace({ e.stopPropagation(); handleArmDelete(e, node.id); }} + aria-label={ + deleteArmedId === node.id + ? `Confirm delete ${node.title}` + : `Delete ${node.title}` + } > {deleteArmedId === node.id ? "Ok?" : "🗑️"} @@ -1657,6 +1669,7 @@ export default function SpatialWorkspace({ setEditingItemType("subvault"); setEditValue(subvault.name); }} + aria-label={`Edit ${subvault.name}`} > ✏️ @@ -1668,6 +1681,11 @@ export default function SpatialWorkspace({ e.stopPropagation(); handleArmDelete(e, subvault.id); }} + aria-label={ + deleteArmedId === subvault.id + ? `Confirm delete ${subvault.name}` + : `Delete ${subvault.name}` + } > {deleteArmedId === subvault.id ? "Ok?" : "🗑️"} @@ -1753,6 +1771,7 @@ export default function SpatialWorkspace({ setEditingItemType("node"); setEditValue(node.title); }} + aria-label={`Edit ${node.title}`} > ✏️ @@ -1764,6 +1783,11 @@ export default function SpatialWorkspace({ e.stopPropagation(); handleArmDelete(e, node.id); }} + aria-label={ + deleteArmedId === node.id + ? `Confirm delete ${node.title}` + : `Delete ${node.title}` + } > {deleteArmedId === node.id ? "Ok?" : "🗑️"}