feat: TASK-22452 rework receipts and processing screens - #3225
Conversation
the bank row jumped its IconStack to 80px, which breaks the ListItem trailing vocabulary and the 16/20/24 icon scale. the invited-by note also forced a 24px top margin with !important over the list's own 8px gap; the container spacing owns it now. TASK-22452
two warning texts painted themselves from the raw ramp: yellow-900 on the recipient card and orange-400 on the passkey preflight, and orange-400 (#f69855) is not readable as type. one semantic token now carries the attention tone for text, at the readable value the recipient card already used. names follow the badge/surface attention family, not a second 'warning' word. no board defines a foreground tone past error — flagged for vlad. TASK-22452
the onboarding hero and its bottom-inset fill painted the blue-300 primitive straight from the ramp, so the surface had no name and every new setup screen had to re-find the right index. same resolved color, now a semantic token. the native status-bar call still takes a hex literal. no board defines it — flagged for vlad. TASK-22452
the bank branches drew a flag image with a mini bank bubble overlaid on it — a hand-composed leading, which the leading vocabulary does not have. the flag/logo now rides the DS avatar with the bank icon as its fallback, the same shape the transaction rows already use. the bank cue only shows when no flag or logo loads; flagged as a lost cue. TASK-22452
the light logo is white glyphs on the white receipt page — invisible. absorbs the still-valid logo half of #3171 onto current dev (TASK-22452).
five hand-rolled flex+CopyToClipboard rows collapse into DataRow allowCopy/copyValue: To, TxID (non-explorer), bank account (full unmasked identifier on copy), transfer id, and the public reference (raw case-sensitive id on copy, middle-ellipsis display). the shared copy glyph gains shrink-0 print:hidden so long values cannot squash it and print output stays clean. absorbs the DataRow half of #3171 (TASK-22452).
…only hugo: 'we can't have 4 CTAs in a single page!' — the receipt now carries one state-aware primary (Split when splittable, Share otherwise, Download on the public page) and demotes share/download/support into a nested More-actions drawer (ListItem rows, yellow size-s bubbles — the user's explicit pick for receipt actions, flagged for the board). the issuer facts appear once, at the top, on the web receipt AND the pdf: dark wordmark left, issued-by + address + site right; the bottom company footer is gone and the pdf wordmark drops its mascot glyph to match the text-only dark asset. the details card gains Reference (raw id copyable, middle-ellipsis display) and Issued-on rows from real source fields, and the pdf's leading date row is relabelled Issued on — same status-branched source timestamp, never the download time. share/download logic is reused, not duplicated: ShareButton's behavior moved to a useShareAction hook (button unchanged), PrivateReceiptPdfActions became the useReceiptPdfFile hook (auth, native http, prefetch and retry semantics identical). the #3159 public/private boundary is untouched (TASK-22452).
the user ruled KEEP for the referral nudge, moved into the overflow. the dead ReceiptReferralNudge component (no consumer since the linkbutton sweep) becomes useReceiptReferralAction: the pre-#3159 eligibility gate unchanged (own completed outbound payment, activated account with a username, never public/pending/failed/refunded/inbound), the invite link from generateInviteCodeLink as before. the impression fires only while the drawer is open with the row visible, once per transaction; outcome events keep firing from share success only. analytics note: the button/text_link variants collapse into one 'drawer_row' variant — the row now has exactly one placement (TASK-22452).
the authenticated all-kinds pdf landed in #3159; the model suite only exercised bank rails. pin a card spend (fx row, no transfer id), a p2p transfer (counterparty + memo) and a send-link claim (From + claim date) so the wider coverage has representative fixtures. no access-boundary changes — hasReceiptPage still classifies the public capability urls (TASK-22452 item 4).
…lingLoading CyclingLoading is inline-only by the rulebook, but five rails used it as a full-screen state. they now share Global/ProcessingScreen — the one mascot loader over a TitleBlock (the user's processing-C pick), centered by each rail's own shell. copy is truthful and localized (en/es/pt): the qr rail says we're confirming your payment, settling deposits say we're confirming your deposit, and the two qr-generation waits carry the title only — no confirming claim before money moved, no invented timings. the rollout orphaned CyclingLoading itself (these five were its only importers) — deleted; its word pool and css keyframes stay with the dev loading-words page (TASK-22452).
the user explicitly ruled Tabs for the network row (over the docs' old
value-toggle guidance — flagged for the board). the tile grid becomes
controlled DS Tabs: an explicit All tab replaces clear-by-reselect (''
keeps its popular-set meaning), each popular chain gets a tab with its
icon, a chain picked from the More-networks list gets its own tab so the
selection stays visible, and More networks is a separate header action.
tab selection keeps the picked token exactly like the old tiles; the
list path still clears it; search still spans every allowed chain.
Tabs gains an optional controlled mode (value/onValueChange) and a
ReactNode label — string labels and the marketing MDX adapter are
untouched. NetworkButton and the clear-selection X are orphaned and
removed. first behavioral tests for both Tabs and TokenSelector
(TASK-22452 item 8).
the ToS re-consent modal and the migration download prompt could stack — they mount in different trees (layout vs HomeModals) with no shared priority. ModalsContext now carries a legal-consent gate that ReConsentModal owns: 'checking' from before the status request until every terminal path (nothing to show, snoozed, accepted, postponed, failed check, logged out, unmount), 'prompting' while the modal shows. the download prompt defers while the gate is not clear FOR ITS OWN account — the gate carries the userId it resolved for, so one account's clear can never release another mid-switch — and a legal prompt actually shown defers the download prompt to the next visit, per account. a failed check or a consent-surface unmount fails open: legal can gate, never brick. covered by a both-mounted suite driving the real provider (in-flight window, dismissal, error, unmount, A→B switch, per-account latch).
…antees review follow-ups on the hook extraction. a prefetched file reaches navigator.share synchronously from the click again — the unconditional async boundary had broken the user-activation guarantee native share sheets need. a receipt/locale switch now drops the cached file and discards an in-flight fetch, so the drawer can never deliver the previous transaction's document. repeated taps while an action is pending are a no-op (ref-guarded, and both drawer file rows disable on busy — the old buttons did). public-capability kinds keep their pre-existing url download inside the drawer (anchor on web, system browser on native, no bearer, no wait) via a helper shared with the visible download button; only private kinds use the authenticated file hook. the public action group also gains the support link with its own reserved hit area.
…nk target receiptIssuedAt is now the pdf's status-branched rule (cancellation date for cancelled/closed, refund date for refunded, settlement/claim for completed, creation for pending) and the pdf model consumes the same helper — page and pdf can never disagree, and no receipt ever invents a time. its stale public-header comment is gone. the receipt's main sections move to the approved xl/24 rhythm, and the support link sits in a 44px flex-centered wrapper so its extended hit area (::after reaches 14px past the text row) can never overlap the button grouped above — root reproduced that exact bottom-edge misfire on the public receipt.
the impression dedup becomes a set keyed per viewer+transaction — the single last-id ref re-fired on an A→B→A bounce and its claim ignored who was looking. the doc comment stops saying a cancelled share captures nothing: the shared hook deliberately counts a completed clipboard copy as success even when the sheet is then dismissed.
…reduced motion root's rail qa: crypto and rhino kept their send-instructions / network toggle above the processing state, inviting a second deposit while the first confirmed. both rails now early-return a NavHeader + ProcessingScreen shell once the deposit is settling (address preparation keeps the bare mascot); navigation and polling are untouched, and the centered block inherits shell height instead of a fixed h-screen box. ProcessingScreen also halts the loader's descendant spin under prefers-reduced-motion, scoped to this composition — the shared Loading has no rule of its own and changing it is separate ds debt.
typescript narrows status after the new early return, so the old 'not loading' comparisons stopped compiling (crypto) or went dead (rhino) — my own orphans, removed.
the tabs migration had grown a ~200-line iife inside the drawer's ternary just to declare the token block and tab list — lifted to plain consts above the return so the new diff reads top-down. the More-networks link also gains a 44px flex-centered wrapper: its extended hit area reaches 14px past the text row, straight into the tab row below without the reservation. no behavior change; the tabs suite pins it.
root measured the wcag ratio at 5.93:1 on white and 5.44:1 on the page tint — the 6.4:1 claim was wrong (still readable, just misstated). the new comments from the mechanical pass drop their sentence-case starts.
…rn it root's committed-state probe caught two intermediate frames the dom-final assertions missed: on A→B the download modal committed visible under B twice before B's consent check published. two owners were wrong. the consent modal's publish effect labelled the PREVIOUS account's resolved state with the new account's id for one render — resolution now carries resolvedFor, and a state/account mismatch always publishes 'checking'. the download prompt rendered its stored visible state under whichever account happened to be current — the render now gates synchronously on the current account and gate (visibleFor ownership + legal blocking + per-account latch), and onVisibilityChange reports that same committed visibility so HomeModals' sibling suppression cannot flash either. one-visit deferral, fail-open on error/unmount, and the dev forceVariant bypass are unchanged. the suite now records every committed visible state with its account (useLayoutEffect recorder) and pins cold login, A→B with A visible, and B's unresolved/failing/no-change results.
the full-suite gate caught send-states crashing at import: the module read REFERRAL_SOURCES eagerly while that suite mocks the analytics constants partially. the old component built the props lazily — restored as a function, call sites unchanged in shape.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Code-analysis diffPainscore total: 7997.19 → 8007.93 (+10.74) 🆕 New findings (107)
…and 87 more. ✅ Resolved (100)
…and 80 more. 📈 Painscore deltas (top movers)
|
🧪 UI test report — ✅ all greenSuites
📊 Coverage (unit)
⏱ 10 slowest test cases
|
|
/chip review |
🖼 Visual diff — 9 screens moved16 of 96 shots changed · 80 identical · baseline
job summary · before/after/diff images — artifact Fixture screenshots, no backend. Advisory — this check never blocks a merge. Posted from the default branch by ds-shots-comment.yml; the report it renders is untrusted data. |
There was a problem hiding this comment.
Chip review — no blocking findings — this is not an approval
No findings in the exact-head review.
Checked clean
- Exact head and merge base matched the supplied SHAs; trusted PR metadata matched the supplied author and dev base.
- Receipt action hierarchy, public/private PDF routing, native/web sharing and downloading, referral eligibility, and receipt/PDF model changes.
- Processing-state replacements across QR pay and fiat/crypto deposit rails, including reduced-motion behavior.
- Controlled Tabs integration and TokenSelector network/token state transitions.
- Legal re-consent priority over the migration download prompt, including cold login and account-switch ownership.
- Core CI gates passed. Screen-library publication alone failed during external Cloudflare token verification; the PR does not change that workflow or its storage scripts.
Security review by moonshotai/kimi-k3: 0 finding(s), marked with the model name. It reads the diff only and answers only security, privacy and money, so treat its findings as advice.
Third opinion by claude-opus: 0 finding(s), marked with the model name. It answers only product truth, missing tests and the cross-repo contract, so treat its findings as advice.
Exact head: d47208a83db0 · Context: repo · Took 19m
Chip review — no blocking findings — this is not an approvalNo findings in the exact-head review. Checked clean
Security review by Third opinion by Exact head: |
Summary
Receipt screens now use one primary action and a More actions drawer. The selected centered layout keeps Split this bill primary where eligible, with Share, PDF, Invite friends, and support in the drawer. Public receipts make Download primary.
Absorbs the current logo/DataRow work from #3171. Its PDF-link change was superseded by #3159.
Task
TASK-22452
Risks and design notes
drawer_rowrather than the retired placements.Flagged, not changed
Allpreserves the existing popular-network set; it does not expand to every supported network. Mono's SegmentedControl guidance needs a separate update.foreground-attentionandbackground-setup-hero. Existing AppShell blue surfaces remain a separate audit.Validation
TZ=UTC: 622 suites, 7,646 passed, 7 skipped. UTC avoids the two acknowledged local timezone failures.d47208a83db0; Kimi security and Claude product/contract passes also found none.Docs and legal
No customer-facing product/help/legal fact changes. The audit read the applicable privacy, terms, and card agreements.
Separate mono DS follow-up:
design/components.mdnetwork Tabs guidance and controlled API;design/design.mdanddesign/components.mdCyclingLoading rows. No content edits are bundled here.Visual evidence
These 375px mobile captures render production components with synthetic, read-only fixtures. They verify the UI surface, not backend payment or rail behavior. The generated PDF uses the same synthetic receipt model. The
pr-assets-3225branch will be deleted after merge.Receipt states, actions, issuer, and PDF
Download the generated synthetic receipt PDF
Processing screens across all five rails
Action lists, network Tabs, warning tokens, setup hero, and bank leading