From 340f6fd89f4886884f6dc25bf0b24cf02ad99926 Mon Sep 17 00:00:00 2001 From: "shakespeare.diy" Date: Thu, 23 Jul 2026 16:35:49 +0700 Subject: [PATCH] fix(mobile): redesign wallet page UI for mobile + global mobile polish Wallet page (/wallet): - Add BalanceHero banner at top showing Cashu balance + wallet status pills - Cashu/Lightning tabs with colored active states (orange/yellow) - Remove nested balance display in CashuWalletCard (now shown in hero) - Compact balance row in CashuWalletCard - Stacked full-width inputs on mobile (no side-by-side on small screens) - h-11 touch targets on all inputs and buttons (44px min) - inputMode="numeric" on number fields (prevents iOS zoom) - Receive/Send tabs with green/red active colors for clear context - History items now 52px min height with colored amount text - WalletComparisonGuide stays collapsed by default - Fix: add Nut icon import to CashuWalletCard (was crashing) - All modals use w-[calc(100%-1rem)] for proper mobile sizing Settings page (/settings): - 7-tab bar now scrollable horizontally on mobile (no overflow/wrapping) - -mx-3 bleed trick so scrollable area goes edge-to-edge - Wallet tab buttons full-width on mobile - Container max-w-3xl for better desktop centering FAQ page (/faq): - Compact hero on mobile (smaller icon, tighter padding) - py-6 on mobile instead of py-12 CSS utilities: - Add xs: breakpoint (375px) variants: flex, flex-row, px-4, -mx-4, gap-2, text-xs/sm, hidden Co-authored-by: shakespeare.diy --- release-notes.txt | 44 ++- src/components/wallet/CashuWalletCard.tsx | 339 +++++++++-------- src/index.css | 14 +- src/pages/FAQPage.tsx | 12 +- src/pages/SettingsPage.tsx | 82 +++-- src/pages/WalletPage.tsx | 427 ++++++++++++---------- 6 files changed, 489 insertions(+), 429 deletions(-) diff --git a/release-notes.txt b/release-notes.txt index 877f471..e8a6a7b 100644 --- a/release-notes.txt +++ b/release-notes.txt @@ -1,10 +1,36 @@ -v1.0.38 - Amber login fix (Capacitor native) +v1.1.0 - Map as Homepage, Camera Fix, Sasquatch AI upgrades, UI/UX Polish -- Fixed login with Amber for ZapStore/Capacitor app users -- Now uses the native nostr-signer-capacitor-plugin instead of browser - intent URLs (which don't work inside a WebView) -- Amber opens natively as a system intent, user approves, done -- All event signing (posts, zaps, etc.) also goes through Amber natively -- Fixed Android 11+ package visibility so Amber is detected correctly -- Fixed Capacitor packages missing from package.json (prevented clean builds) -- Added SNT4EVER as community partner and friend +WHAT'S NEW + +Map is now the Homepage +- Opens directly to the interactive map on launch — no extra tap needed +- HOME removed from nav, SPOTS is now the first tab +- Map zoom capped: no more grey bands when zooming out, world stays visible + +Camera Fixed for Native App +- Tapping the camera button now opens your phone's native OS camera directly +- No more browser permission errors inside the app +- Upload from Gallery fallback added if camera is denied + +Settings → My Stash +- Quick link to your private gear inventory added to Settings > Wallet tab + +Sasquatch AI Guide Upgrades +- FAQ page is now powered by The Sasquatch — ask anything, get live answers +- Quick question chips: tap a topic to instantly ask The Sasquatch +- About page: Ask The Sasquatch button added +- Sasquatch can now be triggered from anywhere in the app + +UI/UX Polish +- Wallet page fully reworked for mobile — better spacing, touch targets, readable on small screens +- Focus rings are now on-brand red (accessibility compliant) +- Card hover micro-interactions throughout the app +- Consistent button/link transitions (150ms) +- Reduced motion support for accessibility +- Map min zoom capped — no more empty grey space when zooming out +- Safe area insets improved for notched phones + +BUG FIXES +- Map no longer duplicates tiles when zoomed out too far +- Camera no longer shows browser permission error in native app +- Sasquatch panel now responds to external triggers from FAQ/About pages diff --git a/src/components/wallet/CashuWalletCard.tsx b/src/components/wallet/CashuWalletCard.tsx index 452ec09..b97cb84 100644 --- a/src/components/wallet/CashuWalletCard.tsx +++ b/src/components/wallet/CashuWalletCard.tsx @@ -34,6 +34,7 @@ import { Shield, ScanLine, Zap, + Nut, } from 'lucide-react'; import { useToast } from '@/hooks/useToast'; import { QRScannerModal } from '@/components/wallet/QRScannerModal'; @@ -228,38 +229,42 @@ export function CashuWalletCard() { return ( <> -
+
{/* Main Wallet Card */} - - - + + + Cashu Wallet - - Built-in ecash wallet - no external setup required + + Built-in ecash wallet — no external setup required - - {/* Balance Display */} -
-
Total Balance
-
- {totalBalance.toLocaleString()} sats -
- {usdValue !== null && ( -
- ≈ ${usdValue.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} + + {/* Balance Display — compact on mobile since BalanceHero already shows it */} +
+
+
Balance
+
+ {totalBalance.toLocaleString()} + sats
- )} + {usdValue !== null && ( +
+ ≈ ${usdValue.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} +
+ )} +
+
{/* Active Mint Selector */} {mints.length > 0 && ( -
- +
+ setQuoteAmount(e.target.value)} - className="min-w-0" + className="h-11 min-w-0" /> @@ -324,54 +330,55 @@ export function CashuWalletCard() {
{/* Cashu Token */} -
-
- - -
-
- setTokenInput(e.target.value)} - className="font-mono text-xs" - /> - -
-
+
+
+ + +
+
+ setTokenInput(e.target.value)} + className="font-mono text-xs h-11" + /> + +
+
{/* Send Tab */} {/* Send Token */}
- -
+ +
setSendAmount(e.target.value)} - className="min-w-0" + className="min-w-0 h-11" /> @@ -388,36 +395,36 @@ export function CashuWalletCard() {
{/* Pay Lightning Invoice */} -
-
- - -
-
- setLightningInvoice(e.target.value)} - className="font-mono text-xs" - /> - -
-
+
+
+ + +
+
+ setLightningInvoice(e.target.value)} + className="font-mono text-xs h-11" + /> + +
+
@@ -429,79 +436,72 @@ export function CashuWalletCard() {
{/* Pay Lightning Address */} -
- -
- setLightningAddress(e.target.value)} - /> -
- setSendAmount(e.target.value)} - className="flex-1" - /> - -
-
-
+
+ +
+ setLightningAddress(e.target.value)} + className="h-11" + /> + setSendAmount(e.target.value)} + className="h-11" + /> + +
+
{/* History */} {history.length > 0 && (
-
- -
-
+ +
{history.slice(0, 5).map((entry) => (
-
+
{entry.type === 'mint' || entry.type === 'receive' ? ( - + ) : ( - + )} -
-
- {entry.type === 'mint' && 'Received Lightning'} - {entry.type === 'melt' && 'Sent Lightning'} - {entry.type === 'send' && 'Sent Token'} - {entry.type === 'receive' && 'Received Token'} +
+
+ {entry.type === 'mint' && 'Received ⚡ Lightning'} + {entry.type === 'melt' && 'Sent ⚡ Lightning'} + {entry.type === 'send' && 'Sent 🥜 Token'} + {entry.type === 'receive' && 'Received 🥜 Token'}
{new Date(entry.timestamp).toLocaleDateString()}
-
-
+
+
{entry.type === 'mint' || entry.type === 'receive' ? '+' : '-'} - {entry.amount.toLocaleString()} sats + {entry.amount.toLocaleString()}
- - {entry.status} - +
sats
))} @@ -512,34 +512,29 @@ export function CashuWalletCard() { {/* What is Cashu Info Card */} - - - + + + What is Cashu? - -

+ +

Cashu is digital cash backed by Bitcoin Lightning. Think of it as Bitcoin tokens you hold in your browser.

-
-
- ✅ - Works offline at skate spots -
-
- ✅ - Instant peer-to-peer payments -
-
- ✅ - Privacy-focused (mints don't track you) -
-
- ✅ - Always redeemable for Lightning sats -
+
+ {[ + 'Works offline at skate spots', + 'Instant peer-to-peer payments', + "Privacy-focused (mints can't track you)", + 'Always redeemable for Lightning sats', + ].map((item) => ( +
+ ✅ + {item} +
+ ))}
- - + + + Backup Your Wallet - -

- Your wallet is secured with a 12-word recovery phrase. Save it safely - you'll need it to restore your balance if you clear browser data. + +

+ Your wallet is secured with a 12-word recovery phrase. Save it safely — you'll need it to restore your balance if you clear browser data.

- This is like your Nostr nsec - keep it secret and backed up! + This is like your Nostr nsec — keep it secret and backed up!

diff --git a/src/index.css b/src/index.css index 24e6bcf..233699e 100644 --- a/src/index.css +++ b/src/index.css @@ -413,11 +413,17 @@ html { display: none; /* Chrome, Safari and Opera */ } -/* Extra small breakpoint for very small phones */ +/* Extra small breakpoint for very small phones (375px+) */ @media (min-width: 375px) { - .xs\:inline { - display: inline; - } + .xs\:inline { display: inline; } + .xs\:flex { display: flex; } + .xs\:hidden { display: none; } + .xs\:flex-row { flex-direction: row; } + .xs\:px-4 { padding-left: 1rem; padding-right: 1rem; } + .xs\:-mx-4 { margin-left: -1rem; margin-right: -1rem; } + .xs\:text-xs { font-size: 0.75rem; line-height: 1rem; } + .xs\:text-sm { font-size: 0.875rem; line-height: 1.25rem; } + .xs\:gap-2 { gap: 0.5rem; } } /* ─── Global UI/UX Polish ────────────────────────────────────────────────── */ diff --git a/src/pages/FAQPage.tsx b/src/pages/FAQPage.tsx index ddea76b..13b74d6 100644 --- a/src/pages/FAQPage.tsx +++ b/src/pages/FAQPage.tsx @@ -57,17 +57,17 @@ export default function FAQPage() { return ( -
+
{/* Hero */} -
-
- 🦧 +
+
+ 🦧
-

+

Got Questions?

-

+

Ask The Sasquatch — he knows everything about SkateSpots, Nostr, Bitcoin, and skateboarding.

diff --git a/src/pages/SettingsPage.tsx b/src/pages/SettingsPage.tsx index 5e4e39b..7a0df4d 100644 --- a/src/pages/SettingsPage.tsx +++ b/src/pages/SettingsPage.tsx @@ -503,8 +503,8 @@ function WalletTab() { -
- @@ -545,7 +545,7 @@ function WalletTab() { - @@ -624,49 +624,51 @@ export default function SettingsPage() { return ( -
-
-

- +
+
+

+ Settings

-

+

Manage your account and app preferences

- - {/* Grid tabs for mobile, horizontal for larger screens */} - - - - Profile - - - - My Data - - - - Security - - - - Theme - - - - Relays - - - - Wallet - - - - Advanced - - + + {/* Horizontally scrollable tab bar on mobile — no wrapping */} +
+ + + + Profile + + + + My Data + + + + Security + + + + Theme + + + + Relays + + + + Wallet + + + + Advanced + + +
diff --git a/src/pages/WalletPage.tsx b/src/pages/WalletPage.tsx index bffd73f..17d9d8a 100644 --- a/src/pages/WalletPage.tsx +++ b/src/pages/WalletPage.tsx @@ -25,8 +25,12 @@ import { WalletMinimal, Info, Nut, + ChevronRight, + Bitcoin, } from 'lucide-react'; +// ─── Wallet Status Card ─────────────────────────────────────────────────────── + function WalletStatusCard() { const { webln } = useWallet(); const { connections } = useNWC(); @@ -36,82 +40,85 @@ function WalletStatusCard() { const isReady = webln || hasNWC || hasCashu; return ( - - + +
- - + + Wallet Status - - {isReady ? 'Ready' : 'Not Connected'} + + {isReady ? '✓ Ready' : 'Not Connected'}
- + {isReady ? 'Your wallet is connected and ready to send zaps!' : 'Connect a wallet to enable Lightning zaps'}
- - {/* Cashu Wallet Status */} -
-
- -
-

Cashu Wallet

-

+ + {/* Cashu */} +

+
+
+ +
+
+

Cashu Wallet

+

{hasCashu && cashuBalance > 0 - ? `${cashuBalance.toLocaleString()} sats${cashuUsd ? ` (~$${cashuUsd.toFixed(2)})` : ''}` + ? `${cashuBalance.toLocaleString()} sats${cashuUsd ? ` · $${cashuUsd.toFixed(2)}` : ''}` : 'Built-in ecash wallet'}

- {hasCashu ? ( - - ) : ( - - )} + {hasCashu + ? + : }
- {/* WebLN Status */} -
-
- -
-

WebLN

-

Browser extension wallet

+ {/* WebLN */} +
+
+
+ +
+
+

WebLN

+

Browser extension wallet

- {webln ? ( - - ) : ( - - )} + {webln + ? + : }
- {/* NWC Status */} -
-
- -
-

Nostr Wallet Connect

-

+ {/* NWC */} +

+
+
+ +
+
+

Nostr Wallet Connect

+

{connections.length > 0 ? `${connections.length} wallet${connections.length !== 1 ? 's' : ''} connected` : 'Remote wallet connection'}

- {hasNWC ? ( - - ) : ( - - )} + {hasNWC + ? + : }
- @@ -121,162 +128,112 @@ function WalletStatusCard() { ); } +// ─── Zaps Info Card ─────────────────────────────────────────────────────────── + function ZapsInfoCard() { + const items = [ + { emoji: '⚡', title: 'Instant', desc: 'Payments settle in seconds over Lightning' }, + { emoji: '🔐', title: 'Flexible custody', desc: 'Use your own wallet or a custodial service' }, + { emoji: '🥜', title: 'NutZaps for privacy', desc: "Cashu ecash — mints can't see who pays whom" }, + { emoji: '💜', title: 'Value for value', desc: 'Support creators directly' }, + ]; + return ( - - - + + + What are Zaps? - -

- Zaps are Lightning Network micropayments on Nostr. They allow you to send - satoshis (sats) instantly to other users as a way of tipping, thanking, or - supporting their content. + +

+ Zaps are Lightning micropayments — send sats instantly to any skater, spot creator, or coach. No middleman, no platform cut.

- -
-
-
- ⚡ +
+ {items.map((item) => ( +
+ {item.emoji} +
+

{item.title}

+

{item.desc}

+
-
-

Instant

-

- Payments settle in seconds over the Lightning Network -

-
-
- -
-
- 🔐 -
-
-

Flexible custody

-

- Use your own wallet (self-custodial) or a custodial service - your choice -

-
-
- -
-
- 🥜 -
-
-

NutZaps for privacy

-

- Use Cashu ecash for private zaps - mints can't see who pays whom -

-
-
- -
-
- 💜 -
-
-

Value for value

-

- Support creators directly for content you appreciate -

-
-
+ ))}
); } +// ─── Recommended Wallets ────────────────────────────────────────────────────── + function WalletResourcesCard() { - const walletResources = [ - { - name: 'Alby', - description: 'Browser extension wallet with WebLN + NWC support', - url: 'https://getalby.com', - type: 'WebLN', - }, - { - name: 'Minibits', - description: 'Mobile Cashu wallet with NWC support', - url: 'https://www.minibits.cash', - type: 'NWC', - }, - { - name: 'Zeus', - description: 'Self-custodial mobile Lightning wallet', - url: 'https://zeusln.com', - type: 'NWC', - }, - { - name: 'Coinos', - description: 'Web-based Lightning wallet, works on any device', - url: 'https://coinos.io', - type: 'NWC', - }, + const wallets = [ + { name: 'Alby', desc: 'Browser extension · WebLN + NWC', url: 'https://getalby.com', type: 'WebLN', color: 'text-yellow-400' }, + { name: 'Minibits', desc: 'Mobile Cashu wallet · NWC', url: 'https://www.minibits.cash', type: 'NWC', color: 'text-orange-400' }, + { name: 'Zeus', desc: 'Self-custodial mobile Lightning', url: 'https://zeusln.com', type: 'NWC', color: 'text-blue-400' }, + { name: 'Coinos', desc: 'Web-based · works everywhere', url: 'https://coinos.io', type: 'NWC', color: 'text-green-400' }, ]; return ( - - - + + + Recommended Wallets - - Get started with one of these Lightning wallets - + Get started with one of these Lightning wallets - -
- {walletResources.map((wallet) => ( - - + + + ))} - - Want to learn more? Check out Plan B Academy's wallet guides + + Learn more at Plan B Academy ); } +// ─── Not Logged In ──────────────────────────────────────────────────────────── + function NotLoggedInCard() { return ( - - - -

Login Required

-

+ + +

+ +
+

Login Required

+

Log in with your Nostr account to connect your Lightning wallet and start zapping.

@@ -285,6 +242,75 @@ function NotLoggedInCard() { ); } +// ─── Balance Hero Banner ────────────────────────────────────────────────────── + +function BalanceHero() { + const { totalBalance: cashuBalance, isInitialized: hasCashu } = useCashu(); + const cashuUsd = useSatsToUsd(cashuBalance); + const { webln } = useWallet(); + const { connections } = useNWC(); + const hasNWC = connections.length > 0 && connections.some(c => c.isConnected); + + return ( +
+ {/* Background glow */} +
+
+ +
+
+
+ + Cashu Balance +
+
+ {hasCashu ? cashuBalance.toLocaleString() : '—'} + sats +
+ {cashuUsd !== null && cashuBalance > 0 && ( +
+ ≈ ${cashuUsd.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} +
+ )} + {/* Wallet status pills */} +
+ {hasCashu && ( + + Cashu + + )} + {webln && ( + + WebLN + + )} + {hasNWC && ( + + NWC + + )} + {!hasCashu && !webln && !hasNWC && ( + + No wallet connected + + )} +
+
+ + {/* Manage button */} + + + +
+
+ ); +} + +// ─── Page ───────────────────────────────────────────────────────────────────── + export default function WalletPage() { useSeoMeta({ title: 'Wallet - SkateSpots', @@ -295,58 +321,63 @@ export default function WalletPage() { return ( -
+
{/* Header */} -
-

Wallet

-

- Manage your Bitcoin and send zaps to skaters and creators +

+

+ + Wallet +

+

+ Bitcoin Lightning payments & zaps

{user ? ( -
- {/* Wallet Comparison Guide */} +
+ {/* Balance hero — always at top for logged-in users */} + + + {/* Quick Guide — collapsed by default */} - - + {/* Tab pills — full width, thumb-friendly height */} + + - Cashu Wallet + Cashu - + Lightning - - - + {/* Cashu tab */} + + + - - {/* Privacy Tips at the top */} - - -
-
- - -
-
- -
-
-
+ {/* Lightning tab */} + + + + + +
) : ( -
+
-
- -
+
)}