diff --git a/.jules/palette.md b/.jules/palette.md index e048c06..b033f61 100644 --- a/.jules/palette.md +++ b/.jules/palette.md @@ -9,3 +9,7 @@ ## 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 {