forked from intitni/CopilotForXcode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSidebarTabView.swift
More file actions
122 lines (114 loc) · 4.14 KB
/
SidebarTabView.swift
File metadata and controls
122 lines (114 loc) · 4.14 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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import SwiftUI
struct SidebarItem: Identifiable, Equatable {
var id: Int { tag }
var tag: Int
var title: String
var subtitle: String? = nil
var image: String? = nil
}
struct SidebarItemPreferenceKey: PreferenceKey {
static var defaultValue: [SidebarItem] = []
static func reduce(value: inout [SidebarItem], nextValue: () -> [SidebarItem]) {
value.append(contentsOf: nextValue())
}
}
extension View {
func sidebarItem(
tag: Int,
currentTag: Int,
title: String,
subtitle: String? = nil,
image: String? = nil
) -> some View {
return opacity(tag != currentTag ? 0 : 1)
.background(GeometryReader { _ in
Color.clear.preference(
key: SidebarItemPreferenceKey.self,
value: [.init(tag: tag, title: title, subtitle: subtitle, image: image)]
)
})
}
}
struct SidebarTabView<Content: View>: View {
@State var sidebarItems = [SidebarItem]()
@Binding var tag: Int
@ViewBuilder var views: (_ tag: Int) -> Content
var body: some View {
HStack(spacing: 0) {
ScrollView {
VStack(alignment: .leading) {
ForEach(sidebarItems) { item in
Button(action: {
tag = item.tag
}) {
HStack {
if let image = item.image {
Image(systemName: image)
.resizable()
.scaledToFit()
.frame(width: 20, height: 20)
}
VStack(alignment: .leading, spacing: 2) {
Text(item.title)
.foregroundStyle(.primary)
if let subtitle = item.subtitle {
Text(subtitle)
.lineSpacing(0)
.font(.caption)
.foregroundStyle(.tertiary)
.opacity(0.5)
.multilineTextAlignment(.leading)
}
}
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.horizontal, 8)
.padding(.vertical, 4)
.background(
Color.primary.opacity(tag == item.tag ? 0.1 : 0),
in: RoundedRectangle(cornerRadius: 4)
)
.padding(.horizontal, 8)
}
.buttonStyle(.borderless)
}
}
.frame(width: 200)
.padding(.vertical, 8)
}
.background(Color.primary.opacity(0.05))
Divider()
ZStack(alignment: .topLeading) {
views(tag)
}
}
.onPreferenceChange(SidebarItemPreferenceKey.self) { items in
sidebarItems = items
}
}
}
struct SidebarTabView_Previews: PreviewProvider {
static var previews: some View {
SidebarTabView(tag: .constant(0)) { tag in
Color.red.sidebarItem(
tag: 0,
currentTag: tag,
title: "Hello",
subtitle: "Meow\nMeow",
image: "person.circle.fill"
)
Color.blue.sidebarItem(
tag: 1,
currentTag: tag,
title: "World",
image: "person.circle.fill"
)
Color.blue.sidebarItem(
tag: 3,
currentTag: tag,
title: "Pikachu",
image: "person.circle.fill"
)
}
}
}