Skip to content

feat(mobile): tx preview card + detail bottom sheet - #541

Merged
Miracle656 merged 2 commits into
Miracle656:mainfrom
chizzy0011:feat/mobile-tx-preview
Jul 30, 2026
Merged

feat(mobile): tx preview card + detail bottom sheet#541
Miracle656 merged 2 commits into
Miracle656:mainfrom
chizzy0011:feat/mobile-tx-preview

Conversation

@chizzy0011

Copy link
Copy Markdown
Contributor

What

The reusable transaction surfaces used across the app: a preview card shown before signing and a detail sheet opened from a history feed — ported as native bottom sheets so transaction presentation stays consistent.

Change

  • components/TxPreviewCard.tsx — presentational confirm-step preview (you send / receive-at-least / to / memo / network fee).
  • components/TxDetailSheet.tsx — a @gorhom BottomSheetModal over a TxRecord (type mirrors the web wallet's TxDetailSheet.tsx), opened via a ref (present()).
  • app/_layout.tsx — wrap the app in GestureHandlerRootView + BottomSheetModalProvider (required by the sheet).
  • app/(tabs)/activity.tsx — demo: renders the preview and a feed whose items open the detail sheet on tap.
  • dep: @gorhom/bottom-sheet (5.2.14, installed via expo install; its peers are satisfied by the app's react-native-reanimated 4.5 + gesture-handler 2.32).

Acceptance

confirm step shows preview; tapping a feed item opens the detail sheet.

✅ The preview renders on the confirm surface; tapping any feed item presents the TxDetailSheet.

Notes

  • _layout.tsx gains the gesture-handler + bottom-sheet-modal providers because @gorhom requires them at the root.
  • Self-contained styling (shared UI primitives aren't in main yet); representative feed/preview data pending wallet + history wiring.

Verification (local — no mobile CI job)

  • npm run typecheck ✅ · eslint on all changed files ✅ clean.

Closes #470

Add the reusable transaction surfaces used across the app: a preview card
shown before signing, and a detail sheet opened from a history feed. Porting
them as native bottom sheets keeps transaction presentation consistent.

- components/TxPreviewCard.tsx: presentational confirm-step preview.
- components/TxDetailSheet.tsx: @gorhom BottomSheetModal over a TxRecord
  (type mirrors the web wallet), opened via a ref.
- app/_layout.tsx: wrap in GestureHandlerRootView + BottomSheetModalProvider
  (required by the sheet).
- app/(tabs)/activity.tsx: demo — renders the preview and a feed whose items
  open the detail sheet on tap.
- dep: @gorhom/bottom-sheet.

Closes Miracle656#470
@chizzy0011
chizzy0011 requested a review from Miracle656 as a code owner July 28, 2026 16:40
@vercel

vercel Bot commented Jul 28, 2026

Copy link
Copy Markdown

@Chizzychi is attempting to deploy a commit to the miracle656's projects Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave

drips-wave Bot commented Jul 28, 2026

Copy link
Copy Markdown

@chizzy0011 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Miracle656 Miracle656 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

TxPreviewCard.tsx and TxDetailSheet.tsx are what #470 asked for and they look right — the TxRecord shape matches the web components and the @gorhom/bottom-sheet wiring in _layout.tsx is correct. One blocker before I can merge.

app/(tabs)/activity.tsx ships fixture data as a real tab

The gallery screen is hardcoded:

const FEED: TxRecord[] = [
  { id: '1', type: 'received', amount: '50', asset: 'USDC', ... },
  ...
];

Because it sits under app/(tabs)/, expo-router turns it into a user-facing tab. Anyone opening the app sees three invented transactions — a 50 USDC receipt, a lunch memo, a Soroswap swap — presented as their own history.

It also collides with #461 (Recent activity feed, PR #528), which owns the real feed and backs it with lib/activityFeed.ts against live data. Two activity surfaces, one of them fake, is not where we want to end up.

What to do

Move the gallery off the tab route — app/tx-surfaces.tsx (or any non-(tabs) path) is fine, and it still satisfies the acceptance criterion, since tapping a row there opens the detail sheet exactly the same way. #531 and #532 do this with app/fonts.tsx and app/ui.tsx; follow that pattern.

Alternatively drop the screen entirely and let #461 demonstrate the detail sheet against real records.

Everything else is fine — move the route and I will merge.

- Take main's app/_layout.tsx (fonts, splash, connectivity gate, network
  hydration, WalletConnect modal) and wrap it in GestureHandlerRootView +
  BottomSheetModalProvider rather than replacing it with the earlier stub.
- Drop app/(tabs)/activity.tsx. It was a showcase screen with hardcoded PREVIEW
  and FEED constants, so it would have shipped a fifth tab presenting invented
  transactions as the user's own history — and main already renders a real
  Wraith-backed ActivityFeed on the dashboard.
- Wire TxDetailSheet into that real feed instead: ActivityFeed already had an
  onSelectTx prop, so tapping a row now presents the sheet. That is the
  acceptance criterion, and it was not reachable before.
- TxDetailSheet redeclared TxRecord field-for-field identically to
  lib/activityFeed.ts. It now imports and re-exports that one, so the feed and
  the sheet cannot drift apart.

tsc clean; jest 12 suites / 206 tests; expo lint clean.
@Miracle656

Copy link
Copy Markdown
Owner

Merging. TxPreviewCard and TxDetailSheet are both clean, and using @gorhom/bottom-sheet with a forwardRef to BottomSheetModal plus a backdrop is the right native pattern for this.

Four changes before merge:

Root layout. The branch replaced app/_layout.tsx with a version built on the old stub. main's has grown a lot since — font loading with a splash hold, the connectivity gate, network hydration, the WalletConnect approval modal. I kept main's and wrapped it in GestureHandlerRootView + BottomSheetModalProvider, which is what the sheets actually need.

Dropped app/(tabs)/activity.tsx. This was a showcase screen built on hardcoded constants:

const PREVIEW: TxPreview = { action: 'Send', amount: '25', asset: 'USDC', ... };
const FEED: TxRecord[] = [ ... ];

As a route under (tabs) it would have shipped as a fifth tab presenting invented transactions as the user's own history. main already renders a real Wraith-backed ActivityFeed on the dashboard as of #528, so there was also a live feed sitting next to a fake one.

Wired the sheet into the real feed. This is the part that made the acceptance criterion true. ActivityFeed already exposed an onSelectTx prop that nothing used; the dashboard now holds the selected record and a BottomSheetModal ref, so tapping a row presents TxDetailSheet with genuine data. Previously the sheet was only reachable from the demo screen.

Deduplicated TxRecord. TxDetailSheet redeclared it field-for-field identically to lib/activityFeed.ts — same ten fields, same optionality. It now imports and re-exports that one, so the feed and the sheet can't drift.

Verified: tsc --noEmit clean, jest 12 suites / 206 tests, expo lint clean, CI green.

The other half of #470confirm step shows preview — isn't reachable yet: TxPreviewCard is merged and ready, but there's no signing confirmation step to host it. That arrives with the send flow, so the component is in place waiting for it rather than being wired to a placeholder.

@Miracle656
Miracle656 merged commit 3aa5697 into Miracle656:main Jul 30, 2026
10 of 13 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.

42. Tx preview + detail sheets

4 participants