Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .Jules/palette.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,7 @@
## 2026-06-23 - [SwiftUI Button Accessibility]
**Learning:** Found a pattern where SwiftUI icon-only buttons or minimal UI elements were given `.help()` modifiers for hover tooltips but lacked `.accessibilityLabel()` modifiers for screen readers.
**Action:** When adding `.help()` to buttons, always pair it with a corresponding `.accessibilityLabel()` to ensure full accessibility.

## 2024-07-12 - [Dynamic Accessibility Labels for List Item Actions]
**Learning:** Icon-only buttons (like Edit/Delete) inside lists pose a major accessibility challenge for VoiceOver users when identical labels ("Edit") are repeated without context, making it impossible to know which row is being acted on.
**Action:** Always interpolate the dynamic item context (e.g., `item.name`) into both `.help()` tooltips and `.accessibilityLabel()` modifiers in repeated SwiftUI lists. Include fallback text for empty states (e.g., `"Unnamed Item"`).
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,8 @@ struct SharedMacroRow: View {
.foregroundColor(.accentColor)
}
.buttonStyle(.borderless)
.help("Edit in shared library")
.accessibilityLabel("Edit in shared library")
.help("Edit \(macro.name.isEmpty ? "Unnamed Macro" : macro.name) in shared library")
.accessibilityLabel("Edit \(macro.name.isEmpty ? "Unnamed Macro" : macro.name) in shared library")
}
.padding(.horizontal, 12)
.padding(.vertical, 8)
Expand Down Expand Up @@ -206,16 +206,16 @@ struct MacroRow: View {
.foregroundColor(.accentColor)
}
.buttonStyle(.borderless)
.help("Edit")
.accessibilityLabel("Edit")
.help("Edit \(macro.name.isEmpty ? "Unnamed Macro" : macro.name)")
.accessibilityLabel("Edit \(macro.name.isEmpty ? "Unnamed Macro" : macro.name)")

Button(action: onDelete) {
Image(systemName: "trash")
.foregroundColor(.red.opacity(0.8))
}
.buttonStyle(.borderless)
.help("Delete")
.accessibilityLabel("Delete")
.help("Delete \(macro.name.isEmpty ? "Unnamed Macro" : macro.name)")
.accessibilityLabel("Delete \(macro.name.isEmpty ? "Unnamed Macro" : macro.name)")
}
}
.padding(.horizontal, 12)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,16 +115,16 @@ struct ChordRow: View {
.foregroundColor(.accentColor)
}
.buttonStyle(.borderless)
.help("Edit")
.accessibilityLabel("Edit")
.help("Edit \(chord.buttonsDisplayString)")
.accessibilityLabel("Edit \(chord.buttonsDisplayString)")

Button(action: onDelete) {
Image(systemName: "trash")
.foregroundColor(.red.opacity(0.8))
}
.buttonStyle(.borderless)
.help("Delete")
.accessibilityLabel("Delete")
.help("Delete \(chord.buttonsDisplayString)")
.accessibilityLabel("Delete \(chord.buttonsDisplayString)")
}
}
.padding(.horizontal, 12)
Expand Down Expand Up @@ -261,16 +261,16 @@ struct SequenceRow: View {
.foregroundColor(.accentColor)
}
.buttonStyle(.borderless)
.help("Edit")
.accessibilityLabel("Edit")
.help("Edit \(sequence.stepsDisplayString)")
.accessibilityLabel("Edit \(sequence.stepsDisplayString)")

Button(action: onDelete) {
Image(systemName: "trash")
.foregroundColor(.red.opacity(0.8))
}
.buttonStyle(.borderless)
.help("Delete")
.accessibilityLabel("Delete")
.help("Delete \(sequence.stepsDisplayString)")
.accessibilityLabel("Delete \(sequence.stepsDisplayString)")
}
}
.padding(.horizontal, 12)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,17 @@ struct GestureRow: View {
.foregroundColor(.accentColor)
}
.buttonStyle(.borderless)
.help("Edit")
.accessibilityLabel("Edit")
.help("Edit \(gestureType.displayName)")
.accessibilityLabel("Edit \(gestureType.displayName)")

if mapping?.hasAction == true {
Button(action: onClear) {
Image(systemName: "trash")
.foregroundColor(.red.opacity(0.8))
}
.buttonStyle(.borderless)
.help("Clear")
.accessibilityLabel("Clear")
.help("Clear \(gestureType.displayName)")
.accessibilityLabel("Clear \(gestureType.displayName)")
Comment on lines +81 to +91

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Contextualize the gesture context-menu actions too.

The new icon-button labels include the gesture name, but the context menu still announces generic “Edit Gesture” and “Clear Action” labels. Include gestureType.displayName in those Label strings so the contextual accessibility behavior is consistent across all row actions.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@XboxControllerMapper/XboxControllerMapper/Views/MainWindow/GestureListViews.swift`
around lines 81 - 91, Update the context-menu accessibility Label strings for
the edit and clear actions in the gesture row to include
gestureType.displayName, matching the contextualized .help and
.accessibilityLabel values while preserving the existing action behavior.

}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,16 +222,16 @@ struct ScriptRow: View {
.foregroundColor(.accentColor)
}
.buttonStyle(.borderless)
.help("Edit")
.accessibilityLabel("Edit")
.help("Edit \(script.name.isEmpty ? "Untitled Script" : script.name)")
.accessibilityLabel("Edit \(script.name.isEmpty ? "Untitled Script" : script.name)")

Button(action: onDelete) {
Image(systemName: "trash")
.foregroundColor(.red.opacity(0.8))
}
.buttonStyle(.borderless)
.help("Delete")
.accessibilityLabel("Delete")
.help("Delete \(script.name.isEmpty ? "Untitled Script" : script.name)")
.accessibilityLabel("Delete \(script.name.isEmpty ? "Untitled Script" : script.name)")
}
}
.padding(.horizontal, 12)
Expand Down
Loading