fix(apple/iOS): larger host cards — touch-first sizing
ci / rust (push) Has been cancelled

The 160 pt grid minimum packed five small cards per iPad row. iOS columns now use a
280 pt minimum (one full-width card on iPhone portrait, 3–4 generous cards on iPad)
and the card content scales with it: 56 pt icon, title3 name, taller padding. macOS
keeps its compact 180–240 pt cards.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-11 12:52:45 +02:00
parent bce820ec67
commit 0b735ac632
@@ -160,12 +160,13 @@ struct ContentView: View {
} }
/// macOS caps card width (a huge window shouldn't yield huge cards); on iOS the /// macOS caps card width (a huge window shouldn't yield huge cards); on iOS the
/// columns FILL the width so the cards stay edge-aligned with the title and bars. /// columns FILL the width so the cards stay edge-aligned with the title and bars
/// sized touch-first: one column on iPhone portrait, 34 generous cards on iPad.
private var gridColumns: [GridItem] { private var gridColumns: [GridItem] {
#if os(macOS) #if os(macOS)
[GridItem(.adaptive(minimum: 180, maximum: 240), spacing: 16)] [GridItem(.adaptive(minimum: 180, maximum: 240), spacing: 16)]
#else #else
[GridItem(.adaptive(minimum: 160), spacing: 16)] [GridItem(.adaptive(minimum: 280), spacing: 16)]
#endif #endif
} }
@@ -203,23 +204,34 @@ struct ContentView: View {
private func hostCard(_ host: StoredHost) -> some View { private func hostCard(_ host: StoredHost) -> some View {
let isConnecting = model.phase == .connecting && model.activeHost?.id == host.id let isConnecting = model.phase == .connecting && model.activeHost?.id == host.id
#if os(iOS)
let iconSize: CGFloat = 56
let iconBox: CGFloat = 76
let cardPadding: CGFloat = 28
let nameFont = Font.title3.weight(.semibold)
#else
let iconSize: CGFloat = 42
let iconBox: CGFloat = 56
let cardPadding: CGFloat = 18
let nameFont = Font.headline
#endif
return Button { return Button {
connect(host) connect(host)
} label: { } label: {
VStack(spacing: 10) { VStack(spacing: 10) {
ZStack { ZStack {
Image(systemName: "play.display") Image(systemName: "play.display")
.font(.system(size: 42, weight: .light)) .font(.system(size: iconSize, weight: .light))
.foregroundStyle(.tint) .foregroundStyle(.tint)
.opacity(isConnecting ? 0.3 : 1) .opacity(isConnecting ? 0.3 : 1)
if isConnecting { if isConnecting {
ProgressView() ProgressView()
} }
} }
.frame(height: 56) .frame(height: iconBox)
VStack(spacing: 2) { VStack(spacing: 2) {
Text(host.displayName) Text(host.displayName)
.font(.headline) .font(nameFont)
.lineLimit(1) .lineLimit(1)
HStack(spacing: 4) { HStack(spacing: 4) {
if host.pinnedSHA256 != nil { if host.pinnedSHA256 != nil {
@@ -235,7 +247,7 @@ struct ContentView: View {
} }
} }
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
.padding(.vertical, 18) .padding(.vertical, cardPadding)
.padding(.horizontal, 12) .padding(.horizontal, 12)
.background(.regularMaterial, in: RoundedRectangle(cornerRadius: 14)) .background(.regularMaterial, in: RoundedRectangle(cornerRadius: 14))
} }