refactor: redesign planning mode picker as 2x2 card grid

Replace crowded segmented control with clean card-based grid.
Each card shows icon and label with selected state highlight.
Fixes text truncation issue with "Follow Team" option.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-01-11 12:48:58 -06:00
parent f7faec01b1
commit b4ac1f7c24

View File

@@ -212,17 +212,25 @@ struct TripCreationView: View {
private var planningModeSection: some View {
ThemedSection(title: "How do you want to plan?") {
Picker("Planning Mode", selection: $viewModel.planningMode) {
LazyVGrid(
columns: [
GridItem(.flexible(), spacing: Theme.Spacing.sm),
GridItem(.flexible(), spacing: Theme.Spacing.sm)
],
spacing: Theme.Spacing.sm
) {
ForEach(PlanningMode.allCases) { mode in
Text(mode.displayName).tag(mode)
PlanningModeCard(
mode: mode,
isSelected: viewModel.planningMode == mode,
colorScheme: colorScheme
) {
withAnimation(.easeInOut(duration: 0.2)) {
viewModel.planningMode = mode
}
}
}
}
.pickerStyle(.segmented)
Text(viewModel.planningMode.description)
.font(.subheadline)
.foregroundStyle(Theme.textSecondary(colorScheme))
.padding(.top, Theme.Spacing.xs)
}
}
@@ -2384,6 +2392,55 @@ struct TeamPickerSheet: View {
}
}
// MARK: - Planning Mode Card
struct PlanningModeCard: View {
let mode: PlanningMode
let isSelected: Bool
let colorScheme: ColorScheme
let onTap: () -> Void
var body: some View {
Button(action: onTap) {
VStack(spacing: Theme.Spacing.sm) {
// Icon
ZStack {
Circle()
.fill(isSelected ? Theme.warmOrange : Theme.warmOrange.opacity(0.15))
.frame(width: 44, height: 44)
Image(systemName: mode.iconName)
.font(.system(size: 20, weight: .semibold))
.foregroundStyle(isSelected ? .white : Theme.warmOrange)
}
// Title
Text(mode.displayName)
.font(.subheadline.weight(.medium))
.foregroundStyle(Theme.textPrimary(colorScheme))
.lineLimit(1)
}
.frame(maxWidth: .infinity)
.padding(.vertical, Theme.Spacing.md)
.padding(.horizontal, Theme.Spacing.sm)
.background(
RoundedRectangle(cornerRadius: Theme.CornerRadius.medium)
.fill(Theme.cardBackgroundElevated(colorScheme))
)
.overlay(
RoundedRectangle(cornerRadius: Theme.CornerRadius.medium)
.strokeBorder(
isSelected ? Theme.warmOrange : Color.clear,
lineWidth: 2
)
)
}
.buttonStyle(.plain)
.accessibilityLabel("\(mode.displayName): \(mode.description)")
.accessibilityAddTraits(isSelected ? .isSelected : [])
}
}
struct TeamRow: View {
let team: Team
let isSelected: Bool