Revert station capsule layout changes
This commit is contained in:
+31
-17
@@ -1842,13 +1842,26 @@ struct StationRow: View {
|
||||
/// 22pt keeps the price the row's loudest element after the station name.
|
||||
@ScaledMetric(relativeTo: .title2) private var priceSize: CGFloat = 22
|
||||
|
||||
/// The identity column's share of the ROW, for every row and both price
|
||||
/// styles. The mockup's divider sits at ~53% of its row; this is that ratio,
|
||||
/// held per row rather than derived from the row's text — the point is that
|
||||
/// the hairline, the price axis and the star cannot move as the list scrolls.
|
||||
/// The price column takes the remainder, and its savings capsule scales down
|
||||
/// instead of widening the column and dragging the hairline with it.
|
||||
///
|
||||
/// One value for both price styles: the star used to sit at the end of the
|
||||
/// price line and hold ~28pt of the price column, so the wide form `£1.58⁷/L`
|
||||
/// — ~20pt wider than the bare `158.7` at the same point size — did not fit on
|
||||
/// a 393pt screen. With the star now under the station logo the price column
|
||||
/// has that width back, so the identity column no longer has to give width up
|
||||
/// in pounds & pence, and names keep the same room in both styles.
|
||||
private static let leftSectionShare: CGFloat = 0.52
|
||||
|
||||
/// The comparison label sits beside the capsule only where the row is wide
|
||||
/// enough for both (regular width). On an iPhone the mockup's canvas is
|
||||
/// wider than the whole screen, so the label drops under the capsule rather
|
||||
/// than starving the station name.
|
||||
@Environment(\.horizontalSizeClass) private var sizeClass
|
||||
@Environment(\.dynamicTypeSize) private var dynamicTypeSize
|
||||
|
||||
private var ragColor: Color {
|
||||
guard let price = station.prices[fuel], let baselinePrice else { return .gray }
|
||||
@@ -1918,9 +1931,13 @@ struct StationRow: View {
|
||||
// the detail sheet instead of being repeated on every row.
|
||||
HStack(alignment: .center, spacing: 12) {
|
||||
// LEFT SECTION — station identity: brand logo, then name, address and
|
||||
// distance. This section yields horizontal space to the financial
|
||||
// column first: a truncated station identity is recoverable from the
|
||||
// detail sheet, while a truncated saving is materially misleading.
|
||||
// distance. Given a FIXED SHARE of the row (~52%, the mockup's ratio)
|
||||
// rather than sizing to its content: sized to content, this column
|
||||
// grew and shrank with each row's badge and savings copy, which moved
|
||||
// the hairline 23pt between adjacent rows (x767 on a BEST VALUE row,
|
||||
// x699 on a "costs more" row) — so the divider and the price axis
|
||||
// both jumped sideways as the list scrolled. One share for every row
|
||||
// puts them on a single vertical line down the whole list.
|
||||
HStack(alignment: .top, spacing: 12) {
|
||||
// The logo, with the favourite star directly beneath it. Moving
|
||||
// the star out of the price line is what gives the price column
|
||||
@@ -1955,15 +1972,16 @@ struct StationRow: View {
|
||||
|
||||
// Name, full address, distance
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
// Keep the established compact row. Long names yield space
|
||||
// to the complete price/verdict column rather than wrapping
|
||||
// and forcing a financial amount to truncate.
|
||||
// The name WRAPS instead of truncating: the row is tall
|
||||
// enough now, and a name cut to "Z A Service Stat…" cannot
|
||||
// be told apart from the station next door. Baseline
|
||||
// alignment keeps the notice symbols on the name's FIRST
|
||||
// line instead of floating beside a two-line name.
|
||||
HStack(alignment: .firstTextBaseline, spacing: 6) {
|
||||
Text(station.name)
|
||||
.font(.headline)
|
||||
.multilineTextAlignment(.leading)
|
||||
.lineLimit(1)
|
||||
.truncationMode(.tail)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
ForEach(StationNotice.notices(for: station)) { notice in
|
||||
Image(systemName: notice.symbolName)
|
||||
.font(.caption2.weight(.semibold))
|
||||
@@ -2001,10 +2019,11 @@ struct StationRow: View {
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.layoutPriority(0)
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.layoutPriority(0)
|
||||
.containerRelativeFrame(.horizontal, alignment: .leading) { length, _ in
|
||||
length * Self.leftSectionShare
|
||||
}
|
||||
|
||||
// 1pt hairline between the two sections. Inset top and bottom so it
|
||||
// spans the row's content without touching the row edges, and
|
||||
@@ -2056,12 +2075,7 @@ struct StationRow: View {
|
||||
savingsCapsule(result)
|
||||
}
|
||||
}
|
||||
// The verdict owns its natural one-line width at normal Dynamic Type
|
||||
// sizes. The identity column compresses first, preventing "Approx.
|
||||
// Save £…" while keeping the same two-column visual design.
|
||||
.fixedSize(horizontal: !dynamicTypeSize.isAccessibilitySize,
|
||||
vertical: false)
|
||||
.layoutPriority(1)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
// The spec's ~20-24pt of air between the divider and the price
|
||||
// column: the row's own 12pt spacing plus this 10pt.
|
||||
.padding(.leading, 10)
|
||||
|
||||
@@ -105,26 +105,25 @@ struct FuelSavingsCapsule: View {
|
||||
let result: FuelSavingsResult
|
||||
var compact: Bool = true
|
||||
|
||||
@Environment(\.dynamicTypeSize) private var dynamicTypeSize
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: compact ? 3 : 5) {
|
||||
Image(systemName: Self.symbol(for: result.status))
|
||||
.accessibilityHidden(true)
|
||||
Text(result.capsuleHeadline())
|
||||
// Financial verdicts stay complete and single-line at ordinary
|
||||
// text sizes. Accessibility sizes may use a second line rather
|
||||
// than clipping, shrinking or losing the amount to an ellipsis.
|
||||
.lineLimit(dynamicTypeSize.isAccessibilitySize ? 2 : 1)
|
||||
.fixedSize(horizontal: !dynamicTypeSize.isAccessibilitySize,
|
||||
vertical: true)
|
||||
.lineLimit(1)
|
||||
// Measured on a 393pt screen: the capsule is handed ~101pt, of
|
||||
// which the icon, its spacing and the 8pt padding either side
|
||||
// take 32pt, leaving ~69pt for the text. "Closest station" needs
|
||||
// ~90pt at full size, so a 0.8 floor — 72pt — could not reach it
|
||||
// and the row showed "Closest stati…" instead. 0.7 leaves ~63pt,
|
||||
// which clears it at ~10pt type: scaled, never truncated.
|
||||
.minimumScaleFactor(0.7)
|
||||
}
|
||||
.font(compact ? .caption.weight(.semibold) : .headline)
|
||||
.foregroundStyle(Self.color(for: result.status))
|
||||
.padding(.horizontal, compact ? 8 : 12)
|
||||
.padding(.vertical, compact ? 4 : 7)
|
||||
.background(Capsule().fill(Self.color(for: result.status).opacity(0.15)))
|
||||
.accessibilityElement(children: .combine)
|
||||
}
|
||||
|
||||
/// Verdict colour: green save, red worse off, grey break even, blue
|
||||
|
||||
Reference in New Issue
Block a user