crossmate

A collaborative crossword app for iOS
Log | Files | Refs | LICENSE

commit 41fa51ed998a1b2678d2766327a886586588979a
parent 8c6d0f8187fc517e00471d446516db3a00f59afa
Author: Michael Camilleri <[email protected]>
Date:   Sat, 20 Jun 2026 10:08:41 +0900

Hint that the Share Game friend row scrolls

The row of prior friends in the Share Game sheet scrolls horizontally,
but nothing signalled that more friends might sit past the trailing
edge. A whole number of avatars could line up flush with the edge,
leaving the row looking complete when it was not.

This commit masks a fixed strip at the trailing edge with a fade, so the
row always reads as scrollable however the avatars happen to fall, and
gives the scroll content a trailing margin so the last item — the 'All'
button — can scroll further clear of the fade rather than stopping
dimmed beneath it.

Co-Authored-By: Claude Opus 4.8 <[email protected]>

Diffstat:
MCrossmate/Views/GameList/GameShareItem.swift | 24++++++++++++++++++++++++
1 file changed, 24 insertions(+), 0 deletions(-)

diff --git a/Crossmate/Views/GameList/GameShareItem.swift b/Crossmate/Views/GameList/GameShareItem.swift @@ -29,6 +29,11 @@ struct GameShareSheet: View { Array(friends.prefix(4)) } + /// Width of the trailing scroll fade. The scroll content gets a matching + /// trailing margin so the last item can scroll clear of the fade instead of + /// stopping flush beneath it. + private static let trailingFadeWidth: CGFloat = 72 + var body: some View { NavigationStack { List { @@ -141,6 +146,24 @@ struct GameShareSheet: View { .frame(maxWidth: .infinity) .padding(.vertical, 2) } + // Fade a fixed strip at the trailing edge so the row + // always reads as scrollable, even when a whole number + // of friends lines up flush with the edge. + .mask( + HStack(spacing: 0) { + Rectangle() + LinearGradient( + colors: [.black, .clear], + startPoint: .leading, + endPoint: .trailing + ) + .frame(width: Self.trailingFadeWidth) + } + ) + // Be proportional to the trailing fade width so the last item can + // scroll clear of the fade instead of stopping flush + // beneath it. + .contentMargins(.trailing, (Self.trailingFadeWidth / 2), for: .scrollContent) .listRowInsets(EdgeInsets(top: 8, leading: 16, bottom: 8, trailing: 16)) } } @@ -212,6 +235,7 @@ struct GameShareSheet: View { } .frame(width: 108, height: 88) } + .buttonStyle(.plain) .disabled(authorID.isEmpty || invitingAuthorID != nil || wasInvited || (isInviteLimitReached && !wasInvited)) }