From 88c0e2cbee048ed2c155512b911c155d73ca835b Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 14 Jul 2026 08:52:30 +0000 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20Fix=20Script=20Ex?= =?UTF-8?q?amples=20Gallery=20and=20Empty=20State=20Accessibility?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: NSEvent <44446865+NSEvent@users.noreply.github.com> --- .Jules/palette.md | 4 ++++ .../Views/Scripts/ScriptExamplesGalleryView.swift | 14 +++++++++----- .../Views/Scripts/ScriptListView.swift | 2 ++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/.Jules/palette.md b/.Jules/palette.md index 58909748..62ce79d6 100644 --- a/.Jules/palette.md +++ b/.Jules/palette.md @@ -29,3 +29,7 @@ ## 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"`). + +## 2024-08-01 - Avoid .onTapGesture for Interactive Elements +**Learning:** In SwiftUI, using `.onTapGesture` on standard Views (such as cards or list rows) prevents them from being natively keyboard-navigable and fails to expose default button accessibility traits. This causes major accessibility barriers for users who rely on keyboard navigation or VoiceOver. +**Action:** When a View functions as a primary interaction point (e.g., a card that performs an action when clicked), wrap it in a `Button` with an appropriate style (like `.buttonStyle(.plain)`) rather than appending `.onTapGesture`. Always ensure it is paired with `.help()` and `.accessibilityLabel()` modifiers containing contextual information. diff --git a/XboxControllerMapper/XboxControllerMapper/Views/Scripts/ScriptExamplesGalleryView.swift b/XboxControllerMapper/XboxControllerMapper/Views/Scripts/ScriptExamplesGalleryView.swift index d9c2a535..ab462e4b 100644 --- a/XboxControllerMapper/XboxControllerMapper/Views/Scripts/ScriptExamplesGalleryView.swift +++ b/XboxControllerMapper/XboxControllerMapper/Views/Scripts/ScriptExamplesGalleryView.swift @@ -26,11 +26,15 @@ struct ScriptExamplesGalleryView: View { ScrollView { LazyVGrid(columns: columns, spacing: 12) { ForEach(ScriptExamplesData.all) { example in - ExampleCard(example: example) - .onTapGesture { - onSelect(example) - dismiss() - } + Button { + onSelect(example) + dismiss() + } label: { + ExampleCard(example: example) + } + .buttonStyle(.plain) + .help("Use \(example.name) script") + .accessibilityLabel("Use \(example.name) script") } } .padding() diff --git a/XboxControllerMapper/XboxControllerMapper/Views/Scripts/ScriptListView.swift b/XboxControllerMapper/XboxControllerMapper/Views/Scripts/ScriptListView.swift index 11c8dd28..5521bd49 100644 --- a/XboxControllerMapper/XboxControllerMapper/Views/Scripts/ScriptListView.swift +++ b/XboxControllerMapper/XboxControllerMapper/Views/Scripts/ScriptListView.swift @@ -129,6 +129,8 @@ struct ScriptListView: View { .contentShape(Rectangle()) } .buttonStyle(.plain) + .help("Add \(example.name) script") + .accessibilityLabel("Add \(example.name) script") } HStack(spacing: 12) { From dcc8c0d4c54269bc351af08d2b69162f24cd9a5e Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 14 Jul 2026 09:03:44 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20Fix=20Script=20Ex?= =?UTF-8?q?amples=20Gallery=20and=20Empty=20State=20Accessibility?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: NSEvent <44446865+NSEvent@users.noreply.github.com>