feat: swipeable food sheet — Quick Add first, swipe for AI Chat
All checks were successful
Security Checks / dockerfile-lint (push) Successful in 4s
Security Checks / dependency-audit (push) Successful in 13s
Security Checks / secret-scanning (push) Successful in 4s

Replaced pill tab selector with swipeable TabView (.page style):
- Page 0: Quick Add (food search list) — shown first
- Page 1: AI Chat — swipe right to access
- Custom dot indicators replace the old pill tabs
- Swipe gesture between pages

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Yusuf Suleman
2026-04-04 11:52:01 -05:00
parent a5c95c2e5f
commit 66ab375ee0

View File

@@ -180,12 +180,13 @@ struct MainTabView: View {
// MARK: - Assistant Sheet
struct AssistantSheetView: View {
@State private var selectedMode = 0
@State private var selectedPage = 0
var onFoodAdded: () -> Void = {}
var body: some View {
VStack(spacing: 0) {
VStack(spacing: 12) {
// Drag handle + title
VStack(spacing: 8) {
Capsule()
.fill(Color.textTertiary.opacity(0.3))
.frame(width: 36, height: 5)
@@ -195,41 +196,30 @@ struct AssistantSheetView: View {
.font(.headline)
.foregroundStyle(Color.textPrimary)
HStack(spacing: 4) {
tabButton("AI Chat", icon: "sparkles", index: 0)
tabButton("Quick Add", icon: "magnifyingglass", index: 1)
// Page indicator dots
HStack(spacing: 6) {
Circle()
.fill(selectedPage == 0 ? Color.accentWarm : Color.textTertiary.opacity(0.3))
.frame(width: 7, height: 7)
Circle()
.fill(selectedPage == 1 ? Color.accentWarm : Color.textTertiary.opacity(0.3))
.frame(width: 7, height: 7)
}
.padding(4)
.background(Color.textTertiary.opacity(0.08))
.clipShape(Capsule())
.padding(.horizontal, 40)
.padding(.bottom, 4)
}
.padding(.bottom, 12)
.background(Color.canvas)
if selectedMode == 0 {
AssistantChatView(onFoodAdded: onFoodAdded)
} else {
// Swipeable pages: Quick Add first, AI Chat second
TabView(selection: $selectedPage) {
FoodSearchView(isSheet: true, onFoodAdded: onFoodAdded)
.tag(0)
AssistantChatView(onFoodAdded: onFoodAdded)
.tag(1)
}
.tabViewStyle(.page(indexDisplayMode: .never))
}
.background(Color.canvas)
.presentationDetents([.large])
}
private func tabButton(_ title: String, icon: String, index: Int) -> some View {
Button {
withAnimation(.easeInOut(duration: 0.2)) { selectedMode = index }
} label: {
HStack(spacing: 5) {
Image(systemName: icon).font(.caption2)
Text(title).font(.subheadline.weight(selectedMode == index ? .semibold : .regular))
}
.foregroundStyle(selectedMode == index ? Color.textPrimary : Color.textTertiary)
.padding(.horizontal, 16)
.padding(.vertical, 8)
.background(selectedMode == index ? Color.surfaceCard : Color.clear)
.clipShape(Capsule())
}
}
}