Skip to content

feat: UI revamp + activity page + swap improvements#184

Open
BitHighlander wants to merge 18 commits into
masterfrom
feature-ui-revamp
Open

feat: UI revamp + activity page + swap improvements#184
BitHighlander wants to merge 18 commits into
masterfrom
feature-ui-revamp

Conversation

@BitHighlander
Copy link
Copy Markdown
Collaborator

Summary

  • UI redesign (vladesign): new v3 component library, ⌘K command palette, portfolio heatmap/stacked-bar/donut views, view picker, dashboard redesign, theme tokens, DogeEasterEgg
  • Activity page: full activity history with PDF reports, tax export, all-network rescan
  • Swap improvements: asset-picker dialog, CAIP routing, deposit-channel hardening (Chainflip), provider badges/animations, ERC-20 guard improvements
  • Emulator infrastructure: 5 bun-side emulator modules + 6 integration test files
  • Windows/Linux build scripts: production build, signing, preflight
  • NEAR Intents removed: P0 fund-loss risk (refunds went to unowned keepkey.near), Pioneer not ready for proper integration — stripped all vault-side workarounds

Test plan

  • Device connects and reaches dashboard
  • ⌘K command palette opens and navigates to chains/tokens
  • Portfolio renders in heatmap, stacked-bar, and donut views
  • Activity page loads swap history and generates PDF report
  • Swap dialog quotes and executes (ETH/BTC/THOR routes)
  • Chainflip deposit-channel swap routes correctly (data=0x guard passes)
  • NEAR Intents is no longer offered as a swap route

sktbrd and others added 16 commits May 18, 2026 03:07
- Sidebar chain list replaces the cards grid; main area centers a
  flex-1 hero region with stable sun/donut y-position.
- Chain-detail orbital (chain icon as the sun, clean tokens orbiting)
  with per-token glow extracted from each icon's dominant color.
- Always-on Receive/Send/Swap action row in drilled mode; Swap opens
  the SwapDialog directly via a lazy import (no AssetPage detour).
- DonutChart enlarged and restyled to match the rest of the app;
  legend pill uses ink palette + bigger USD amount.
- View toggle (orbital/donut) moved to the TopNav, shared with
  Dashboard through a tiny context.
- Mono is the app-wide default font; serif aliases collapse to mono
  and decorative italic headers are dropped.
- Full-screen ambient radial glow, removed per-card chrome around
  the orbital so the glow reads as the page background.
- Refresh + Reports moved to top-right of the main canvas.
- Icon preloader keeps chain/token logos warm so they don't
  re-fetch when switching chains in the sidebar.
- Dogecoin easter egg: bottom-right Shiba that slides in, bobs,
  barks (synthesized), spouts random doge speak, and auto-dismisses
  after 8s (timer resets on click).
Pull in develop's portfolio reliability + cache fixes
(failedPubkeySet, no-walk-backwards cache, api-blue selector,
forceRefresh changes, 1.3.6 prep) so the design branch stays
current and minimizes future conflicts.

# Conflicts:
#	projects/keepkey-vault/src/mainview/components/Dashboard.tsx
- ⌘K / Ctrl+K command palette (CommandPalette.tsx) for fuzzy-jumping
  to any chain or token. Substring matching across name/symbol/CAIP
  with priority (exact symbol > startsWith > contains). Arrow-key
  navigation, Enter to select, Esc/backdrop to close.
- Tiny commandBus.ts pub/sub bridges the palette (lives at the App
  level) to Dashboard's drilldown state and serves Dashboard's
  balances Map for token search without lifting state.
- AssetPage accepts an `initialToken` prop. Clicking a token in the
  orbital (satellite or token list row) now lands directly on the
  token detail view — no more select-again after entering the chain.
- Token hover card in the chain-detail orbital uses the icon's
  extracted dominant color: tinted inset/outer shadow, colored
  symbol text. Falls back to white when extraction returned the
  fallback color.
