feat: implement Dynamic Type with Apple text styles
Replace all custom Theme.FontSize values and hardcoded font sizes with Apple's built-in text styles (.largeTitle, .title2, .headline, .body, .subheadline, .caption, .caption2) to support accessibility scaling. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -96,11 +96,11 @@ struct PhotoImportView: View {
|
||||
|
||||
VStack(spacing: Theme.Spacing.sm) {
|
||||
Text("Import from Photos")
|
||||
.font(.system(size: Theme.FontSize.sectionTitle, weight: .bold, design: .rounded))
|
||||
.font(.title2)
|
||||
.foregroundStyle(Theme.textPrimary(colorScheme))
|
||||
|
||||
Text("Select photos taken at stadiums to automatically log your visits. We'll use GPS and date data to match them to games.")
|
||||
.font(.system(size: Theme.FontSize.body))
|
||||
.font(.body)
|
||||
.foregroundStyle(Theme.textSecondary(colorScheme))
|
||||
.multilineTextAlignment(.center)
|
||||
.padding(.horizontal, Theme.Spacing.xl)
|
||||
@@ -114,7 +114,7 @@ struct PhotoImportView: View {
|
||||
Image(systemName: "photo.stack")
|
||||
Text("Select Photos")
|
||||
}
|
||||
.font(.system(size: Theme.FontSize.body, weight: .semibold))
|
||||
.font(.body)
|
||||
.foregroundStyle(.white)
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(Theme.Spacing.md)
|
||||
@@ -137,7 +137,7 @@ struct PhotoImportView: View {
|
||||
Image(systemName: "info.circle.fill")
|
||||
.foregroundStyle(Theme.warmOrange)
|
||||
Text("How it works")
|
||||
.font(.system(size: Theme.FontSize.body, weight: .semibold))
|
||||
.font(.body)
|
||||
}
|
||||
|
||||
VStack(alignment: .leading, spacing: Theme.Spacing.xs) {
|
||||
@@ -147,7 +147,7 @@ struct PhotoImportView: View {
|
||||
InfoRow(icon: "hand.tap", text: "You confirm or edit the rest")
|
||||
}
|
||||
}
|
||||
.font(.system(size: Theme.FontSize.caption))
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(Theme.textSecondary(colorScheme))
|
||||
.padding(Theme.Spacing.md)
|
||||
.background(Theme.cardBackground(colorScheme))
|
||||
@@ -164,11 +164,11 @@ struct PhotoImportView: View {
|
||||
ThemedSpinner(size: 50, lineWidth: 4)
|
||||
|
||||
Text("Processing photos...")
|
||||
.font(.system(size: Theme.FontSize.body, weight: .medium))
|
||||
.font(.body)
|
||||
.foregroundStyle(Theme.textSecondary(colorScheme))
|
||||
|
||||
Text("\(viewModel.processedCount) of \(viewModel.totalCount) photos")
|
||||
.font(.system(size: Theme.FontSize.caption))
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(Theme.textMuted(colorScheme))
|
||||
|
||||
Spacer()
|
||||
@@ -222,7 +222,7 @@ struct PhotoImportView: View {
|
||||
Image(systemName: "plus.circle")
|
||||
Text("Add More Photos")
|
||||
}
|
||||
.font(.system(size: Theme.FontSize.body))
|
||||
.font(.body)
|
||||
.foregroundStyle(Theme.warmOrange)
|
||||
}
|
||||
.padding(.top, Theme.Spacing.md)
|
||||
@@ -259,11 +259,11 @@ struct PhotoImportView: View {
|
||||
private func summaryBadge(count: Int, label: String, color: Color) -> some View {
|
||||
VStack(spacing: 4) {
|
||||
Text("\(count)")
|
||||
.font(.system(size: Theme.FontSize.sectionTitle, weight: .bold, design: .rounded))
|
||||
.font(.title2)
|
||||
.foregroundStyle(color)
|
||||
|
||||
Text(label)
|
||||
.font(.system(size: Theme.FontSize.caption))
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(Theme.textSecondary(colorScheme))
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
@@ -283,10 +283,10 @@ struct PhotoImportView: View {
|
||||
.foregroundStyle(color)
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(title)
|
||||
.font(.system(size: Theme.FontSize.body, weight: .semibold))
|
||||
.font(.body)
|
||||
.foregroundStyle(Theme.textPrimary(colorScheme))
|
||||
Text(subtitle)
|
||||
.font(.system(size: Theme.FontSize.caption))
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(Theme.textSecondary(colorScheme))
|
||||
}
|
||||
Spacer()
|
||||
@@ -372,7 +372,7 @@ struct PhotoImportCandidateCard: View {
|
||||
.foregroundStyle(isConfirmed ? .green : Theme.textMuted(colorScheme))
|
||||
}
|
||||
}
|
||||
.font(.system(size: Theme.FontSize.caption))
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(Theme.textSecondary(colorScheme))
|
||||
|
||||
// Match result
|
||||
@@ -407,10 +407,10 @@ struct PhotoImportCandidateCard: View {
|
||||
HStack {
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text("\(matches.count) possible games")
|
||||
.font(.system(size: Theme.FontSize.body, weight: .medium))
|
||||
.font(.body)
|
||||
.foregroundStyle(Theme.textPrimary(colorScheme))
|
||||
Text("Tap to select the correct game")
|
||||
.font(.system(size: Theme.FontSize.caption))
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(Theme.warmOrange)
|
||||
}
|
||||
Spacer()
|
||||
@@ -424,7 +424,7 @@ struct PhotoImportCandidateCard: View {
|
||||
Image(systemName: "exclamationmark.triangle")
|
||||
.foregroundStyle(.red)
|
||||
Text(reason.description)
|
||||
.font(.system(size: Theme.FontSize.caption))
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(Theme.textSecondary(colorScheme))
|
||||
}
|
||||
}
|
||||
@@ -434,7 +434,7 @@ struct PhotoImportCandidateCard: View {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
HStack {
|
||||
Text(match.matchupDescription)
|
||||
.font(.system(size: Theme.FontSize.body, weight: .semibold))
|
||||
.font(.body)
|
||||
.foregroundStyle(Theme.textPrimary(colorScheme))
|
||||
|
||||
Image(systemName: match.game.sport.iconName)
|
||||
@@ -442,7 +442,7 @@ struct PhotoImportCandidateCard: View {
|
||||
}
|
||||
|
||||
Text("\(match.stadium.name) • \(match.gameDateTime)")
|
||||
.font(.system(size: Theme.FontSize.caption))
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(Theme.textSecondary(colorScheme))
|
||||
|
||||
// Confidence badge
|
||||
@@ -463,7 +463,7 @@ struct PhotoImportCandidateCard: View {
|
||||
}()
|
||||
|
||||
return Text(text)
|
||||
.font(.system(size: 10, weight: .medium))
|
||||
.font(.caption2)
|
||||
.foregroundStyle(color)
|
||||
.padding(.horizontal, 6)
|
||||
.padding(.vertical, 2)
|
||||
@@ -496,7 +496,7 @@ struct GameMatchPickerSheet: View {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
HStack {
|
||||
Text(match.fullMatchupDescription)
|
||||
.font(.system(size: Theme.FontSize.body, weight: .medium))
|
||||
.font(.body)
|
||||
.foregroundStyle(Theme.textPrimary(colorScheme))
|
||||
|
||||
Spacer()
|
||||
@@ -506,7 +506,7 @@ struct GameMatchPickerSheet: View {
|
||||
}
|
||||
|
||||
Text("\(match.stadium.name) • \(match.gameDateTime)")
|
||||
.font(.system(size: Theme.FontSize.caption))
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(Theme.textSecondary(colorScheme))
|
||||
}
|
||||
.padding(.vertical, 4)
|
||||
|
||||
Reference in New Issue
Block a user