Key sheet: card redesign matching the tip section
Price-rating legend now renders as five accent cards (tip-section style): Best value (green, checkmark) / Okay (orange, equal) / Pricey (red, exclamation) each with a RAG dot + threshold (≤1.5p / ≤4p / >4p) on the right in the row's accent colour; TOP (blue capsule) and star (yellow) as accent cards below a divider. Footer: 'Colours match each station's rating on the list'. Copy split into title/blurb keys in Localizable. Sheet chrome (medium detent, Done, info button) unchanged.
This commit is contained in:
@@ -193,39 +193,54 @@ struct StationsView: View {
|
||||
.sheet(isPresented: $showKey) {
|
||||
NavigationStack {
|
||||
List {
|
||||
Section("Key") {
|
||||
HStack(spacing: 8) {
|
||||
Circle().fill(.green).frame(width: 12, height: 12)
|
||||
Text("Best value — within 1.5p of the cheapest")
|
||||
.font(.caption)
|
||||
}
|
||||
HStack(spacing: 8) {
|
||||
Circle().fill(.orange).frame(width: 12, height: 12)
|
||||
Text("Okay — within 4p of the cheapest")
|
||||
.font(.caption)
|
||||
}
|
||||
HStack(spacing: 8) {
|
||||
Circle().fill(.red).frame(width: 12, height: 12)
|
||||
Text("Pricey — more than 4p over the cheapest")
|
||||
.font(.caption)
|
||||
}
|
||||
HStack(spacing: 8) {
|
||||
Text("TOP")
|
||||
.font(.caption2.bold())
|
||||
.padding(.horizontal, 5)
|
||||
.padding(.vertical, 1)
|
||||
.background(Capsule().fill(.blue.opacity(0.15)))
|
||||
.foregroundStyle(.blue)
|
||||
Text("Top result for the current sort")
|
||||
.font(.caption)
|
||||
}
|
||||
HStack(spacing: 8) {
|
||||
Image(systemName: "star.fill")
|
||||
.font(.caption2)
|
||||
.foregroundStyle(.yellow)
|
||||
Text("Star a station to add it to Favourites")
|
||||
.font(.caption)
|
||||
Section {
|
||||
VStack(spacing: 10) {
|
||||
keyCard(
|
||||
icon: "checkmark.circle.fill", color: .green,
|
||||
title: "Best value", blurb: "Within 1.5p of the cheapest",
|
||||
threshold: "≤1.5p")
|
||||
keyCard(
|
||||
icon: "equal.circle.fill", color: .orange,
|
||||
title: "Okay", blurb: "Within 4p of the cheapest",
|
||||
threshold: "≤4p")
|
||||
keyCard(
|
||||
icon: "exclamationmark.circle.fill", color: .red,
|
||||
title: "Pricey", blurb: "More than 4p over the cheapest",
|
||||
threshold: ">4p")
|
||||
Rectangle()
|
||||
.fill(Color(.separator))
|
||||
.frame(height: 0.5)
|
||||
.padding(.vertical, 2)
|
||||
HStack(spacing: 12) {
|
||||
Text("TOP")
|
||||
.font(.caption2.bold())
|
||||
.padding(.horizontal, 7)
|
||||
.padding(.vertical, 3)
|
||||
.background(Capsule().fill(.blue.opacity(0.16)))
|
||||
.foregroundStyle(.blue)
|
||||
Text("Top result for the current sort")
|
||||
.font(.subheadline.weight(.semibold))
|
||||
Spacer(minLength: 0)
|
||||
}
|
||||
.keyCardFill(color: .blue)
|
||||
HStack(spacing: 12) {
|
||||
Image(systemName: "star.fill")
|
||||
.font(.title3)
|
||||
.foregroundStyle(.yellow)
|
||||
.frame(width: 34)
|
||||
Text("Star a station to add it to Favourites")
|
||||
.font(.subheadline.weight(.semibold))
|
||||
Spacer(minLength: 0)
|
||||
}
|
||||
.keyCardFill(color: .yellow)
|
||||
Text("Colours match each station's rating on the list")
|
||||
.font(.footnote)
|
||||
.foregroundStyle(.secondary)
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.top, 4)
|
||||
}
|
||||
.listRowBackground(Color.clear)
|
||||
.listRowInsets(EdgeInsets(top: 4, leading: 16, bottom: 4, trailing: 16))
|
||||
}
|
||||
}
|
||||
.navigationTitle("Key")
|
||||
@@ -240,6 +255,47 @@ struct StationsView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// One price-rating card for the Key sheet: accent icon, title + blurb,
|
||||
/// and the rating threshold in the accent colour (mirrors the tip cards).
|
||||
private func keyCard(icon: String, color: Color, title: String, blurb: String, threshold: String) -> some View {
|
||||
HStack(spacing: 12) {
|
||||
Image(systemName: icon)
|
||||
.font(.title3)
|
||||
.foregroundStyle(color)
|
||||
.frame(width: 34)
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(LocalizedStringKey(title)).font(.headline)
|
||||
Text(LocalizedStringKey(blurb))
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
Spacer(minLength: 8)
|
||||
HStack(spacing: 6) {
|
||||
Circle().fill(color).frame(width: 10, height: 10)
|
||||
Text(threshold)
|
||||
.font(.headline.weight(.bold))
|
||||
.foregroundStyle(color)
|
||||
.monospacedDigit()
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 14)
|
||||
.padding(.vertical, 10)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.keyCardFill(color: color)
|
||||
}
|
||||
}
|
||||
|
||||
/// Card background shared by the Key sheet cards — subtle accent tint over
|
||||
/// the grouped background, matching the tip-section card style.
|
||||
private extension View {
|
||||
func keyCardFill(color: Color) -> some View {
|
||||
background(
|
||||
RoundedRectangle(cornerRadius: 12)
|
||||
.fill(Color(.secondarySystemGroupedBackground))
|
||||
.overlay(RoundedRectangle(cornerRadius: 12).fill(color.opacity(0.08)))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Fuel-type iconography (app target only — FuelStore.swift is Foundation-only)
|
||||
|
||||
Reference in New Issue
Block a user