Skip to content

feat(game): New invite sheet, who first - #262

Merged
arrzdev merged 4 commits into
mainfrom
feat/new-invite-sheet
Nov 2, 2026
Merged

arrzdev merged 4 commits into
mainfrom
feat/new-invite-sheet

Conversation

@arrzdev

@arrzdev arrzdev commented Nov 1, 2026

Copy link
Copy Markdown
Owner

What and why

The New invite sheet asks who first. Recent opponents show as chips (photo or initials, up to four, most recent first), then a field for anybody else, then the link as one card, then the opening and side folded into a one-line summary. Change opens a game panel with the carousel and side picker; Done returns. The send button names the person ("Invite joana_p").

  • Recent opponents are derived on the client from the active and finished games the online page already loads (recentOpponentsOf): distinct by name, never yourself, most recent first, four at most. No new request or endpoint.
  • The link card makes the link and hands it to the share sheet (phones) or the clipboard (desktop), keeps its height from idle to made, and retries on a tap when the request fails.
  • Sheet gets an opt-in pinFooter, so on a 320x460 phone the send stays on screen while the body scrolls.
  • Copy in en, pt and de. The other locales fall back to English until they are translated. de api_invite_exists is shortened so the reserved error line stays on one line.
  • Not in this change: pre-marking people already invited.

How to verify

  • pnpm exec playwright test e2e/invite-composer.spec.ts e2e/modal-layout.spec.ts e2e/invite-copy-link.spec.ts on chromium and webkit-iphone.
  • Unit: recent-opponents.test.ts.
  • By hand: open /online?invite=new as a player with games (chips), and as a new account (no chips, label "Opponent").
  • The composer's sections sit 12px apart inside (who, link and terms), so modal-layout.spec.ts no longer runs the two-size rhythm check on it; it still checks shift, clipping and scrolling.

UI quality gate

  • No layout shift: click, open, hover, focus, loading → loaded, font swap
  • Space reserved for text that appears later (status, error, feedback)
  • No hard-clipped text: ellipsis or wrap, never cut mid-character
  • No text hidden by its container, the viewport, or a sticky bar
  • Modals and dialogs fit without scrolling at 375x667
  • Focus ring fully visible on every control (not cut by overflow)
  • Touch targets ≥ 44x44 on phone
  • Empty, loading and error states exist and look designed
  • Every network action shows a pending state: spinner, busy, disabled, one submit
  • Button labels stay on one line at 320 in the longest locale (the send wraps to at most two lines by design; the other buttons are one line)
  • Checked at 375x667, 402x710 and desktop, Chromium + WebKit (plus 375x548, 390x664, 320x460)
  • New UI spec uses the shift and clipped-text helpers

- up to four distinct names, most recent first, never the player
- no new request: both lists are the hub's own
- recent opponents as one radio group, a field for anybody else
- the link as a card, the opening and side folded into a summary row
- Change opens a game panel; Sheet can pin its footer on a phone
- en, pt, de copy; the other locales fall back to en until translated
- layout shift, clipped text and scrolling at 375x667, 375x548, 390x664, 320x460
- chip, typed-name, game panel, link failure and loading states

@arrzdev arrzdev left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approve. Code reviewed against the design and the spec acceptance criteria; CI green (checks, e2e 1-3, gate).

Non-blocking notes for a follow-up:

  • useOnlineHome: recentOpponents is computed as soon as either games list lands, so if the active list arrives first the chips can be replaced when the finished list lands (row height stays, the names can change under the thumb). Waiting for both lists unless one failed would make the first set of chips final.
  • InviteLinkCard.handleCopy: the setTimeout that resets the copied check is not cleared on unmount (the card remounts when the terms change).

@arrzdev
arrzdev merged commit d3d1616 into main Nov 2, 2026
8 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant