Skip to content

Vault dashboard redesign: sidebar + galaxy/donut/heatmap/stack + ⌘K + token-direct nav#181

Open
sktbrd wants to merge 10 commits into
keepkey:developfrom
sktbrd:vladesign
Open

Vault dashboard redesign: sidebar + galaxy/donut/heatmap/stack + ⌘K + token-direct nav#181
sktbrd wants to merge 10 commits into
keepkey:developfrom
sktbrd:vladesign

Conversation

@sktbrd
Copy link
Copy Markdown

@sktbrd sktbrd commented May 18, 2026

This PR brings a substantial UX refresh to the vault dashboard. Everything is gated behind the existing dashboard view-mode preference (persisted to localStorage), so on first load returning users see the new orbital layout but can switch back to a familiar donut at any time.

Highlights

  • Sidebar chain list replaces the cards grid. Each row shows the chain icon, name, USD value (now larger and white-on-text-0 instead of muted), native balance, and a token-count chip. Active row highlights with the chain's color.
  • Galaxy hero region — vertically centered between sidebar and right edge, with a stable y-coordinate so the sun (orbital) and the donut center line up across modes.
  • Four portfolio views, picked from an eye-icon dropdown in the TopNav:
    • Orbital — chains orbiting the portfolio total (default).
    • Chain-detail orbital — drilled-in: chain icon as the sun, clean tokens as orbiting satellites with per-token glow extracted from each icon's dominant color.
    • Donut — restyled chart with an enlarged USD asset amount in the legend, drilled-mode shows the chain's tokens.
    • Heatmap — squarified treemap (Bruls et al, 2000) sized by USD share, fills the entire canvas via ResizeObserver.
    • Stack — horizontal stacked bar with inline labels for large segments and chip legend for the small ones.
  • Always-on Send / Receive / Swap action row when drilled, with Swap routing directly to SwapDialog (no AssetPage detour).
  • AssetPage takes an `initialToken` — clicking a token in the orbital/list lands directly on that token, no second click required.
  • ⌘K command palette — fuzzy search across chains and tokens (substring, prioritized: exact symbol > startsWith > contains). Arrow keys + Enter to jump. Tiny commandBus bridges the palette to Dashboard without lifting state.
  • Icon preloader keeps chain/token logos warm so they don't flash when switching chains.
  • Full-screen ambient radial glow replaces the per-card chrome.
  • Mono is the app-wide default font; serif aliases collapse to mono and decorative cursive headers were dropped.
  • Refresh + Reports moved to the top-right of the page canvas.
  • Hover tooltips flip below the satellite when the satellite is in the upper half of the orbit, so the TopNav never clips them. Token hover cards are tinted with the token's extracted color.
  • 🐕 Dogecoin easter egg — bottom-right Shiba that slides in, bobs, plays a synthesized two-yip bark, throws a random doge-speak phrase, and auto-dismisses after 8 s (timer resets on click). Shown only when the user drills into Dogecoin.

Notes for review

  • This branch was rebased on top of `develop` (merge commit `cc87b0e`). One small conflict in `Dashboard.tsx` around the Refresh button was resolved in favor of the new top-right placement; develop's `refreshBalances(true)` change was carried over.
  • No bun-side changes — all changes live under `projects/keepkey-vault/src/mainview/` and `src/shared/`.
  • Icon network swaps (Optimism/Arbitrum L2 marks → official brand-pack versions) were uploaded to the Spaces bucket out of band; the CDN edge still needs a purge before they're visible. Do not merge before that purge or new icons will look stale to fresh installs until the TTL expires.

Test plan

  • Launch `make dev-hmr` and verify the dashboard renders without errors against a connected KeepKey.
  • Sidebar: click each chain, confirm the galaxy swaps to chain-detail mode for that chain.
  • Try all four views from the eye-icon menu; persistence holds across reloads.
  • Click a token (satellite or list row): AssetPage opens with that token already selected.
  • Click Swap on a drilled chain: SwapDialog opens directly (no underlying receive view).
  • Press ⌘K from anywhere: palette opens, fuzzy search for "USDT" / "eth" / "polygon" → Enter routes correctly.
  • Drill into Dogecoin: doge mascot appears bottom-right, plays bark, auto-dismisses at 8 s.
  • Toggle the donut/orbital/heatmap/stack views: sun and donut centers stay at the same vertical position; heatmap stretches to the full canvas; stack shows inline labels + chip legend.
  • Stop dev-hmr, restart, confirm bun side still builds cleanly (no backend changes were made in this branch beyond the develop merge).

🤖 Generated with Claude Code

sktbrd added 6 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.
sktbrd added 4 commits May 18, 2026 04:02
…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.
Previously the scrollbar width toggled 0 → 6px on hover, which
re-flowed the chain rows. Now the 6px gutter is reserved at all
times and only the thumb opacity changes:
- resting: gutter present, thumb transparent (invisible)
- hover: thumb at rgba(255,255,255,0.06)
- thumb-hover: rgba(255,255,255,0.14)

Firefox `scrollbar-color` mirrors the webkit treatment.
Token page (AssetPage):
- When `initialToken` is set, the header now actually renders the
  token as the primary identity — icon, name, symbol, balance, and
  USD value all switch to the token. The chain shows up as a small
  "on Ethereum" subtitle with a "← chain" pill to drop the token
  context and view the chain.
- Mobile balance row and right-side balance both follow the same
  rule. Send/receive flows already consumed selectedToken, so they
  continue to work; this just makes the page visually feel like a
  token page instead of "chain page with a token internally tracked".

Sidebar scrollbar:
- Dropped `scrollbar-width: thin` — on WebKit it overrode the
  ::-webkit-scrollbar pseudo-elements and let the system thin
  scrollbar paint bright/white over the gutter. Now we only declare
  ::-webkit-scrollbar (6px reserved gutter, transparent track and
  thumb until hover) and gate the Firefox treatment behind a
  `@supports (-moz-appearance: none)` block. `colorScheme: dark`
  on the box for good measure.
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.

1 participant