Skip to content

feat(portfolio): add shareable performance card with canvas-rendered PNG (closes #881) - #908

Open
guptakumarranjeet150 wants to merge 2 commits into
accesslayerorg:devfrom
guptakumarranjeet150:feat/issue-881-shareable-portfolio-card
Open

guptakumarranjeet150 wants to merge 2 commits into
accesslayerorg:devfrom
guptakumarranjeet150:feat/issue-881-shareable-portfolio-card

Conversation

@guptakumarranjeet150

Copy link
Copy Markdown

Summary

Closes #881 — Implements a fully client-side shareable portfolio performance card that generates a branded 1200×675 PNG image showing key portfolio metrics, ready to download or copy to clipboard for social sharing.

Changes

New: src/components/common/SharePortfolioModal.tsx

  • HTML5 <canvas>-based card renderer (zero external image-generation service)
  • Dark gradient background (090d16 → 0b1329) with decorative glow blob
  • 3 metric tiles: Total Invested, Current Value, Unrealised PnL (green/red color-coded)
  • Top 3 creator holdings table with rank, name, quantity, and value
  • Wallet badge: address auto-truncated (e.g. GBZXN7...ABCD) for privacy
  • Download PNG — anchor-click download, accesslayer-portfolio-<timestamp>.png
  • Copy to Clipboard — ClipboardItem API with react-hot-toast fallback
  • Lazy render: canvas draws 50 ms after dialog opens to ensure ref is mounted

New: src/utils/wallet.utils.ts

  • truncateWallet(address) helper extracted to a dedicated file
  • Satisfies react-refresh/only-export-components ESLint rule

Modified: src/pages/LandingPage.tsx

  • isShareModalOpen + topHoldings state added
  • "Share Performance" button wired to open SharePortfolioModal

New: src/components/common/__tests__/SharePortfolioModal.test.tsx

  • truncateWallet unit tests: empty, short, full 56-char Stellar address
  • Modal renders correctly when open=true
  • Close button fires onOpenChange(false)

Modified: src/hooks/usePrefersReducedMotion.ts

  • Added typeof window === "undefined" guard for SSR/test-environment safety

No External Dependencies Added

Pure HTML5 Canvas + existing UI primitives (Dialog, Button, lucide icons, react-hot-toast).

Closes #881

…PNG (closes accesslayerorg#881)

- New SharePortfolioModal component (src/components/common/SharePortfolioModal.tsx)
  * Client-side 1200x675 canvas card with dark gradient background, metric tiles
    (Total Invested, Current Value, Unrealised PnL with color-coded green/red),
    top-3 creator holdings table, and branded AccessLayer footer
  * Wallet address auto-truncated for privacy via wallet.utils.ts
  * Download PNG action (anchor click, zero external dependencies)
  * Copy to Clipboard (ClipboardItem API with toast fallback)
- New src/utils/wallet.utils.ts with truncateWallet helper
  (extracted to separate file per react-refresh/only-export-components rule)
- Integrate SharePortfolioModal into LandingPage.tsx with Share Performance button
- Unit tests in SharePortfolioModal.test.tsx:
  * truncateWallet: empty, short address, full 56-char Stellar address cases
  * Modal renders title/description/buttons when open=true
  * Close button fires onOpenChange(false)
- Fix usePrefersReducedMotion.ts: typeof window guard for SSR safety

Closes accesslayerorg#881
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.

Add a shareable portfolio performance card that generates an image summary for social sharing

1 participant