Skip to content

Interactive Grid Global Accounts wallet demo#580

Open
patcapulong wants to merge 184 commits into
mainfrom
pat/wallet-demo-country-banks
Open

Interactive Grid Global Accounts wallet demo#580
patcapulong wants to merge 184 commits into
mainfrom
pat/wallet-demo-country-banks

Conversation

@patcapulong

Copy link
Copy Markdown
Contributor

Summary

Draft PR to get a staging link for team feedback — not ready to merge yet.

This branch builds out the interactive Grid Global Accounts wallet demo (components/grid-wallet-demo), embedded on the docs Playground page (global-accounts/demo):

  • Recipient-first Send flow (bank + crypto), country bank picker (65+ countries) with searchable currency/country list, Add money / Withdraw flows (incl. withdraw-to-crypto), all wired to representative Grid API calls shown live in the API panel.
  • Real activity list, earnings card, scrollable wallet home with an iOS-style status-bar scroll edge, glass UI components, and adaptive light/dark theming synced with the docs.

Deploy / embed

  • Demo is deployed to Vercel production: https://grid-wallet-demo.vercel.app (under lightspark-team).
  • The docs embed (mintlify/snippets/global-accounts/wallet-demo-embed.mdx) loads that URL in an iframe; CSP frame-ancestors already allows the docs + Mintlify preview domains.

How to try it

Status

🚧 Work in progress — sharing for early feedback.

Made with Cursor

picsoulabs and others added 30 commits May 28, 2026 14:05
Interactive, embeddable wallet demo for the Grid docs — the neobank analog of
the Flow Builder. New standalone Next.js app (components/grid-wallet-demo) that
the docs embed in an iframe with light/dark theme sync, mirroring how
grid-visualizer powers /flow-builder.

- Same shell + design system as the Flow Builder (@lightsparkdev/origin,
  sidebar + canvas + CodePanel-style API log, central-icons, squircle).
- Playground model: pick a use case + sign-in method, then drive a real wallet
  on a phone (create account, add money, send, cash out, issue a card, tap to
  pay) by clicking the phone itself; the exact Grid API calls render alongside.
- Phone wallet adapted from the bread neobank app; Robinhood-style glass card
  with a cinematic reveal.
- Scripted happy path (no live sandbox calls), like the Flow Builder.

Docs wiring (mintlify/): new global-accounts/demo.mdx ("See it live", under
Introduction), docs.json nav + chrome-hide CSS, style.css full-bleed iframe.

Deployment + designer handoff notes in components/grid-wallet-demo/HANDOFF.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- demo.mdx: remove JS line comment that broke Mintlify's MDX parse
  (rendered the page blank) and add phone icon to "See it live"
- add phone.svg sidebar icon
- vendor Suisse Intl fonts into public/fonts so Origin's @font-face
  resolves (was 404ing, falling back to system fonts)
- flow.ts: keep Google/Apple capitalized in the sign-in CTA
- Sidebar.tsx: mark Phone (SMS) sign-in as "Soon"

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drop custom page mode and replace viewport-fixed iframe CSS with in-content
full-bleed layout so the demo spans the main pane while Mintlify nav stays usable.

Co-authored-by: Cursor <cursoragent@cursor.com>
Match Flow Builder panel headers and Figma intro layout while preserving demo logic in a hook for phase-2 wiring.

Co-authored-by: Cursor <cursoragent@cursor.com>
Adds use case, auth, and flow pickers with multiselect auth, column resize, consistent hover surfaces, and demo reference assets.

Co-authored-by: Cursor <cursoragent@cursor.com>
Snap near 50/50 split, center the grip on the boundary, and collapse handle margins so no gap appears before the API column.

Co-authored-by: Cursor <cursoragent@cursor.com>
Matches Figma card layout with updated app icons, overlay gradient ring on stroke-xs, and drop-shadow on icons.

Co-authored-by: Cursor <cursoragent@cursor.com>
Use non-scaling-stroke on the checkbox icon and set content gap to spacing-md (16px).

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Wires entries into ApiPanel and shows Figma-aligned placeholder copy until the first flow runs.

Co-authored-by: Cursor <cursoragent@cursor.com>
…tyle paths.

Wire ApiCallList into the panel with Flow Builder patterns (680px column, syntax highlighting, sliding tab indicator), split step titles from descriptions, and show OpenAPI paths in the UI while keeping the versioned base URL in generated cURL.

Co-authored-by: Cursor <cursoragent@cursor.com>
Animate the active gradient ring between tiles, clear hover fill on selection, and add swift-out icon scale on hover with a press-down bounce.

