From 4c5af99d8f5ddd0917e940024bdb164356f981eb Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sat, 9 May 2026 06:40:42 +0000 Subject: [PATCH 1/2] Add accessibility and tooltips to NodeModulesSection header Co-authored-by: acebytes <2820910+acebytes@users.noreply.github.com> --- .jules/palette.md | 14 +++----------- Sources/Cacheout/Views/NodeModulesSection.swift | 4 ++++ 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/.jules/palette.md b/.jules/palette.md index e048c06..c674725 100644 --- a/.jules/palette.md +++ b/.jules/palette.md @@ -1,11 +1,3 @@ -## 2024-04-30 - Clickable List Rows and Accessibility -**Learning:** In SwiftUI lists, adding a `Button` only around a checkbox creates a tiny hit target that is hard to tap and poorly reported by VoiceOver. -**Action:** Wrap the entire row's `HStack` in a `Button`, apply `.contentShape(Rectangle())` to make empty space clickable, use `.buttonStyle(.plain)` to prevent unintended text styling, and apply `.accessibilityElement(children: .combine)` along with `.accessibilityAddTraits(.isSelected)` for optimal VoiceOver experience. - -## 2024-05-24 - Accessibility Modifiers on Icon-only Controls -**Learning:** SwiftUI icon-only controls (e.g. Button, Menu, Toggle) with just an Image label need an `.accessibilityLabel` to be correctly read by VoiceOver. The `.help` modifier only adds a mouse hover tooltip but does not set the accessibility label. Without an explicit accessibility label, VoiceOver may read nothing or read generic terms like "Button". -**Action:** Always add an `.accessibilityLabel` to any interactive control that uses an icon-only label in SwiftUI, particularly when standardizing or refactoring views. - -## 2024-05-24 - Empty States in Process Lists -**Learning:** Users can misinterpret an empty dynamic list (like processes) as a broken UI or a frozen app if there's no visual feedback indicating that the list is intentionally empty. -**Action:** Always provide a clear, empty state with an icon and brief text for dynamic lists that might temporarily yield no results, preventing user confusion. +## 2024-05-24 - NodeModulesSection Header Accessibility +**Learning:** Disclosure groups built with custom `Button` and `Image` primitives in SwiftUI lack native expand/collapse semantics for VoiceOver, unlike the native `DisclosureGroup` component. +**Action:** When building custom expand/collapse headers, explicitly add `.accessibilityAddTraits(.isButton)`, an `.accessibilityLabel`, an `.accessibilityValue` (Expanded/Collapsed), and a `.help` tooltip. diff --git a/Sources/Cacheout/Views/NodeModulesSection.swift b/Sources/Cacheout/Views/NodeModulesSection.swift index c5110e6..73215bc 100644 --- a/Sources/Cacheout/Views/NodeModulesSection.swift +++ b/Sources/Cacheout/Views/NodeModulesSection.swift @@ -58,6 +58,10 @@ struct NodeModulesSection: View { .contentShape(Rectangle()) } .buttonStyle(.plain) + .accessibilityLabel("Project node modules") + .accessibilityValue(isExpanded ? "Expanded" : "Collapsed") + .accessibilityAddTraits(.isButton) + .help(isExpanded ? "Collapse node_modules section" : "Expand node_modules section") if isExpanded && viewModel.isNodeModulesScanning { HStack { From 6db4317caafe293e997caa96f0b56912298ac94e Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 17 May 2026 14:35:26 +0000 Subject: [PATCH 2/2] Add accessibility and tooltips to NodeModulesSection header Co-authored-by: acebytes <2820910+acebytes@users.noreply.github.com> --- .jules/palette.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.jules/palette.md b/.jules/palette.md index c674725..b033f61 100644 --- a/.jules/palette.md +++ b/.jules/palette.md @@ -1,3 +1,15 @@ +## 2024-04-30 - Clickable List Rows and Accessibility +**Learning:** In SwiftUI lists, adding a `Button` only around a checkbox creates a tiny hit target that is hard to tap and poorly reported by VoiceOver. +**Action:** Wrap the entire row's `HStack` in a `Button`, apply `.contentShape(Rectangle())` to make empty space clickable, use `.buttonStyle(.plain)` to prevent unintended text styling, and apply `.accessibilityElement(children: .combine)` along with `.accessibilityAddTraits(.isSelected)` for optimal VoiceOver experience. + +## 2024-05-24 - Accessibility Modifiers on Icon-only Controls +**Learning:** SwiftUI icon-only controls (e.g. Button, Menu, Toggle) with just an Image label need an `.accessibilityLabel` to be correctly read by VoiceOver. The `.help` modifier only adds a mouse hover tooltip but does not set the accessibility label. Without an explicit accessibility label, VoiceOver may read nothing or read generic terms like "Button". +**Action:** Always add an `.accessibilityLabel` to any interactive control that uses an icon-only label in SwiftUI, particularly when standardizing or refactoring views. + +## 2024-05-24 - Empty States in Process Lists +**Learning:** Users can misinterpret an empty dynamic list (like processes) as a broken UI or a frozen app if there's no visual feedback indicating that the list is intentionally empty. +**Action:** Always provide a clear, empty state with an icon and brief text for dynamic lists that might temporarily yield no results, preventing user confusion. + ## 2024-05-24 - NodeModulesSection Header Accessibility **Learning:** Disclosure groups built with custom `Button` and `Image` primitives in SwiftUI lack native expand/collapse semantics for VoiceOver, unlike the native `DisclosureGroup` component. **Action:** When building custom expand/collapse headers, explicitly add `.accessibilityAddTraits(.isButton)`, an `.accessibilityLabel`, an `.accessibilityValue` (Expanded/Collapsed), and a `.help` tooltip.