Skip to content
Open
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-06-27 - [Disambiguating List Actions]
**Learning:** In repeated lists (like quick text, apps, or links), icon-only buttons with static accessibility labels (e.g., "Edit app") sound identical to screen reader users, making it impossible to know *which* item is being targeted.
**Action:** Always use dynamic context from the current item in the iteration (e.g., `.accessibilityLabel("Edit \(item.displayName)")`) to disambiguate repeated list actions for assistive technologies.
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,15 @@ struct QuickTextRowView<SuggestionsView: View>: View {
}
.buttonStyle(.borderless)
.help("Edit quick text")
.accessibilityLabel("Edit quick text")
.accessibilityLabel("Edit \(quickText.text)")

Button(action: onDelete) {
Image(systemName: "trash")
.foregroundColor(.red)
}
.buttonStyle(.borderless)
.help("Delete quick text")
.accessibilityLabel("Delete quick text")
.accessibilityLabel("Delete \(quickText.text)")
Comment on lines +119 to +127

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 | 🟡 Minor | ⚡ Quick win

Add a fallback label when the item name is blank.

QuickText.text, AppBarItem.displayName, and WebsiteLink.displayName all default to an empty string upstream, so blank or migrated rows will announce labels like Edit / Delete instead of a meaningful control name. Keep the dynamic form, but fall back to the old noun when the interpolated value is empty.

💡 Example fix
- .accessibilityLabel("Edit \(quickText.text)")
+ .accessibilityLabel(quickText.text.isEmpty ? "Edit quick text" : "Edit \(quickText.text)")

- .accessibilityLabel("Delete \(item.displayName)")
+ .accessibilityLabel(item.displayName.isEmpty ? "Delete app" : "Delete \(item.displayName)")

- .accessibilityLabel("Edit \(link.displayName)")
+ .accessibilityLabel(link.displayName.isEmpty ? "Edit link" : "Edit \(link.displayName)")

Also applies to: 198-206, 277-285

🤖 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/OnScreenKeyboardSettingsView.swift`
around lines 119 - 127, The accessibility labels for the edit/delete buttons in
OnScreenKeyboardSettingsView currently interpolate QuickText.text,
AppBarItem.displayName, and WebsiteLink.displayName directly, which can produce
blank announcements when those values are empty. Update the label-building logic
around the affected Button/accessibilityLabel calls so it keeps the dynamic name
when present but falls back to the old noun (for example, the item type like
quick text/app bar item/website link) when the interpolated display name is
empty. Apply the same fallback behavior to all three label pairs in this view,
including the other Edit/Delete sections referenced by the review.

}
}

Expand Down Expand Up @@ -195,15 +195,15 @@ struct AppBarItemRowView: View {
}
.buttonStyle(.borderless)
.help("Edit app")
.accessibilityLabel("Edit app")
.accessibilityLabel("Edit \(item.displayName)")

Button(action: onDelete) {
Image(systemName: "trash")
.foregroundColor(.red)
}
.buttonStyle(.borderless)
.help("Delete app")
.accessibilityLabel("Delete app")
.accessibilityLabel("Delete \(item.displayName)")
}
.padding(.vertical, 4)
.padding(.horizontal, 8)
Expand Down Expand Up @@ -274,15 +274,15 @@ struct WebsiteLinkRowView: View {
}
.buttonStyle(.borderless)
.help("Edit link")
.accessibilityLabel("Edit link")
.accessibilityLabel("Edit \(link.displayName)")

Button(action: onDelete) {
Image(systemName: "trash")
.foregroundColor(.red)
}
.buttonStyle(.borderless)
.help("Delete link")
.accessibilityLabel("Delete link")
.accessibilityLabel("Delete \(link.displayName)")
}
.padding(.vertical, 4)
.padding(.horizontal, 8)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@ struct JoystickSettingsView: View {
}
.buttonStyle(.borderless)
.help("Reset to base (inherit)")
.accessibilityLabel("Reset \(label) to inherited")
}
}

Expand Down
Loading