feat: add WCAG AA accessibility app-wide, fix CloudKit container config, remove debug logs
- Add VoiceOver labels, hints, and element grouping across all 60+ views - Add Reduce Motion support (Theme.Animation.prefersReducedMotion) to all animations - Replace fixed font sizes with semantic Dynamic Type styles - Hide decorative elements from VoiceOver with .accessibilityHidden(true) - Add .minimumHitTarget() modifier ensuring 44pt touch targets - Add AccessibilityAnnouncer utility for VoiceOver announcements - Improve color contrast values in Theme.swift for WCAG AA compliance - Extract CloudKitContainerConfig for explicit container identity - Remove PostHog debug console log from AnalyticsManager Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -107,6 +107,7 @@ struct GameMatchConfirmationView: View {
|
||||
HStack {
|
||||
Image(systemName: "mappin.circle.fill")
|
||||
.foregroundStyle(Theme.warmOrange)
|
||||
.accessibilityHidden(true)
|
||||
Text("Nearest Stadium")
|
||||
.font(.body)
|
||||
.foregroundStyle(Theme.textPrimary(colorScheme))
|
||||
@@ -131,6 +132,7 @@ struct GameMatchConfirmationView: View {
|
||||
Text(match.formattedDistance)
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(confidenceColor(match.confidence))
|
||||
.accessibilityLabel("\(match.formattedDistance), \(match.confidence.description) confidence")
|
||||
|
||||
Text(match.confidence.description)
|
||||
.font(.caption2)
|
||||
@@ -154,6 +156,7 @@ struct GameMatchConfirmationView: View {
|
||||
HStack {
|
||||
Image(systemName: "sportscourt.fill")
|
||||
.foregroundStyle(Theme.warmOrange)
|
||||
.accessibilityHidden(true)
|
||||
Text(matchOptionsTitle)
|
||||
.font(.body)
|
||||
.foregroundStyle(Theme.textPrimary(colorScheme))
|
||||
@@ -196,6 +199,9 @@ struct GameMatchConfirmationView: View {
|
||||
} label: {
|
||||
gameMatchRow(match, isSelected: selectedMatch?.id == match.id)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.accessibilityValue(selectedMatch?.id == match.id ? "Selected" : "Not selected")
|
||||
.accessibilityAddTraits(selectedMatch?.id == match.id ? .isSelected : [])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,6 +228,7 @@ struct GameMatchConfirmationView: View {
|
||||
Image(systemName: match.game.sport.iconName)
|
||||
.font(.caption)
|
||||
.foregroundStyle(match.game.sport.themeColor)
|
||||
.accessibilityHidden(true)
|
||||
}
|
||||
|
||||
Text(match.gameDateTime)
|
||||
@@ -233,6 +240,7 @@ struct GameMatchConfirmationView: View {
|
||||
Circle()
|
||||
.fill(combinedConfidenceColor(match.confidence.combined))
|
||||
.frame(width: 8, height: 8)
|
||||
.accessibilityLabel(confidenceAccessibilityLabel(match.confidence.combined))
|
||||
Text(match.confidence.combined.description)
|
||||
.font(.caption2)
|
||||
.foregroundStyle(Theme.textMuted(colorScheme))
|
||||
@@ -245,6 +253,7 @@ struct GameMatchConfirmationView: View {
|
||||
Image(systemName: isSelected ? "checkmark.circle.fill" : "circle")
|
||||
.font(.title2)
|
||||
.foregroundStyle(isSelected ? .green : Theme.textMuted(colorScheme))
|
||||
.accessibilityHidden(true)
|
||||
}
|
||||
.padding(Theme.Spacing.md)
|
||||
.background(isSelected ? Theme.cardBackgroundElevated(colorScheme) : Color.clear)
|
||||
@@ -318,6 +327,14 @@ struct GameMatchConfirmationView: View {
|
||||
case .manualOnly: return .red
|
||||
}
|
||||
}
|
||||
|
||||
private func confidenceAccessibilityLabel(_ confidence: CombinedConfidence) -> String {
|
||||
switch confidence {
|
||||
case .autoSelect: return "High confidence"
|
||||
case .userConfirm: return "Medium confidence"
|
||||
case .manualOnly: return "Low confidence"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Preview
|
||||
|
||||
Reference in New Issue
Block a user