Skip to content

Commit dd66ac0

Browse files
authored
Merge pull request #7 from kushalpandya/kp-unify-list-header-style
Unified header styles across the app for consistency
2 parents b874342 + 46329f2 commit dd66ac0

8 files changed

Lines changed: 1284 additions & 1064 deletions

File tree

Views/Components/ListHeader.swift

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
import SwiftUI
2+
3+
// MARK: - List Header Style View Modifier
4+
5+
struct ListHeaderStyle: ViewModifier {
6+
let height: CGFloat
7+
let padding: EdgeInsets
8+
9+
init(height: CGFloat = 36, padding: EdgeInsets? = nil) {
10+
self.height = height
11+
self.padding = padding ?? EdgeInsets(top: 8, leading: 12, bottom: 8, trailing: 12)
12+
}
13+
14+
func body(content: Content) -> some View {
15+
content
16+
.padding(padding)
17+
.frame(maxWidth: .infinity)
18+
.frame(height: height)
19+
.background(Color(NSColor.controlBackgroundColor).opacity(0.5))
20+
}
21+
}
22+
23+
// MARK: - View Extension
24+
25+
extension View {
26+
func listHeaderStyle(height: CGFloat = 36, padding: EdgeInsets? = nil) -> some View {
27+
modifier(ListHeaderStyle(height: height, padding: padding))
28+
}
29+
}
30+
31+
// MARK: - List Header Container
32+
33+
struct ListHeader<Content: View>: View {
34+
enum HeaderType {
35+
case simple // Default 36px height
36+
case expanded // Custom height for complex content
37+
}
38+
39+
let type: HeaderType
40+
let height: CGFloat?
41+
let padding: EdgeInsets?
42+
let content: () -> Content
43+
44+
init(
45+
type: HeaderType = .simple,
46+
height: CGFloat? = nil,
47+
padding: EdgeInsets? = nil,
48+
@ViewBuilder content: @escaping () -> Content
49+
) {
50+
self.type = type
51+
self.height = height
52+
self.padding = padding
53+
self.content = content
54+
}
55+
56+
var body: some View {
57+
HStack {
58+
content()
59+
}
60+
.listHeaderStyle(
61+
height: height ?? (type == .simple ? 36 : 120),
62+
padding: padding
63+
)
64+
}
65+
}
66+
67+
// MARK: - Specialized Header Components
68+
69+
// For complex playlist headers with artwork
70+
struct PlaylistHeader<Content: View>: View {
71+
let content: () -> Content
72+
73+
init(@ViewBuilder content: @escaping () -> Content) {
74+
self.content = content
75+
}
76+
77+
var body: some View {
78+
content()
79+
.padding(.horizontal, 20)
80+
.padding(.vertical, 20)
81+
.frame(maxWidth: .infinity)
82+
.background(Color(NSColor.controlBackgroundColor).opacity(0.5))
83+
}
84+
}
85+
86+
// For track list headers with title and count
87+
struct TrackListHeader<Trailing: View>: View {
88+
let title: String
89+
let subtitle: String?
90+
let trackCount: Int
91+
let trailing: (() -> Trailing)?
92+
93+
init(
94+
title: String,
95+
subtitle: String? = nil,
96+
trackCount: Int,
97+
@ViewBuilder trailing: @escaping () -> Trailing
98+
) {
99+
self.title = title
100+
self.subtitle = subtitle
101+
self.trackCount = trackCount
102+
self.trailing = trailing
103+
}
104+
105+
init(
106+
title: String,
107+
subtitle: String? = nil,
108+
trackCount: Int
109+
) where Trailing == EmptyView {
110+
self.title = title
111+
self.subtitle = subtitle
112+
self.trackCount = trackCount
113+
self.trailing = nil
114+
}
115+
116+
var body: some View {
117+
ListHeader {
118+
VStack(alignment: .leading, spacing: 2) {
119+
Text(title)
120+
.headerTitleStyle()
121+
122+
if let subtitle = subtitle {
123+
Text(subtitle)
124+
.headerSubtitleStyle()
125+
}
126+
}
127+
128+
Spacer()
129+
130+
if let trailing = trailing {
131+
trailing()
132+
} else {
133+
Text("\(trackCount) tracks")
134+
.headerSubtitleStyle()
135+
}
136+
}
137+
}
138+
}
139+
140+
// MARK: - Common Header Text Styles
141+
142+
struct HeaderTitleStyle: ViewModifier {
143+
func body(content: Content) -> some View {
144+
content
145+
.font(.headline)
146+
}
147+
}
148+
149+
struct HeaderSubtitleStyle: ViewModifier {
150+
func body(content: Content) -> some View {
151+
content
152+
.font(.caption)
153+
.foregroundColor(.secondary)
154+
}
155+
}
156+
157+
extension View {
158+
func headerTitleStyle() -> some View {
159+
modifier(HeaderTitleStyle())
160+
}
161+
162+
func headerSubtitleStyle() -> some View {
163+
modifier(HeaderSubtitleStyle())
164+
}
165+
}
166+
167+
// MARK: - Divider Extension for Headers
168+
169+
extension Divider {
170+
static var headerDivider: some View {
171+
Divider()
172+
.frame(height: 1)
173+
.overlay(Color(NSColor.separatorColor).opacity(0.3))
174+
}
175+
}

0 commit comments

Comments
 (0)