- Doge easter egg picks a random phrase on initial appearance so
  every remount feels fresh instead of always saying "wow such doge".
- Add a third "heatmap" portfolio view next to orbital/donut in the
  TopNav pill. Renders a squarified treemap (Bruls et al, 2000) where
  each chain (or each token in chain-detail mode) is a tile with area
  proportional to its USD value, tile color from chain.color (or a
  rotating token palette). Click a tile to drill in / open the token.
- DashboardView type extended to 'orbital' | 'donut' | 'heatmap',
  persistence respects the new value.
- Tighten CommandPalette styles: kill the browser default focus ring on
  the search input, restyle the esc badge as a small ink-3 pill,
  smaller magnifying-glass icon in muted text-3 for a calmer look.
- Replace the three-button orbital/donut/heatmap pill in the TopNav with
  a single eye-icon button that drops a 260px menu (ViewPickerMenu.tsx).
  Each menu row carries a small SVG "thumbnail" of the view so the
  selection is visually recognizable, plus a one-line description and
  a gold check on the currently active view.
- Add a fourth view "stack": a horizontal stacked bar (StackedBarView.tsx)
  where each chain (or each token, when drilled) is a colored segment
  proportional to its USD share. Segments above 5% get inline labels
  (name + percentage + value); smaller items collapse into a chip
  legend below the bar. Optional 24h delta slot is wired but not fed
  data yet — pass `deltaUsd`/`deltaPct` once the engine surfaces it.
- DashboardView type extended to 'orbital' | 'donut' | 'heatmap' | 'stack'.
- HeatmapView measures its parent via ResizeObserver and lays out
  squarified tiles to the actual rendered dimensions, instead of the
  prior hardcoded 520×420. Explicit width/height props still supported
  for embedded usages.
- Dashboard wraps the heatmap in a flex-stretch container when the
  user is on the heatmap view, and collapses the bottom slot's reserved
  height when no per-chain content needs to render — gives the heatmap
  the entire area to the right of the sidebar.
…bar scrollbar

- Heatmap squarified layout now applies a value^0.65 compression curve
  so tiny-balance chains still get a usable tile next to five-figure
  positions. Pure proportional sizing made $5 chains effectively
  invisible against $5k chains; this trades exact area accuracy for
  glanceability.
- Heatmap container clamps to `calc(100vh - 90px)` (h + maxH) so the
  layout area equals the visible canvas — small chains no longer fall
  below the viewport fold.
- Outer hero region drops its 60–70vh minH when on the heatmap view
  so the column doesn't push beyond the viewport.
- Sidebar scrollbar is hidden by default and only fades in on hover
  (kk-sidebar-scroll class + scrollbar-width + webkit-scrollbar CSS).
The previous calc(100vh - 90px) guess was wrong because the actual
available height varies with the Dashboard's top-right utility row,
banners, and the App's nav padding. Introduce HeatmapHost which:

- on mount + window resize, reads the container's top via
  getBoundingClientRect and subtracts from window.innerHeight with a
  12 px breathing margin, then sets that as the explicit px height
- re-measures one frame later so it picks up flex-layout-settled rects

Net result: smaller tiles no longer fall below the fold; the heatmap
fills exactly the area between its top edge and the window bottom.
v1.3.6 published as prerelease.
…s alias fix

- ActivityPage: replace homemade CSV export with ReportDialog (PDF + CSV)
- ActivityPage: chain dropdown now shows all supported networks, not just
  networks that happen to appear in current activity
- ActivityPage: Rescan now works without selecting a network — iterates all
  chains when no filter is active; removes the "select a network to scan" gate
- swap-tracker: map nearIntents → shapeshift in PIONEER_INTEGRATION_ALIAS so
  NEAR Intents BTC→EVM swaps register with Pioneer (validator rejects nearIntents)
