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) {
|
.sheet(isPresented: $showKey) {
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
List {
|
List {
|
||||||
Section("Key") {
|
Section {
|
||||||
HStack(spacing: 8) {
|
VStack(spacing: 10) {
|
||||||
Circle().fill(.green).frame(width: 12, height: 12)
|
keyCard(
|
||||||
Text("Best value — within 1.5p of the cheapest")
|
icon: "checkmark.circle.fill", color: .green,
|
||||||
.font(.caption)
|
title: "Best value", blurb: "Within 1.5p of the cheapest",
|
||||||
}
|
threshold: "≤1.5p")
|
||||||
HStack(spacing: 8) {
|
keyCard(
|
||||||
Circle().fill(.orange).frame(width: 12, height: 12)
|
icon: "equal.circle.fill", color: .orange,
|
||||||
Text("Okay — within 4p of the cheapest")
|
title: "Okay", blurb: "Within 4p of the cheapest",
|
||||||
.font(.caption)
|
threshold: "≤4p")
|
||||||
}
|
keyCard(
|
||||||
HStack(spacing: 8) {
|
icon: "exclamationmark.circle.fill", color: .red,
|
||||||
Circle().fill(.red).frame(width: 12, height: 12)
|
title: "Pricey", blurb: "More than 4p over the cheapest",
|
||||||
Text("Pricey — more than 4p over the cheapest")
|
threshold: ">4p")
|
||||||
.font(.caption)
|
Rectangle()
|
||||||
}
|
.fill(Color(.separator))
|
||||||
HStack(spacing: 8) {
|
.frame(height: 0.5)
|
||||||
Text("TOP")
|
.padding(.vertical, 2)
|
||||||
.font(.caption2.bold())
|
HStack(spacing: 12) {
|
||||||
.padding(.horizontal, 5)
|
Text("TOP")
|
||||||
.padding(.vertical, 1)
|
.font(.caption2.bold())
|
||||||
.background(Capsule().fill(.blue.opacity(0.15)))
|
.padding(.horizontal, 7)
|
||||||
.foregroundStyle(.blue)
|
.padding(.vertical, 3)
|
||||||
Text("Top result for the current sort")
|
.background(Capsule().fill(.blue.opacity(0.16)))
|
||||||
.font(.caption)
|
.foregroundStyle(.blue)
|
||||||
}
|
Text("Top result for the current sort")
|
||||||
HStack(spacing: 8) {
|
.font(.subheadline.weight(.semibold))
|
||||||
Image(systemName: "star.fill")
|
Spacer(minLength: 0)
|
||||||
.font(.caption2)
|
}
|
||||||
.foregroundStyle(.yellow)
|
.keyCardFill(color: .blue)
|
||||||
Text("Star a station to add it to Favourites")
|
HStack(spacing: 12) {
|
||||||
.font(.caption)
|
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")
|
.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)
|
// MARK: - Fuel-type iconography (app target only — FuelStore.swift is Foundation-only)
|
||||||
|
|||||||
@@ -23,11 +23,15 @@
|
|||||||
"Show %lld more (%lld remaining)" = "Show %lld more (%lld remaining)";
|
"Show %lld more (%lld remaining)" = "Show %lld more (%lld remaining)";
|
||||||
"All %lld stations shown" = "All %lld stations shown";
|
"All %lld stations shown" = "All %lld stations shown";
|
||||||
"Key" = "Key";
|
"Key" = "Key";
|
||||||
"Best value — within 1.5p of the cheapest" = "Best value — within 1.5p of the cheapest";
|
"Best value" = "Best value";
|
||||||
"Okay — within 4p of the cheapest" = "Okay — within 4p of the cheapest";
|
"Within 1.5p of the cheapest" = "Within 1.5p of the cheapest";
|
||||||
"Pricey — more than 4p over the cheapest" = "Pricey — more than 4p over the cheapest";
|
"Okay" = "Okay";
|
||||||
|
"Within 4p of the cheapest" = "Within 4p of the cheapest";
|
||||||
|
"Pricey" = "Pricey";
|
||||||
|
"More than 4p over the cheapest" = "More than 4p over the cheapest";
|
||||||
"Top result for the current sort" = "Top result for the current sort";
|
"Top result for the current sort" = "Top result for the current sort";
|
||||||
"Star a station to add it to Favourites" = "Star a station to add it to Favourites";
|
"Star a station to add it to Favourites" = "Star a station to add it to Favourites";
|
||||||
|
"Colours match each station's rating on the list" = "Colours match each station's rating on the list";
|
||||||
|
|
||||||
/* Favourites tab */
|
/* Favourites tab */
|
||||||
"No favourites yet" = "No favourites yet";
|
"No favourites yet" = "No favourites yet";
|
||||||
|
|||||||
Reference in New Issue
Block a user