From f78b3264a7e53013f8331ef1076b2a60cd3994ac Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 06:09:09 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20Make=20category=20row?= =?UTF-8?q?s=20fully=20clickable=20and=20accessible?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wrapped the CategoryRow's HStack in a Button and used `.contentShape(Rectangle())` to make the entire row clickable rather than just the small checkbox. Added `.accessibilityElement(children: .combine)` and `.accessibilityAddTraits(.isSelected)` to ensure VoiceOver correctly reads the whole row and announces its selection state. Co-authored-by: acebytes <2820910+acebytes@users.noreply.github.com> --- .jules/palette.md | 3 +++ Sources/Cacheout/Views/CategoryRow.swift | 15 +++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) create mode 100644 .jules/palette.md diff --git a/.jules/palette.md b/.jules/palette.md new file mode 100644 index 0000000..858fa61 --- /dev/null +++ b/.jules/palette.md @@ -0,0 +1,3 @@ +## 2024-05-30 - Make SwiftUI List Rows Fully Clickable +**Learning:** In SwiftUI, just having a button in an HStack restricts the clickable area. Furthermore, wrapping an HStack in a button requires `.contentShape(Rectangle())` to make whitespace clickable and specific `.accessibilityElement(children: .combine)` and `.accessibilityAddTraits` to ensure proper VoiceOver behavior. +**Action:** Always wrap the entire row contents in a Button, apply `.contentShape(Rectangle())`, and apply proper accessibility traits when building custom list rows. diff --git a/Sources/Cacheout/Views/CategoryRow.swift b/Sources/Cacheout/Views/CategoryRow.swift index 2653aae..ee99b7d 100644 --- a/Sources/Cacheout/Views/CategoryRow.swift +++ b/Sources/Cacheout/Views/CategoryRow.swift @@ -24,15 +24,12 @@ struct CategoryRow: View { let onToggle: () -> Void var body: some View { - HStack(spacing: 12) { - // Checkbox - Button(action: onToggle) { + Button(action: onToggle) { + HStack(spacing: 12) { + // Checkbox Image(systemName: result.isSelected ? "checkmark.circle.fill" : "circle") .font(.title3) .foregroundStyle(result.isSelected ? .blue : .secondary) - } - .buttonStyle(.plain) - .disabled(result.isEmpty) // Icon Image(systemName: result.category.icon) @@ -70,6 +67,12 @@ struct CategoryRow: View { RiskBadge(level: result.category.riskLevel) } } + .contentShape(Rectangle()) + } + .buttonStyle(.plain) + .disabled(result.isEmpty) + .accessibilityElement(children: .combine) + .accessibilityAddTraits(result.isSelected ? [.isSelected] : []) .padding(.vertical, 6) .padding(.horizontal, 10) .opacity(result.isEmpty ? 0.5 : 1)