Co-authored-by: Cursor <cursoragent@cursor.com>
Fill the panel with gray-scale placeholder steps, then reveal the empty message and a bottom gradient cover in sync after a short pause.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Mount the demo phone on the dot grid, add slop/swag and screen fixtures for styling QA, and enable API panel seed data for local demos.

Co-authored-by: Cursor <cursoragent@cursor.com>
Replace the placeholder swag bezel with a 434×906 shell and 402×874 inner screen, and fix phone radius tokens so the ×1.8 squircle override isn't clobbered by fallbacks.

Co-authored-by: Cursor <cursoragent@cursor.com>
Reusable Glass/LiquidGlass built on a generated SVG feDisplacementMap
(displacement.ts) with squircle clip support and tuning presets. Map is
aspect-correct and the edge uses a bleed-and-trim pass, so refraction
stays clean (no dark rim) with anti-aliased corners.

Co-authored-by: Cursor <cursoragent@cursor.com>
…metry.

Compute the top-left quadrant of the rounded-rect map once and mirror it
into all four (negating the X bend across the vertical axis, Y across the
horizontal); the directional specular stays exact (2-fold, per-pixel).
Output is byte-identical to the full-loop version.

Co-authored-by: Cursor <cursoragent@cursor.com>
… it.

Ports grid-visualizer's DotGrid ripple (Canvas 2D) as the phone backdrop,
and wires the liquid-glass shell so it refracts the backdrop (sized filter
region, bleed-and-trim edge, aspect-correct map).

Co-authored-by: Cursor <cursoragent@cursor.com>
- StageGL WebGL glass: implement chroma, glow, brightness, splay, and a
  9-tap bilinear gaussian blur, all wired to the tuning panel.
- Center the animated dot-grid backdrop with even row/column spacing and
  24px padding at any canvas size.
- Drive the phone radius concentrically (shell + inner screen track one
  value); match the corner to iOS via corner smoothing (corner-shape
  superellipse, exponent = 2 + smoothing*4 = 2K).
- Adopt superellipse(1.24) app-wide via a single --corner-shape token and
  retune the squircle radius multiplier 1.8x -> 1.2x for the rounder shape.
- Dev tooling: reference-bezel overlay to line up against a real iPhone,
  plus live drop-shadow sliders (offset/blur/spread/opacity).

Co-authored-by: Cursor <cursoragent@cursor.com>
Revert the grounded (below-only) shadow back to a single box-shadow built
from the Shadow sliders, so it peeks out on all sides and stays tunable.

Co-authored-by: Cursor <cursoragent@cursor.com>
Mintlify re-mounts the MDX page body on each theme toggle, which
recreated the embedded <iframe> and cold-reloaded the demo (lost state,
~0.5s flash). Move the iframe into a singleton host on <body> — outside
the re-mounted subtree — so it loads once; the MDX renders a placeholder
that the host is positioned over. Theme now flows through the existing
theme-sync postMessage path, so toggling recolors in place with no
reload (and navigating away/back no longer reloads either).

Make the dot-grid backdrop theme-aware to match: since it's canvas-drawn
it can't rely on CSS alone now that there's no reload, so read the new
--dot-grid-* tokens via dotGridColors and repaint on data-theme changes
(DotGrid + StageGL), with matching CSS fallbacks.

Co-authored-by: Cursor <cursoragent@cursor.com>
The font token was "Suisse Intl" with no fallback and font-display: swap,
so any frame the webfont isn't painted (the repaint when the docs theme
toggles) fell back to the browser default — serif. Give the sans/mono
tokens a system fallback stack so that frame renders a near-identical
system sans, never serif.

Also preload the visible weights (Book 450, Medium 500, Mono) with
crossorigin so the first paint shows Suisse Intl sooner without a double
fetch — matching the @font-face's CORS-mode request.

Co-authored-by: Cursor <cursoragent@cursor.com>
The placeholder was created by the WalletDemoEmbed component, so it only
existed after the client JS mounted. The chrome-hiding CSS keys off
#content-area:has(#wallet-demo-container), so until then the bare docs
page (sidebar, title, pagination) showed for a frame on refresh.

Move #wallet-demo-container back to a static element in the MDX so the
CSS applies on first paint; the component now returns null and just
positions the persistent iframe over that box via getElementById.

Co-authored-by: Cursor <cursoragent@cursor.com>
…uts.

Use case and auth pickers share a single bordered grid, API call cards merge endpoint and code into one block, and the API column defaults to content width with snap-back resize.

Co-authored-by: Cursor <cursoragent@cursor.com>
- Add <GlassOver> for the "glass over a known background" case (button / tab
  bar / card) — it does the backdrop-copy for you; exported from the barrel.
- Add a component README: the "refracts its children" mental model, GlassOver
  vs Glass, presets, copy-paste recipes, gotchas, and the SVG-vs-WebGL rule.
