Improve pattern theme with visible mood icon backgrounds

- Remove pattern from month section header for cleaner look
- Fix entry rows to show mood icon as repeating background
- Add ultraThinMaterial behind text for better readability

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Trey t
2025-12-18 13:45:34 -06:00
parent f57e8da4ff
commit e123df1790
2 changed files with 75 additions and 106 deletions

View File

@@ -574,50 +574,19 @@ extension DayView {
}
private func patternSectionHeader(month: Int, year: Int) -> some View {
ZStack {
// Subtle mood icon pattern background
GeometryReader { geo in
let iconSize: CGFloat = 12
let spacing: CGFloat = 20
let cols = Int(geo.size.width / spacing) + 1
let rows = 3
HStack(spacing: 10) {
Image(systemName: "calendar")
.font(.system(size: 16, weight: .semibold))
.foregroundColor(textColor.opacity(0.6))
Canvas { context, size in
for row in 0..<rows {
for col in 0..<cols {
let x = CGFloat(col) * spacing + (row % 2 == 0 ? 0 : spacing / 2)
let y = CGFloat(row) * spacing + 8
let rect = CGRect(x: x, y: y, width: iconSize, height: iconSize)
context.opacity = 0.06
context.fill(Circle().path(in: rect), with: .color(textColor))
}
}
}
}
.frame(height: 60)
Text("\(Random.monthName(fromMonthInt: month)) \(String(year))")
.font(.system(size: 20, weight: .bold, design: .rounded))
.foregroundColor(textColor)
HStack(spacing: 12) {
// Mood icon cluster
HStack(spacing: -4) {
ForEach(0..<3, id: \.self) { i in
Circle()
.fill(textColor.opacity(0.15 - Double(i) * 0.04))
.frame(width: 20 - CGFloat(i * 2), height: 20 - CGFloat(i * 2))
}
}
Text(Random.monthName(fromMonthInt: month))
.font(.system(size: 18, weight: .semibold))
.foregroundColor(textColor)
Text(String(year))
.font(.system(size: 14, weight: .regular))
.foregroundColor(textColor.opacity(0.5))
Spacer()
}
.padding(.horizontal, 20)
Spacer()
}
.padding(.horizontal, 16)
.padding(.vertical, 14)
.background(.ultraThinMaterial)
}

View File

@@ -1274,84 +1274,84 @@ struct EntryListView: View {
// MARK: - Pattern Style (Mood icons as repeating background)
private var patternStyle: some View {
ZStack {
HStack(spacing: 16) {
// Large mood icon
ZStack {
Circle()
.fill(isMissing ? Color.gray.opacity(0.2) : moodColor)
.frame(width: 54, height: 54)
imagePack.icon(forMood: entry.mood)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 28, height: 28)
.foregroundColor(.white)
}
VStack(alignment: .leading, spacing: 6) {
Text(entry.forDate, format: .dateTime.weekday(.wide).day())
.font(.system(size: 17, weight: .semibold))
.foregroundColor(textColor)
if isMissing {
Text("No mood recorded")
.font(.system(size: 14))
.foregroundColor(.gray)
} else {
Text(entry.moodString)
.font(.system(size: 15, weight: .medium))
.foregroundColor(moodColor)
}
}
.padding(.horizontal, 12)
.padding(.vertical, 8)
.background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 10))
Spacer()
Text(entry.forDate, format: .dateTime.month(.abbreviated))
.font(.system(size: 12, weight: .medium))
.foregroundColor(textColor.opacity(0.6))
.padding(.horizontal, 10)
.padding(.vertical, 6)
.background(.ultraThinMaterial, in: Capsule())
}
.padding(16)
.frame(height: 86)
.background {
// Repeating mood icon pattern background
GeometryReader { geo in
let iconSize: CGFloat = 24
let spacing: CGFloat = 32
let iconSize: CGFloat = 20
let spacing: CGFloat = 28
let cols = Int(geo.size.width / spacing) + 2
let rows = Int(geo.size.height / spacing) + 2
ForEach(0..<rows, id: \.self) { row in
ForEach(0..<cols, id: \.self) { col in
imagePack.icon(forMood: entry.mood)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: iconSize, height: iconSize)
.foregroundColor(isMissing ? Color.gray.opacity(0.08) : moodColor.opacity(0.12))
.position(
x: CGFloat(col) * spacing + (row.isMultiple(of: 2) ? spacing/2 : 0),
y: CGFloat(row) * spacing
)
}
}
}
.clipped()
// Content card
HStack(spacing: 16) {
// Large mood icon
ZStack {
Circle()
.fill(isMissing ? Color.gray.opacity(0.2) : moodColor)
.frame(width: 54, height: 54)
// Base background color
RoundedRectangle(cornerRadius: 16)
.fill(colorScheme == .dark ? Color(.systemGray6) : Color(.systemGray6).opacity(0.5))
imagePack.icon(forMood: entry.mood)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 28, height: 28)
.foregroundColor(.white)
}
VStack(alignment: .leading, spacing: 6) {
Text(entry.forDate, format: .dateTime.weekday(.wide).day())
.font(.system(size: 17, weight: .semibold))
.foregroundColor(textColor)
if isMissing {
Text("No mood recorded")
.font(.system(size: 14))
.foregroundColor(.gray)
} else {
Text(entry.moodString)
.font(.system(size: 15, weight: .medium))
.foregroundColor(moodColor)
// Pattern overlay
ForEach(0..<rows, id: \.self) { row in
ForEach(0..<cols, id: \.self) { col in
imagePack.icon(forMood: entry.mood)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: iconSize, height: iconSize)
.foregroundColor(isMissing ? Color.gray.opacity(0.15) : moodColor.opacity(0.2))
.position(
x: CGFloat(col) * spacing + (row.isMultiple(of: 2) ? spacing/2 : 0),
y: CGFloat(row) * spacing
)
}
}
}
Spacer()
Text(entry.forDate, format: .dateTime.month(.abbreviated))
.font(.system(size: 12, weight: .medium))
.foregroundColor(textColor.opacity(0.4))
.padding(.horizontal, 10)
.padding(.vertical, 6)
.background(
Capsule()
.fill(textColor.opacity(0.08))
)
}
.padding(16)
.background(
RoundedRectangle(cornerRadius: 16)
.fill(colorScheme == .dark ? Color(.systemGray6).opacity(0.95) : Color.white.opacity(0.95))
)
.clipShape(RoundedRectangle(cornerRadius: 16))
}
.frame(height: 86)
.clipShape(RoundedRectangle(cornerRadius: 16))
.overlay(
RoundedRectangle(cornerRadius: 16)
.stroke(isMissing ? Color.gray.opacity(0.15) : moodColor.opacity(0.25), lineWidth: 1)
.stroke(isMissing ? Color.gray.opacity(0.15) : moodColor.opacity(0.3), lineWidth: 1)
)
}