- ActivityTracker/ActivityPanel: moved bubble and slide-up panel to right side
  (avoids overlapping Vlad's left sidebar)
- docs/handoffs: pioneer-near-intents-tracking.md documenting Pioneer's two bugs
  (integration enum validator, protocol misidentification as thorchain)
- Additional handoff docs from PR #178 diagnostic work

NEAR Intents BTC broadcast confirmed (txid 292ddbb5, 7 confirmations as of today).
Pioneer registration was failing silently on every NEAR Intents swap — now fixed.
Root cause: getSwapQuote(balance) commits NEAR Intents to receiving the
full balance, but buildUtxoTx(isMax=true) only delivers balance-miner_fee.
NEAR Intents hard-fails with PARTIAL_DEPOSIT on any shortfall — slippage
tolerance only applies to the ETH output, not the BTC input amount.

Fixes:
- Add estimateUtxoFee() to txbuilder/utxo.ts (coin selection dry-run)
- For NEAR Intents sendMax BTC: estimate fee first, re-quote with net
  delivery amount so the deposit channel receives what was committed
- Block Pioneer's 'thorchain' swapper adoption for NEAR Intents swaps
  (Pioneer misidentifies memo-less BTC deposits as THORChain)
- Exclude NEAR Intents from Relay request-id backfill path (wrong protocol)
- Update Pioneer handoff with on-chain evidence of the stuck swap and
  confirmed PARTIAL_DEPOSIT root cause from NEAR Intents status API
…ty resume swap

P1: Pass isMax to getSwapQuote so the NEAR Intents sendMax re-quote
path actually fires. SwapDialog was omitting isMax from the quote RPC
call, making the backend guard a dead code path for sendMax BTC swaps.

P2: Queue vault commands when Dashboard is unmounted. CommandPalette
calls onJumpToVault() then dispatchVaultCommand() synchronously, but
React hasn't re-rendered yet so Dashboard's listener isn't subscribed.
commandBus now stashes one pending command and drains it on the next
subscribeVaultCommand() call (Dashboard mount).

P2: ActivityPage can now resume pending swaps. Dashboard was rendering
ActivityPage without onResumeSwap, so clicking a pending swap fell
through to a static detail view. Added activityResumeSwap state and
wired it to LazySwapDialog alongside the ActivityPage render.
…elds

- Dashboard: don't close ActivityPage when opening resume dialog — both
  live in the same showActivityPage branch so the dialog stays mounted.
  onResumeSwap now only sets activityResumeSwap; onClose clears it.
- types: add isMax? and feeLevel? to SwapQuoteParams so the SwapDialog
  quote call and index.ts backend guard have matching type contracts.
NEAR Intents BTC→EVM had a confirmed fund loss (75k sat refunded to keepkey.near
which KeepKey does not control). The vault was accumulating workarounds for Pioneer's
misidentification of NEAR as THORChain and status never advancing past "pending".
Removing the integration entirely until Pioneer has proper server-side support.

- swap-tracker.ts: drop nearIntentsData forwarding, isNearIntentsSwap(), 1Click polling
- swap.ts: drop BTC→EVM quote minimum/expiry guards
- swap-parsing.ts: remove 'NEAR Intents' from DEPOSIT_CHANNEL_SWAPPERS, genericise guards
- docs: remove 5 NEAR Intents handoff docs
@BitHighlander BitHighlander requested a review from pastaghost as a code owner May 19, 2026 17:55
- swap-parsing.ts: drop NEAR Intents quotes before selecting best so a
  supported fallback route (e.g. Chainflip) is used when Pioneer returns
  NEAR first. Falls back to full list only if all quotes are filtered.
- swap-parsing.test.ts: two stale NEAR Intents tests now assert throws;
  added fallback-route test covering the NEAR-first scenario.

Fixes P1 findings from PR #184 review.
latestBalances in commandBus.ts was module-level and never reset, so
stale balances from a previous wallet session persisted in the ⌘K palette
after disconnect or wallet switch.

- commandBus.ts: add clearBalances() that zeroes the cache and notifies listeners
- Dashboard.tsx: call clearBalances() on unmount via a mount-only useEffect

Fixes P2 from PR #184 review.
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.

2 participants