Trends: anchor empty/loading/error states to the top of the chart slot

The no-data states previously floated or centred vertically (Spacer
sandwich), so the sheet rendered them halfway down the page while the
chart-with-data anchors to the top. All chartArea states now share one
top-aligned container that fills the space below the pickers — the
empty state sits exactly where the chart will render, and the layout no
longer jumps between states. 83 tests, Release build green.
This commit is contained in:
FuelBoard Contributor
2026-08-15 12:30:25 +01:00
parent d1fbac3f05
commit 54aca14fd4
+30 -24
View File
@@ -147,32 +147,38 @@ struct TrendsView: View {
@ViewBuilder @ViewBuilder
private var chartArea: some View { private var chartArea: some View {
if isLoading { // Every state anchors to the TOP of the chart slot the same spot the
Spacer() // chart occupies when data exists. The empty/loading/error states must
ProgressView("Fetching price history…") // not float or centre in the sheet, or the layout jumps between states.
Spacer() Group {
} else if loadFailed { if isLoading {
Spacer() VStack(spacing: 12) {
VStack(spacing: 10) { ProgressView("Fetching price history…")
Image(systemName: "wifi.exclamationmark") }
.font(.system(size: 32)) .padding(.top, 24)
.foregroundStyle(.secondary) } else if loadFailed {
Text("Couldn't load price history") VStack(spacing: 10) {
.font(.headline) Image(systemName: "wifi.exclamationmark")
Button("Retry") { Task { await load() } } .font(.system(size: 32))
.buttonStyle(.bordered) .foregroundStyle(.secondary)
} Text("Couldn't load price history")
Spacer() .font(.headline)
} else if !hasAnyData { Button("Retry") { Task { await load() } }
emptyState .buttonStyle(.bordered)
} else if !hasEnoughData { }
emptyState // single point nothing to draw yet .padding(.top, 24)
} else { } else if !hasAnyData {
VStack(spacing: 12) { emptyState
chart } else if !hasEnoughData {
legend emptyState // single point nothing to draw yet
} else {
VStack(spacing: 12) {
chart
legend
}
} }
} }
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
} }
private var emptyState: some View { private var emptyState: some View {