forked from BasedHardware/omi
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathStableChatCardHeader.swift
More file actions
87 lines (83 loc) · 2.7 KB
/
Copy pathStableChatCardHeader.swift
File metadata and controls
87 lines (83 loc) · 2.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import OmiTheme
import SwiftUI
/// Shared geometry for expandable timeline cards. Optional link-out actions
/// always retain their slot so status, text, and disclosure anchors never move
/// as agent availability changes.
struct StableChatCardHeader<Identity: View, Content: View>: View {
let isExpanded: Bool
let showsDisclosure: Bool
let horizontalPadding: CGFloat
let verticalPadding: CGFloat
let minimumHeight: CGFloat?
let onToggle: (() -> Void)?
let onOpen: (() -> Void)?
let identity: Identity
let content: Content
init(
isExpanded: Bool = false,
showsDisclosure: Bool,
horizontalPadding: CGFloat = OmiSpacing.md,
verticalPadding: CGFloat = OmiSpacing.sm,
minimumHeight: CGFloat? = nil,
onToggle: (() -> Void)? = nil,
onOpen: (() -> Void)? = nil,
@ViewBuilder identity: @escaping () -> Identity,
@ViewBuilder content: @escaping () -> Content
) {
self.isExpanded = isExpanded
self.showsDisclosure = showsDisclosure
self.horizontalPadding = horizontalPadding
self.verticalPadding = verticalPadding
self.minimumHeight = minimumHeight
self.onToggle = onToggle
self.onOpen = onOpen
self.identity = identity()
self.content = content()
}
var body: some View {
HStack(alignment: .top, spacing: OmiSpacing.xxs) {
Button(action: { onToggle?() }) {
HStack(alignment: .top, spacing: OmiSpacing.sm) {
identity
.frame(width: 18, height: 18, alignment: .center)
content
.frame(maxWidth: .infinity, alignment: .leading)
Group {
if showsDisclosure {
Image(systemName: isExpanded ? "chevron.up" : "chevron.down")
.scaledFont(size: OmiType.micro)
.foregroundColor(Ink.secondary)
} else {
Color.clear
}
}
.frame(width: 18, height: 18, alignment: .center)
}
.frame(maxWidth: .infinity, alignment: .leading)
.contentShape(Rectangle())
}
.buttonStyle(.plain)
.allowsHitTesting(onToggle != nil)
Group {
if let onOpen {
Button(action: onOpen) {
Image(systemName: "arrow.up.forward.app")
.scaledFont(size: OmiType.micro)
.foregroundColor(Ink.secondary)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.contentShape(Rectangle())
}
.buttonStyle(.plain)
.help("Open agent")
} else {
Color.clear
}
}
.frame(width: 28, height: 28)
}
.padding(.horizontal, horizontalPadding)
.padding(.vertical, verticalPadding)
.frame(minHeight: minimumHeight)
.textSelection(.disabled)
}
}