- Add a liquid-glass agent skill so other chats use it correctly.
- Correct displacement.ts header: the map drives the SVG path; the WebGL path
  (StageGL) re-derives the math, it isn't fed the map, and there's no auto-switch.

Co-authored-by: Cursor <cursoragent@cursor.com>
Reuse CopyButton for the path action with matching hover styles, always-visible placement aligned to the toolbar, and a persistent gradient fade for long endpoints.

Co-authored-by: Cursor <cursoragent@cursor.com>
corner-shape is Chromium-only, so on Safari/Firefox the phone screen fell
back to a circular border-radius that clipped tighter than the squircle
lens, breaking concentricity. Clip the screen to the same superellipse the
WebGL lens draws (clip-path: path, cross-browser) with border-radius 0 so
it is the sole corner shaper, and render the drop shadow as an SVG outset
filter so it stays a squircle on every browser too.

Co-authored-by: Cursor <cursoragent@cursor.com>
patcapulong and others added 20 commits June 14, 2026 23:56
…ing.

- Add the UK (GBP) and Germany (EUR representative) to the popular section
  (ranks 6-7) so developed markets show alongside the remittance corridors.
- Drop the payment rail from every country row (picker, saved banks, form
  header) -- users pick by country + currency, so the rail was just noise.
- Spacing: "Popular" now rests 16px under the search pill, section labels get
  +4px left/right and +8px bottom, and the search icon drops to label-tertiary.
- Light-mode specular reads stronger + thicker so the white rim shows on the
  near-white pill; dark stays matched to the back button.

Co-authored-by: Cursor <cursoragent@cursor.com>
Mirrors the Popular / All countries headers (and inherits the first-child
spacing, so it rests under the search pill the same way).

Co-authored-by: Cursor <cursoragent@cursor.com>
- Rename step titles to actions: "Select bank" (saved-banks list) and "Enter
  bank details" (the form), matching the "Select country" style.
- Empty banks state gets a home-style "Add bank" CTA (jumps to the country
  picker) and clearer copy: "Add a bank account in 65+ countries to get started".
- Cap the empty-state description at 240px with text-wrap: balance so longer
  copy wraps to even lines; the other empty states keep their explicit breaks.

Co-authored-by: Cursor <cursoragent@cursor.com>
- Swap the saved-banks "+" for the real SF Symbol `plus` at semibold (matching
  the back button's chevron); register it in the export script + path map.
- Bank form: drop the flag header for a read-only "Country" row styled as the
  first field; field rows get 16px top/bottom padding, no label/value gap, and
  an emphasized (semibold) value (with the variation axis set so it renders).
- Rename Mexico's bank to "Nu México" everywhere (form prefill + activity row).

Co-authored-by: Cursor <cursoragent@cursor.com>
- Add an illustrative bank-name pool to the popular 7 countries; addBank cycles
  it by how many of that country are already saved (Nu México first for MX, then
  BBVA / Santander / Citibanamex, etc.). Long-tail countries keep their single
  name.
- Randomize the account-number digits on each prefill (enum fields + names left
  intact), so even two accounts at the same bank differ by their last 4.
- Store the chosen name per SavedBank and use it in the saved-banks row and the
  selected-bank display, instead of the country's single default.

Co-authored-by: Cursor <cursoragent@cursor.com>
… address.

Send is "external to someone else", so it now opens on a RECIPIENT list (its own,
separate from your add/withdraw accounts). "Add recipient" opens a Bank / Crypto
chooser.

- Bank recipients: a country-matched recipient name from a cycling pool (so
  repeats differ), name-led rows (rounded SF Pro Rounded initials avatar + a
  16px flag badge), USD -> their local currency with the 0.30% fee on confirm.
- Crypto recipients: the pasted address is saved (token avatar + "<network>
  wallet"), each a fresh random address; 1:1 USDC.
- Recipients are a bank | crypto union (discriminated by `'address' in r`); the
  selection splits into selectedBank / selectedCrypto so the bank logic is
  untouched. Round skeleton avatar placeholders, and mode-aware back-nav + the
  X/back control. Add and withdraw stay source-first and bank-only.

Co-authored-by: Cursor <cursoragent@cursor.com>
Linking a bank or crypto recipient now logs POST /customers/external-accounts
with a spec-accurate accountInfo body, and send quotes reference the recipient's
bank off-ramp (local currency) or Solana wallet instead of a UMA address.

Co-authored-by: Cursor <cursoragent@cursor.com>
The confirmed transfer now passes its destination up from the sheet, so the
Activity row and toast reflect the actual bank (flag, name, last 4) or crypto
recipient instead of a hardcoded Nu México / demo Solana address.

Co-authored-by: Cursor <cursoragent@cursor.com>
The withdraw sheet's Crypto wallet source is now active: enter an address,
then amount and confirm. It reuses the send-crypto address step as a one-off
destination — links the wallet (POST /customers/external-accounts), quotes
USDB → USDC at 1:1, and logs the activity as an on-chain payout.

Co-authored-by: Cursor <cursoragent@cursor.com>
Neither was mounted or called — the live panel is ApiCallList, which doesn't
render an ApiCall's note. Drops the dead component, its styles, and the
orphaned accessor; the note field stays as data for a future panel subtitle.

Co-authored-by: Cursor <cursoragent@cursor.com>
Hovering the Add source list or the Send/Receive button group fades the
non-functional options (Crypto/Cash App/Apple Pay in Add, and Receive) to
50%, restoring on mouse-out. They stay non-interactive throughout; only the
dim is hover-revealed, so each option still reads normally at rest.

Co-authored-by: Cursor <cursoragent@cursor.com>
Adopts AuthSheet's layout: a gradient icon tile + glass X header and a
left-aligned title/subtitle, replacing the centered title group. The two
bordered action pills (Send, and the hover-dimmed Receive) are unchanged.

Co-authored-by: Cursor <cursoragent@cursor.com>
…reen.

A cold jump (clicking a flow while signed out) mounted the wallet and opened
the sheet immediately, so home was never seen. It now provisions right away
but waits for the entrance reveal to land before opening the flow. The timer
lives in a ref with no effect cleanup so StrictMode's dev double-invoke can't
clear it before it fires.

Co-authored-by: Cursor <cursoragent@cursor.com>
The sheet keeps its content mounted through the close→reopen of a flow switch,
so the step stack and toolbar title animated the mode change as a forward push.
An openKey now remounts both on each open, so a flow opened from another flow
appears in place; step-to-step navigation within a flow still slides.

Co-authored-by: Cursor <cursoragent@cursor.com>
…eal.

Earnings shows yield on the live balance (balance × 5% APY ÷ 365) as today's
accrual, with "+X today" (green amount, secondary qualifier). Weekly activity
now tracks real card spend: it starts empty and each Tap to Pay appends a bar
(building left→right, heights varying by amount), with the detail as spent.

Co-authored-by: Cursor <cursoragent@cursor.com>
Going back from the wallet now blur-fades the auth screen in over the held
home (easeOutSnappy) — the reverse of the sign-in reveal — so the two
directions read as one motion. Reduced motion gets a plain crossfade.

Co-authored-by: Cursor <cursoragent@cursor.com>
Seconds were shown but the panel only re-sampled every 30s, so counts froze
between ticks. It now refreshes every second and reads "Just now" (<5s) →
live "5s…59s ago" → "1m/2m/1h/1d", so a call counts up smoothly and new
calls never render the rest against a stale clock.

Co-authored-by: Cursor <cursoragent@cursor.com>
- The balance/actions/insight/activity sheet now page-scrolls while the
  debit card (sticky), aurora, title, and gear stay pinned behind it and
  get covered cleanly as it scrolls up.
- The scroll content runs under the status bar and melts into the wallet
  bg via a progressive blur + bg-color fade, so it never clashes with the
  status-bar glyphs. Three stacked backdrop-filter layers ramp the blur
  radius (8/4/2px) instead of one uniform blur, removing the hard edge.

Co-authored-by: Cursor <cursoragent@cursor.com>
The home scroll work made the body underlap the status bar in every card
state, so on the issuance/card screens the transparent body sat over the
aurora and the tone sampler resolved up to the light wallet bg — black
glyphs over the blue aurora. Scope the status-bar underlap + scroll to the
plain home (.bodyHome); issuance/open/tap revert to the original header-only
underlap so the aurora stays the topmost layer under the bar.

Co-authored-by: Cursor <cursoragent@cursor.com>
Added by `vercel link` when connecting the demo folder to the
lightspark-team/grid-wallet-demo project for CLI deploys.

Co-authored-by: Cursor <cursoragent@cursor.com>
@vercel

vercel Bot commented Jun 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
grid-flow-builder Ignored Ignored Preview Jun 15, 2026 11:22am

Request Review

@patcapulong patcapulong marked this pull request as ready for review June 15, 2026 11:07
@greptile-apps

greptile-apps Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Too many files changed for review. (320 files found, 100 file limit)

Co-authored-by: Cursor <cursoragent@cursor.com>
Also nudges Mintlify to build a preview for this PR — its monorepo app only
deploys when a pushed commit touches a file under mintlify/.

Co-authored-by: Cursor <cursoragent@cursor.com>
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.

3 participants