More info sheet: overlay tap target on the map, copy line below the address, capsule left

This commit is contained in:
FuelBoard Contributor
2026-10-14 11:22:02 +01:00
parent 94d66f4c30
commit 8bb08ebe6b
2 changed files with 46 additions and 37 deletions
-1
View File
@@ -118,7 +118,6 @@ struct FuelSavingsSummaryView: View {
// matched neither the listing nor each other. // matched neither the listing nor each other.
VStack(alignment: .leading, spacing: 10) { VStack(alignment: .leading, spacing: 10) {
capsule(for: result, compact: false) capsule(for: result, compact: false)
.frame(maxWidth: .infinity, alignment: .trailing)
.accessibilityLabel(accessibilityHeadline(for: result)) .accessibilityLabel(accessibilityHeadline(for: result))
LabeledContent("Your fill-up", value: amountText) LabeledContent("Your fill-up", value: amountText)
LabeledContent("Fuel you'll receive", value: String(format: "%.2f litres", result.fillLitres)) LabeledContent("Fuel you'll receive", value: String(format: "%.2f litres", result.fillLitres))
+25 -15
View File
@@ -84,13 +84,17 @@ struct StationDetailView: View {
NavigationStack { NavigationStack {
List { List {
Section { Section {
// Tapping the map opens the same Apple Maps directions the // Tapping anywhere on the map opens the same Apple Maps
// Directions button below opens. The Map still ignores // directions the Directions button below opens.
// hit testing itself so the wrapping Button — not MapKit — //
// owns the tap; the map is a preview, not something to pan. // The tap target is an OVERLAY Button laid ON TOP of the
Button { // Map, not a Button wrapping it. A Map runs its own UIKit
openDirections() // view, and inside a List row the wrapped-Map form left the
} label: { // card untappable — the touch never reached the button. An
// overlay sits above the map, owns an explicit rounded-rect
// content shape, and cannot be intercepted by MapKit. The
// Map itself stays non-interactive: it is a preview, not
// something to pan.
Map(position: .constant(.region(MKCoordinateRegion( Map(position: .constant(.region(MKCoordinateRegion(
center: stationCoordinate, center: stationCoordinate,
span: MKCoordinateSpan(latitudeDelta: 0.02, longitudeDelta: 0.02) span: MKCoordinateSpan(latitudeDelta: 0.02, longitudeDelta: 0.02)
@@ -101,16 +105,19 @@ struct StationDetailView: View {
.frame(height: 180) .frame(height: 180)
.clipShape(RoundedRectangle(cornerRadius: 12)) .clipShape(RoundedRectangle(cornerRadius: 12))
.allowsHitTesting(false) .allowsHitTesting(false)
.overlay {
Button {
openDirections()
} label: {
Color.clear
.contentShape(RoundedRectangle(cornerRadius: 12))
} }
.buttonStyle(.plain) .buttonStyle(.plain)
// The hit area is declared on the BUTTON, not inside the
// label: the label's Map has hit testing switched off, so
// without this the card could fall through to the row.
.contentShape(RoundedRectangle(cornerRadius: 12))
.accessibilityLabel(String(localized: "Directions to \(station.name)", .accessibilityLabel(String(localized: "Directions to \(station.name)",
comment: "Accessibility label for the tappable map preview in the More info sheet")) comment: "Accessibility label for the tappable map preview in the More info sheet"))
.accessibilityHint(String(localized: "Opens Apple Maps with driving directions", .accessibilityHint(String(localized: "Opens Apple Maps with driving directions",
comment: "Accessibility hint for the tappable map preview in the More info sheet")) comment: "Accessibility hint for the tappable map preview in the More info sheet"))
}
.listRowInsets(EdgeInsets()) .listRowInsets(EdgeInsets())
} }
Section { Section {
@@ -121,28 +128,31 @@ struct StationDetailView: View {
// //
// The whole row is a copy control: it puts JUST the postcode // The whole row is a copy control: it puts JUST the postcode
// on the clipboard so it can be pasted into another // on the clipboard so it can be pasted into another
// navigation app. The trailing icon marks it tappable and // navigation app. The copy glyph and its "Copied"
// becomes the "Copied" confirmation for a couple of seconds. // confirmation share a SECOND line that is always there, so
// the confirmation can never reflow the address above it.
Button { Button {
copyPostcode() copyPostcode()
} label: { } label: {
VStack(alignment: .leading, spacing: 6) {
HStack(alignment: .firstTextBaseline, spacing: 8) { HStack(alignment: .firstTextBaseline, spacing: 8) {
Text("Address") Text("Address")
Spacer(minLength: 8) Spacer(minLength: 8)
Text(addressLine) Text(addressLine)
.multilineTextAlignment(.trailing) .multilineTextAlignment(.trailing)
.foregroundStyle(.secondary) .foregroundStyle(.secondary)
}
HStack(spacing: 4) { HStack(spacing: 4) {
Spacer(minLength: 0)
if showingCopied { if showingCopied {
Text("Copied") Text("Copied")
.font(.footnote.weight(.semibold))
.foregroundStyle(.green) .foregroundStyle(.green)
.transition(.opacity) .transition(.opacity)
} }
Image(systemName: showingCopied ? "checkmark" : "doc.on.doc") Image(systemName: showingCopied ? "checkmark" : "doc.on.doc")
.font(.footnote.weight(.semibold))
.foregroundStyle(showingCopied ? Color.green : Color.secondary) .foregroundStyle(showingCopied ? Color.green : Color.secondary)
} }
.font(.footnote.weight(.semibold))
} }
} }
.buttonStyle(.plain) .buttonStyle(.plain)