fix: warm sheet header, welcome state for AI chat, consistent colors
- Custom sheet header with warm canvas background (no white bar) - Tab picker styled as warm pills (not default segmented control) - AI Chat welcome state: sparkles icon + 'What did you eat?' prompt - All backgrounds use canvas color consistently Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -63,28 +63,62 @@ struct MainTabView: View {
|
||||
}
|
||||
|
||||
struct AssistantSheetView: View {
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
@State private var selectedMode = 0
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
VStack(spacing: 0) {
|
||||
Picker("Mode", selection: $selectedMode) {
|
||||
Text("AI Chat").tag(0)
|
||||
Text("Quick Add").tag(1)
|
||||
}
|
||||
.pickerStyle(.segmented)
|
||||
.padding(.horizontal)
|
||||
// Custom header — warm background
|
||||
VStack(spacing: 12) {
|
||||
// Drag handle
|
||||
Capsule()
|
||||
.fill(Color.textTertiary.opacity(0.3))
|
||||
.frame(width: 36, height: 5)
|
||||
.padding(.top, 8)
|
||||
|
||||
Text("Add Food")
|
||||
.font(.headline)
|
||||
.foregroundStyle(Color.textPrimary)
|
||||
|
||||
// Tab picker — warm styled
|
||||
HStack(spacing: 4) {
|
||||
tabButton("AI Chat", icon: "sparkles", index: 0)
|
||||
tabButton("Quick Add", icon: "magnifyingglass", index: 1)
|
||||
}
|
||||
.padding(4)
|
||||
.background(Color.textTertiary.opacity(0.08))
|
||||
.clipShape(Capsule())
|
||||
.padding(.horizontal, 40)
|
||||
}
|
||||
.padding(.bottom, 12)
|
||||
.background(Color.canvas)
|
||||
|
||||
// Content
|
||||
if selectedMode == 0 {
|
||||
AssistantChatView()
|
||||
} else {
|
||||
FoodSearchView(isSheet: true)
|
||||
}
|
||||
}
|
||||
.navigationTitle("Add Food")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
.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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,27 @@ struct AssistantChatView: View {
|
||||
ScrollViewReader { proxy in
|
||||
ScrollView {
|
||||
LazyVStack(spacing: 8) {
|
||||
// Welcome state when no messages
|
||||
if vm.messages.isEmpty {
|
||||
VStack(spacing: 16) {
|
||||
Spacer(minLength: 60)
|
||||
Image(systemName: "sparkles")
|
||||
.font(.system(size: 40))
|
||||
.foregroundStyle(Color.accentWarm.opacity(0.4))
|
||||
Text("What did you eat?")
|
||||
.font(.title3.weight(.semibold))
|
||||
.foregroundStyle(Color.textPrimary)
|
||||
Text("Describe your food naturally.\n\"2 eggs and toast for breakfast\"\nor snap a photo of your meal.")
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(Color.textSecondary)
|
||||
.multilineTextAlignment(.center)
|
||||
.lineSpacing(4)
|
||||
Spacer(minLength: 60)
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.horizontal, 32)
|
||||
}
|
||||
|
||||
ForEach(vm.messages) { message in
|
||||
chatBubble(message)
|
||||
.id(message.id)
|
||||
|
||||
Reference in New Issue
Block a user