Files
nebula/_migrate/tokens.html

1215 lines
50 KiB
HTML
Raw Normal View History

<!DOCTYPE html>
<!--
================================================================================
TEMPL MIGRATION GUIDE: tokens.html → views/tokens.templ
================================================================================
PAGE OVERVIEW:
- Token portfolio view with sortable table
- Stats: Portfolio Value with change, Allocation chart, Total Assets count
- Network filter tabs (All, Sonr, Ethereum, Cosmos)
- Search input for token filtering
- Sortable columns: Asset, Price, 24h Change, Holdings, Value
- Sparkline mini-charts showing 24h price movement
- Token actions: Send, Receive, Swap, View Chart, Explorer, Hide
MAIN TEMPL COMPONENT:
templ TokensPage(data TokensData) {
@layouts.DashboardLayout("tokens") {
@PageHeader("Tokens", "All crypto assets across networks")
@TokensStatsGrid(data.Stats)
@TokensTableCard(data.Tokens, data.Filter)
}
}
HTMX INTEGRATION:
- Network filter tabs: hx-get="/tokens?network=sonr" hx-target="#tokens-table" hx-push-url="true"
- Search input: hx-get="/tokens?search={query}" hx-trigger="keyup changed delay:300ms" hx-target="#tokens-tbody"
- Column sorting: hx-get="/tokens?sort=value&dir=desc" hx-target="#tokens-tbody"
- Import token: hx-get="/dialogs/import-token" hx-target="#dialog-container"
- Token actions: hx-get="/drawers/send?token=ETH" hx-target="#drawer-container"
- Hide token: hx-post="/api/tokens/hide" hx-vals='{"symbol":"OP"}' hx-target="closest tr" hx-swap="delete"
SUB-COMPONENTS TO EXTRACT:
- TokensStatsGrid(stats TokensStats)
- PortfolioValueCard(value float64, change float64, changePercent float64)
- AllocationCard(allocations []Allocation)
- AllocationBar(allocations []Allocation)
- AllocationLegend(allocations []Allocation)
- TokensTableCard(tokens []TokenRow, filter TokenFilter)
- TokensFilterBar(filter TokenFilter)
- NetworkTabs(activeNetwork string)
- TokensTable(tokens []TokenRow, sortColumn string, sortDir string)
- TokenTableRow(token TokenRow)
- SparklineChart(data []float64, isPositive bool)
- NetworkBadge(network string, color string)
- TokenActionsDropdown(token TokenRow)
STATE/PROPS:
type TokensData struct {
Stats TokensStats
Tokens []TokenRow
Filter TokenFilter
}
type TokensStats struct {
TotalValue float64
Change24h float64
ChangePercent float64
TotalAssets int
NetworkCount int
Allocations []Allocation
}
type Allocation struct {
Symbol string
Percent float64
Color string
}
type TokenFilter struct {
Network string
Search string
Sort string
SortDir string
}
type TokenRow struct {
Symbol string
Name string
Network string
NetworkColor string
Price float64
Change24h float64
SparklineData []float64
Holdings float64
ValueUSD float64
ValueChange float64
IconColor string
HasBalance bool
}
HTMX PATTERNS:
// Network filter tabs with URL push
<wa-tab-group hx-on:wa-tab-show="
htmx.ajax('GET', '/tokens?network=' + event.detail.name, {target: '#tokens-tbody', pushUrl: true})
">
// Search with debounce
<wa-input hx-get="/tokens/search"
hx-trigger="keyup changed delay:300ms"
hx-target="#tokens-tbody"
hx-include="[name='network']"
name="search">
// Sortable column headers
<th class="sortable"
hx-get="/tokens?sort=value&dir={nextDir}"
hx-target="#tokens-tbody"
hx-include="[name='network'],[name='search']">
Value
<wa-icon name="sort"></wa-icon>
</th>
// Token row actions
<wa-dropdown-item hx-get="/drawers/send?token={token.Symbol}"
hx-target="#drawer-container">
Send
</wa-dropdown-item>
// Hide token with row deletion
<wa-dropdown-item hx-post="/api/tokens/{token.Symbol}/hide"
hx-target="closest tr"
hx-swap="delete"
hx-confirm="Hide {token.Name}?">
// Import token dialog
<wa-button hx-get="/dialogs/import-token"
hx-target="#dialog-container"
hx-swap="innerHTML">
Import Token
</wa-button>
// Sparkline as server-rendered SVG
templ SparklineChart(data []float64, isPositive bool) {
<svg class="spark-chart" viewBox="0 0 100 32">
<polyline class={ sparkClass(isPositive) }
points={ sparklinePoints(data) } />
</svg>
}
================================================================================
-->
<html lang="en" class="wa-cloak">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Tokens - Sonr Motr Wallet</title>
<script src="https://cdn.sonr.org/wa/autoloader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/d3@7"></script>
<script src="charts.js"></script>
<style>
:root {
--wa-color-primary: #17c2ff;
}
html, body {
min-height: 100%;
padding: 0;
margin: 0;
}
.dashboard-layout {
display: grid;
grid-template-columns: 240px 1fr;
min-height: 100vh;
}
@media (max-width: 768px) {
.dashboard-layout {
grid-template-columns: 1fr;
}
.sidebar {
display: none;
}
}
.sidebar {
border-right: 1px solid var(--wa-color-neutral-200);
padding: var(--wa-space-m);
background: var(--wa-color-surface);
}
.sidebar-header {
padding: var(--wa-space-s) var(--wa-space-xs);
margin-bottom: var(--wa-space-m);
}
.sidebar-nav {
list-style: none;
padding: 0;
margin: 0;
}
.sidebar-nav li {
margin-bottom: var(--wa-space-2xs);
}
.sidebar-nav a {
display: flex;
align-items: center;
gap: var(--wa-space-s);
padding: var(--wa-space-s) var(--wa-space-m);
border-radius: var(--wa-radius-m);
text-decoration: none;
color: var(--wa-color-neutral-700);
font-size: var(--wa-font-size-s);
transition: background 0.15s;
}
.sidebar-nav a:hover {
background: var(--wa-color-surface-alt);
}
.sidebar-nav a.active {
background: var(--wa-color-primary-subtle);
color: var(--wa-color-primary);
font-weight: 500;
}
.main-content {
padding: var(--wa-space-xl);
background: var(--wa-color-surface-alt);
overflow-y: auto;
}
.page-header {
margin-bottom: var(--wa-space-xl);
}
.stats-grid {
--min-column-size: 200px;
margin-bottom: var(--wa-space-xl);
}
.stat-card {
background: var(--wa-color-surface);
}
.tokens-table {
width: 100%;
border-collapse: collapse;
background: var(--wa-color-surface);
border-radius: var(--wa-radius-l);
overflow: hidden;
}
.tokens-table th {
text-align: left;
padding: var(--wa-space-m) var(--wa-space-l);
font-size: var(--wa-font-size-xs);
font-weight: 500;
color: var(--wa-color-neutral-500);
text-transform: uppercase;
letter-spacing: 0.05em;
border-bottom: 1px solid var(--wa-color-neutral-200);
background: var(--wa-color-surface);
}
.tokens-table th.sortable {
cursor: pointer;
user-select: none;
}
.tokens-table th.sortable:hover {
color: var(--wa-color-neutral-700);
}
.tokens-table td {
padding: var(--wa-space-m) var(--wa-space-l);
border-bottom: 1px solid var(--wa-color-neutral-100);
font-size: var(--wa-font-size-s);
vertical-align: middle;
}
.tokens-table tr:hover td {
background: var(--wa-color-surface-alt);
}
.tokens-table tr:last-child td {
border-bottom: none;
}
.token-cell {
display: flex;
align-items: center;
gap: var(--wa-space-s);
}
.spark-chart {
width: 100px;
height: 32px;
}
.spark-chart svg {
width: 100%;
height: 100%;
}
.spark-up { stroke: var(--wa-color-success); }
.spark-down { stroke: var(--wa-color-danger); }
.change-positive { color: var(--wa-color-success); }
.change-negative { color: var(--wa-color-danger); }
.network-badge {
display: inline-flex;
align-items: center;
gap: var(--wa-space-2xs);
padding: var(--wa-space-2xs) var(--wa-space-xs);
background: var(--wa-color-surface-alt);
border-radius: var(--wa-radius-s);
font-size: var(--wa-font-size-xs);
color: var(--wa-color-neutral-600);
}
.filter-bar {
display: flex;
align-items: center;
gap: var(--wa-space-m);
margin-bottom: var(--wa-space-l);
flex-wrap: wrap;
}
.table-actions {
display: flex;
gap: var(--wa-space-xs);
}
.portfolio-allocation {
display: flex;
height: 8px;
border-radius: var(--wa-radius-s);
overflow: hidden;
margin-bottom: var(--wa-space-xs);
}
.allocation-segment {
transition: width 0.3s ease;
}
.allocation-legend {
display: flex;
flex-wrap: wrap;
gap: var(--wa-space-m);
}
.legend-item {
display: flex;
align-items: center;
gap: var(--wa-space-2xs);
font-size: var(--wa-font-size-xs);
}
.legend-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.chart-dialog-content {
min-height: 400px;
}
.chart-header {
display: flex;
align-items: center;
gap: var(--wa-space-m);
margin-bottom: var(--wa-space-l);
}
.chart-timeframe {
margin-left: auto;
}
.chart-stats {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: var(--wa-space-m);
margin-top: var(--wa-space-l);
padding-top: var(--wa-space-l);
border-top: 1px solid var(--wa-color-neutral-200);
}
.chart-stat {
text-align: center;
}
.chart-stat-label {
font-size: var(--wa-font-size-xs);
color: var(--wa-color-neutral-500);
margin-bottom: var(--wa-space-2xs);
}
.chart-stat-value {
font-size: var(--wa-font-size-m);
font-weight: 600;
}
</style>
</head>
<body>
<wa-page>
<div class="dashboard-layout">
<aside class="sidebar">
<div class="sidebar-header">
<div class="wa-cluster wa-gap-s">
<wa-avatar initials="S" style="--size: 32px; background: var(--wa-color-primary);"></wa-avatar>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Sonr Wallet</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">sonr1x9f...7k2m</span>
</div>
</div>
</div>
<nav>
<ul class="sidebar-nav">
<li>
<a href="accounts.html">
<wa-icon name="wallet"></wa-icon>
Accounts
</a>
</li>
<li>
<a href="transactions.html">
<wa-icon name="arrow-right-arrow-left"></wa-icon>
Transactions
</a>
</li>
<li>
<a href="tokens.html" class="active">
<wa-icon name="coins"></wa-icon>
Tokens
</a>
</li>
<li>
<a href="nfts.html">
<wa-icon name="image"></wa-icon>
NFTs
</a>
</li>
<li>
<a href="activity.html">
<wa-icon name="chart-line"></wa-icon>
Activity
</a>
</li>
</ul>
</nav>
<wa-divider style="margin: var(--wa-space-l) 0;"></wa-divider>
<ul class="sidebar-nav">
<li>
<a href="connections.html">
<wa-icon name="plug"></wa-icon>
Connections
</a>
</li>
<li>
<a href="device.html">
<wa-icon name="mobile"></wa-icon>
Devices
</a>
</li>
<li>
<a href="service.html">
<wa-icon name="server"></wa-icon>
Services
</a>
</li>
<li>
<a href="settings.html">
<wa-icon name="gear"></wa-icon>
Settings
</a>
</li>
</ul>
</aside>
<main class="main-content">
<header class="page-header">
<div class="wa-flank">
<div class="wa-stack wa-gap-2xs">
<span class="wa-heading-xl">Tokens</span>
<span class="wa-caption-s" style="color: var(--wa-color-neutral-500);">All crypto assets across Sonr networks</span>
</div>
<div class="wa-cluster wa-gap-s">
<wa-button variant="neutral" appearance="outlined" size="small">
<wa-icon slot="start" name="plus"></wa-icon>
Import Token
</wa-button>
<wa-button variant="brand" size="small">
<wa-icon slot="start" name="arrow-right-arrow-left"></wa-icon>
Swap
</wa-button>
</div>
</div>
</header>
<div class="wa-grid stats-grid">
<wa-card class="stat-card">
<div class="wa-stack wa-gap-xs">
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">Portfolio Value</span>
<span class="wa-heading-2xl">
<wa-format-number type="currency" currency="USD" value="12847.32" lang="en-US"></wa-format-number>
</span>
<span class="wa-caption-s change-positive">
<wa-icon name="arrow-trend-up" style="font-size: 12px;"></wa-icon>
+$302.18 (2.4%) today
</span>
</div>
</wa-card>
<wa-card class="stat-card">
<div class="wa-stack wa-gap-xs">
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">Portfolio Allocation</span>
<div class="portfolio-allocation">
<div class="allocation-segment" style="width: 52%; background: #627eea;"></div>
<div class="allocation-segment" style="width: 33%; background: linear-gradient(135deg, #17c2ff, #0090ff);"></div>
<div class="allocation-segment" style="width: 10%; background: #2775ca;"></div>
<div class="allocation-segment" style="width: 5%; background: #e84142;"></div>
</div>
<div class="allocation-legend">
<span class="legend-item"><span class="legend-dot" style="background: #627eea;"></span>ETH 52%</span>
<span class="legend-item"><span class="legend-dot" style="background: #17c2ff;"></span>SNR 33%</span>
<span class="legend-item"><span class="legend-dot" style="background: #2775ca;"></span>USDC 10%</span>
<span class="legend-item"><span class="legend-dot" style="background: #e84142;"></span>AVAX 5%</span>
</div>
</div>
</wa-card>
<wa-card class="stat-card">
<div class="wa-flank">
<div class="wa-stack wa-gap-3xs">
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">Total Assets</span>
<span class="wa-heading-2xl">7</span>
<span class="wa-caption-s" style="color: var(--wa-color-neutral-500);">across 3 networks</span>
</div>
</div>
</wa-card>
</div>
<wa-card>
<div class="filter-bar">
<wa-tab-group style="flex: 1;">
<wa-tab panel="all">All Networks</wa-tab>
<wa-tab panel="sonr">Sonr Mainnet</wa-tab>
<wa-tab panel="ethereum">Ethereum</wa-tab>
<wa-tab panel="cosmos">Cosmos</wa-tab>
</wa-tab-group>
<wa-input placeholder="Search tokens..." size="small" style="width: 200px;">
<wa-icon slot="prefix" name="magnifying-glass"></wa-icon>
</wa-input>
</div>
<table class="tokens-table">
<thead>
<tr>
<th class="sortable">
Asset
<wa-icon name="sort" style="font-size: 10px; margin-left: 4px;"></wa-icon>
</th>
<th>Network</th>
<th class="sortable">
Price
<wa-icon name="sort" style="font-size: 10px; margin-left: 4px;"></wa-icon>
</th>
<th>24h Chart</th>
<th class="sortable">
24h Change
<wa-icon name="sort" style="font-size: 10px; margin-left: 4px;"></wa-icon>
</th>
<th class="sortable">
Holdings
<wa-icon name="sort" style="font-size: 10px; margin-left: 4px;"></wa-icon>
</th>
<th class="sortable">
Value
<wa-icon name="sort" style="font-size: 10px; margin-left: 4px;"></wa-icon>
</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div class="token-cell">
<wa-avatar initials="E" style="--size: 36px; background: #627eea;"></wa-avatar>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Ethereum</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">ETH</span>
</div>
</div>
</td>
<td>
<span class="network-badge">
<wa-icon name="circle" variant="solid" style="font-size: 6px; color: #627eea;"></wa-icon>
Ethereum
</span>
</td>
<td>
<wa-format-number type="currency" currency="USD" value="2345.67" lang="en-US"></wa-format-number>
</td>
<td>
<div class="spark-chart">
<svg viewBox="0 0 100 32" preserveAspectRatio="none">
<polyline class="spark-up" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
points="0,20 10,22 20,18 30,19 40,15 50,16 60,12 70,14 80,10 90,8 100,6" />
</svg>
</div>
</td>
<td>
<span class="change-positive">
<wa-icon name="arrow-up" style="font-size: 10px;"></wa-icon>
+3.24%
</span>
</td>
<td>
<div class="wa-stack wa-gap-0">
<span>2.847 ETH</span>
</div>
</td>
<td>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">$6,682.04</span>
<span class="wa-caption-xs change-positive">+$209.51</span>
</div>
</td>
<td>
<div class="table-actions">
<wa-tooltip content="Send">
<wa-icon-button name="arrow-up" label="Send"></wa-icon-button>
</wa-tooltip>
<wa-tooltip content="Receive">
<wa-icon-button name="arrow-down" label="Receive"></wa-icon-button>
</wa-tooltip>
<wa-dropdown>
<wa-icon-button slot="trigger" name="ellipsis-vertical" label="More"></wa-icon-button>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-right-arrow-left"></wa-icon>Swap</wa-dropdown-item>
<wa-dropdown-item><wa-icon slot="icon" name="chart-simple"></wa-icon>View Chart</wa-dropdown-item>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-up-right-from-square"></wa-icon>Explorer</wa-dropdown-item>
<wa-divider></wa-divider>
<wa-dropdown-item variant="danger"><wa-icon slot="icon" name="eye-slash"></wa-icon>Hide Token</wa-dropdown-item>
</wa-dropdown>
</div>
</td>
</tr>
<tr>
<td>
<div class="token-cell">
<wa-avatar initials="S" style="--size: 36px; background: linear-gradient(135deg, #17c2ff, #0090ff);"></wa-avatar>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Sonr</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">SNR</span>
</div>
</div>
</td>
<td>
<span class="network-badge">
<wa-icon name="circle" variant="solid" style="font-size: 6px; color: #17c2ff;"></wa-icon>
Sonr Mainnet
</span>
</td>
<td>
<wa-format-number type="currency" currency="USD" value="0.50" lang="en-US"></wa-format-number>
</td>
<td>
<div class="spark-chart">
<svg viewBox="0 0 100 32" preserveAspectRatio="none">
<polyline class="spark-up" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
points="0,24 10,22 20,20 30,22 40,18 50,16 60,14 70,16 80,12 90,10 100,8" />
</svg>
</div>
</td>
<td>
<span class="change-positive">
<wa-icon name="arrow-up" style="font-size: 10px;"></wa-icon>
+5.67%
</span>
</td>
<td>
<div class="wa-stack wa-gap-0">
<span>8,432.50 SNR</span>
</div>
</td>
<td>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">$4,216.25</span>
<span class="wa-caption-xs change-positive">+$226.12</span>
</div>
</td>
<td>
<div class="table-actions">
<wa-tooltip content="Send">
<wa-icon-button name="arrow-up" label="Send"></wa-icon-button>
</wa-tooltip>
<wa-tooltip content="Receive">
<wa-icon-button name="arrow-down" label="Receive"></wa-icon-button>
</wa-tooltip>
<wa-dropdown>
<wa-icon-button slot="trigger" name="ellipsis-vertical" label="More"></wa-icon-button>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-right-arrow-left"></wa-icon>Swap</wa-dropdown-item>
<wa-dropdown-item><wa-icon slot="icon" name="chart-simple"></wa-icon>View Chart</wa-dropdown-item>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-up-right-from-square"></wa-icon>Explorer</wa-dropdown-item>
<wa-divider></wa-divider>
<wa-dropdown-item variant="danger"><wa-icon slot="icon" name="eye-slash"></wa-icon>Hide Token</wa-dropdown-item>
</wa-dropdown>
</div>
</td>
</tr>
<tr>
<td>
<div class="token-cell">
<wa-avatar initials="U" style="--size: 36px; background: #2775ca;"></wa-avatar>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">USD Coin</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">USDC</span>
</div>
</div>
</td>
<td>
<span class="network-badge">
<wa-icon name="circle" variant="solid" style="font-size: 6px; color: #627eea;"></wa-icon>
Ethereum
</span>
</td>
<td>
<wa-format-number type="currency" currency="USD" value="1.00" lang="en-US"></wa-format-number>
</td>
<td>
<div class="spark-chart">
<svg viewBox="0 0 100 32" preserveAspectRatio="none">
<polyline stroke="var(--wa-color-neutral-400)" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
points="0,16 10,16 20,16 30,16 40,16 50,16 60,16 70,16 80,16 90,16 100,16" />
</svg>
</div>
</td>
<td>
<span style="color: var(--wa-color-neutral-500);">
0.00%
</span>
</td>
<td>
<div class="wa-stack wa-gap-0">
<span>1,250.00 USDC</span>
</div>
</td>
<td>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">$1,250.00</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">$0.00</span>
</div>
</td>
<td>
<div class="table-actions">
<wa-tooltip content="Send">
<wa-icon-button name="arrow-up" label="Send"></wa-icon-button>
</wa-tooltip>
<wa-tooltip content="Receive">
<wa-icon-button name="arrow-down" label="Receive"></wa-icon-button>
</wa-tooltip>
<wa-dropdown>
<wa-icon-button slot="trigger" name="ellipsis-vertical" label="More"></wa-icon-button>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-right-arrow-left"></wa-icon>Swap</wa-dropdown-item>
<wa-dropdown-item><wa-icon slot="icon" name="chart-simple"></wa-icon>View Chart</wa-dropdown-item>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-up-right-from-square"></wa-icon>Explorer</wa-dropdown-item>
<wa-divider></wa-divider>
<wa-dropdown-item variant="danger"><wa-icon slot="icon" name="eye-slash"></wa-icon>Hide Token</wa-dropdown-item>
</wa-dropdown>
</div>
</td>
</tr>
<tr>
<td>
<div class="token-cell">
<wa-avatar initials="A" style="--size: 36px; background: #e84142;"></wa-avatar>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Avalanche</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">AVAX</span>
</div>
</div>
</td>
<td>
<span class="network-badge">
<wa-icon name="circle" variant="solid" style="font-size: 6px; color: #e84142;"></wa-icon>
Avalanche
</span>
</td>
<td>
<wa-format-number type="currency" currency="USD" value="28.15" lang="en-US"></wa-format-number>
</td>
<td>
<div class="spark-chart">
<svg viewBox="0 0 100 32" preserveAspectRatio="none">
<polyline class="spark-down" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
points="0,8 10,10 20,12 30,10 40,14 50,16 60,18 70,16 80,20 90,22 100,24" />
</svg>
</div>
</td>
<td>
<span class="change-negative">
<wa-icon name="arrow-down" style="font-size: 10px;"></wa-icon>
-2.18%
</span>
</td>
<td>
<div class="wa-stack wa-gap-0">
<span>24.83 AVAX</span>
</div>
</td>
<td>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">$699.03</span>
<span class="wa-caption-xs change-negative">-$15.58</span>
</div>
</td>
<td>
<div class="table-actions">
<wa-tooltip content="Send">
<wa-icon-button name="arrow-up" label="Send"></wa-icon-button>
</wa-tooltip>
<wa-tooltip content="Receive">
<wa-icon-button name="arrow-down" label="Receive"></wa-icon-button>
</wa-tooltip>
<wa-dropdown>
<wa-icon-button slot="trigger" name="ellipsis-vertical" label="More"></wa-icon-button>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-right-arrow-left"></wa-icon>Swap</wa-dropdown-item>
<wa-dropdown-item><wa-icon slot="icon" name="chart-simple"></wa-icon>View Chart</wa-dropdown-item>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-up-right-from-square"></wa-icon>Explorer</wa-dropdown-item>
<wa-divider></wa-divider>
<wa-dropdown-item variant="danger"><wa-icon slot="icon" name="eye-slash"></wa-icon>Hide Token</wa-dropdown-item>
</wa-dropdown>
</div>
</td>
</tr>
<tr>
<td>
<div class="token-cell">
<wa-avatar initials="A" style="--size: 36px; background: #2b6cb0;"></wa-avatar>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Cosmos</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">ATOM</span>
</div>
</div>
</td>
<td>
<span class="network-badge">
<wa-icon name="circle" variant="solid" style="font-size: 6px; color: #2b6cb0;"></wa-icon>
Cosmos Hub
</span>
</td>
<td>
<wa-format-number type="currency" currency="USD" value="8.42" lang="en-US"></wa-format-number>
</td>
<td>
<div class="spark-chart">
<svg viewBox="0 0 100 32" preserveAspectRatio="none">
<polyline class="spark-up" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
points="0,18 10,20 20,16 30,18 40,14 50,12 60,14 70,10 80,12 90,8 100,10" />
</svg>
</div>
</td>
<td>
<span class="change-positive">
<wa-icon name="arrow-up" style="font-size: 10px;"></wa-icon>
+1.85%
</span>
</td>
<td>
<div class="wa-stack wa-gap-0">
<span>0.00 ATOM</span>
</div>
</td>
<td>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">$0.00</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);"></span>
</div>
</td>
<td>
<div class="table-actions">
<wa-tooltip content="Send">
<wa-icon-button name="arrow-up" label="Send" disabled></wa-icon-button>
</wa-tooltip>
<wa-tooltip content="Receive">
<wa-icon-button name="arrow-down" label="Receive"></wa-icon-button>
</wa-tooltip>
<wa-dropdown>
<wa-icon-button slot="trigger" name="ellipsis-vertical" label="More"></wa-icon-button>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-right-arrow-left"></wa-icon>Swap</wa-dropdown-item>
<wa-dropdown-item><wa-icon slot="icon" name="chart-simple"></wa-icon>View Chart</wa-dropdown-item>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-up-right-from-square"></wa-icon>Explorer</wa-dropdown-item>
<wa-divider></wa-divider>
<wa-dropdown-item variant="danger"><wa-icon slot="icon" name="eye-slash"></wa-icon>Hide Token</wa-dropdown-item>
</wa-dropdown>
</div>
</td>
</tr>
<tr>
<td>
<div class="token-cell">
<wa-avatar initials="O" style="--size: 36px; background: #ff0420;"></wa-avatar>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Optimism</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">OP</span>
</div>
</div>
</td>
<td>
<span class="network-badge">
<wa-icon name="circle" variant="solid" style="font-size: 6px; color: #ff0420;"></wa-icon>
Optimism
</span>
</td>
<td>
<wa-format-number type="currency" currency="USD" value="1.82" lang="en-US"></wa-format-number>
</td>
<td>
<div class="spark-chart">
<svg viewBox="0 0 100 32" preserveAspectRatio="none">
<polyline class="spark-down" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
points="0,10 10,12 20,14 30,12 40,16 50,18 60,16 70,20 80,18 90,22 100,20" />
</svg>
</div>
</td>
<td>
<span class="change-negative">
<wa-icon name="arrow-down" style="font-size: 10px;"></wa-icon>
-4.32%
</span>
</td>
<td>
<div class="wa-stack wa-gap-0">
<span>0.00 OP</span>
</div>
</td>
<td>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">$0.00</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);"></span>
</div>
</td>
<td>
<div class="table-actions">
<wa-tooltip content="Send">
<wa-icon-button name="arrow-up" label="Send" disabled></wa-icon-button>
</wa-tooltip>
<wa-tooltip content="Receive">
<wa-icon-button name="arrow-down" label="Receive"></wa-icon-button>
</wa-tooltip>
<wa-dropdown>
<wa-icon-button slot="trigger" name="ellipsis-vertical" label="More"></wa-icon-button>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-right-arrow-left"></wa-icon>Swap</wa-dropdown-item>
<wa-dropdown-item><wa-icon slot="icon" name="chart-simple"></wa-icon>View Chart</wa-dropdown-item>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-up-right-from-square"></wa-icon>Explorer</wa-dropdown-item>
<wa-divider></wa-divider>
<wa-dropdown-item variant="danger"><wa-icon slot="icon" name="eye-slash"></wa-icon>Hide Token</wa-dropdown-item>
</wa-dropdown>
</div>
</td>
</tr>
<tr>
<td>
<div class="token-cell">
<wa-avatar initials="A" style="--size: 36px; background: #8247e5;"></wa-avatar>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Polygon</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">MATIC</span>
</div>
</div>
</td>
<td>
<span class="network-badge">
<wa-icon name="circle" variant="solid" style="font-size: 6px; color: #8247e5;"></wa-icon>
Polygon
</span>
</td>
<td>
<wa-format-number type="currency" currency="USD" value="0.52" lang="en-US"></wa-format-number>
</td>
<td>
<div class="spark-chart">
<svg viewBox="0 0 100 32" preserveAspectRatio="none">
<polyline class="spark-up" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
points="0,22 10,20 20,22 30,18 40,20 50,16 60,18 70,14 80,16 90,12 100,10" />
</svg>
</div>
</td>
<td>
<span class="change-positive">
<wa-icon name="arrow-up" style="font-size: 10px;"></wa-icon>
+2.91%
</span>
</td>
<td>
<div class="wa-stack wa-gap-0">
<span>0.00 MATIC</span>
</div>
</td>
<td>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">$0.00</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);"></span>
</div>
</td>
<td>
<div class="table-actions">
<wa-tooltip content="Send">
<wa-icon-button name="arrow-up" label="Send" disabled></wa-icon-button>
</wa-tooltip>
<wa-tooltip content="Receive">
<wa-icon-button name="arrow-down" label="Receive"></wa-icon-button>
</wa-tooltip>
<wa-dropdown>
<wa-icon-button slot="trigger" name="ellipsis-vertical" label="More"></wa-icon-button>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-right-arrow-left"></wa-icon>Swap</wa-dropdown-item>
<wa-dropdown-item><wa-icon slot="icon" name="chart-simple"></wa-icon>View Chart</wa-dropdown-item>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-up-right-from-square"></wa-icon>Explorer</wa-dropdown-item>
<wa-divider></wa-divider>
<wa-dropdown-item variant="danger"><wa-icon slot="icon" name="eye-slash"></wa-icon>Hide Token</wa-dropdown-item>
</wa-dropdown>
</div>
</td>
</tr>
</tbody>
</table>
</wa-card>
</main>
</div>
</wa-page>
<wa-dialog label="Price Chart" id="chart-dialog" style="--width: 800px;">
<div class="chart-dialog-content">
<div class="chart-header">
<wa-avatar id="chart-token-avatar" initials="E" style="--size: 48px; background: #627eea;"></wa-avatar>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-l" id="chart-token-name">Ethereum</span>
<span class="wa-caption-s" style="color: var(--wa-color-neutral-500);" id="chart-token-symbol">ETH</span>
</div>
<div class="chart-timeframe">
<wa-radio-group value="1d" orientation="horizontal" id="chart-timeframe-select">
<wa-radio appearance="button" value="1h">1H</wa-radio>
<wa-radio appearance="button" value="1d">1D</wa-radio>
<wa-radio appearance="button" value="1w">1W</wa-radio>
<wa-radio appearance="button" value="1m">1M</wa-radio>
<wa-radio appearance="button" value="1y">1Y</wa-radio>
</wa-radio-group>
</div>
</div>
<div id="candle-chart-container" style="width: 100%;"></div>
<div class="chart-stats">
<div class="chart-stat">
<div class="chart-stat-label">24h High</div>
<div class="chart-stat-value" id="chart-stat-high">$2,412.50</div>
</div>
<div class="chart-stat">
<div class="chart-stat-label">24h Low</div>
<div class="chart-stat-value" id="chart-stat-low">$2,298.20</div>
</div>
<div class="chart-stat">
<div class="chart-stat-label">24h Volume</div>
<div class="chart-stat-value" id="chart-stat-volume">$12.4B</div>
</div>
<div class="chart-stat">
<div class="chart-stat-label">Market Cap</div>
<div class="chart-stat-value" id="chart-stat-mcap">$282.1B</div>
</div>
</div>
</div>
<div slot="footer" class="wa-cluster wa-gap-s" style="justify-content: flex-end;">
<wa-button variant="neutral" appearance="outlined" data-dialog="close">Close</wa-button>
<wa-button variant="brand">
<wa-icon slot="start" name="arrow-right-arrow-left"></wa-icon>
Trade
</wa-button>
</div>
</wa-dialog>
<script>
document.querySelectorAll('.sidebar-nav a').forEach(link => {
link.addEventListener('click', function(e) {
if (this.getAttribute('href') === '#') {
e.preventDefault();
}
});
});
const chartDialog = document.getElementById('chart-dialog');
let candleChart = null;
const sampleCandleData = [
{ open: 119.31, close: 120.41, high: 120.69, low: 119.22, date: "2025-01-30T16:50:00" },
{ open: 120.37, close: 119.77, high: 120.37, low: 119.47, date: "2025-01-30T17:00:00" },
{ open: 119.78, close: 119.32, high: 120.03, low: 119.26, date: "2025-01-30T17:10:00" },
{ open: 119.33, close: 119.11, high: 119.56, low: 118.94, date: "2025-01-30T17:20:00" },
{ open: 119.11, close: 119.41, high: 119.60, low: 118.93, date: "2025-01-30T17:30:00" },
{ open: 119.39, close: 119.63, high: 119.82, low: 119.33, date: "2025-01-30T17:40:00" },
{ open: 119.62, close: 119.82, high: 120.01, low: 119.62, date: "2025-01-30T17:50:00" },
{ open: 119.82, close: 119.83, high: 119.92, low: 119.17, date: "2025-01-30T18:00:00" },
{ open: 119.82, close: 119.58, high: 119.94, low: 119.50, date: "2025-01-30T18:10:00" },
{ open: 119.59, close: 119.29, high: 119.67, low: 119.08, date: "2025-01-30T18:20:00" },
{ open: 119.30, close: 119.42, high: 119.60, low: 119.20, date: "2025-01-30T18:30:00" },
{ open: 119.42, close: 119.51, high: 119.61, low: 119.32, date: "2025-01-30T18:40:00" },
{ open: 119.51, close: 119.93, high: 120.03, low: 119.37, date: "2025-01-30T18:50:00" },
{ open: 119.95, close: 120.72, high: 120.76, low: 119.82, date: "2025-01-30T19:00:00" },
{ open: 120.71, close: 121.02, high: 121.17, low: 120.69, date: "2025-01-30T19:10:00" },
{ open: 121.03, close: 121.27, high: 121.37, low: 120.82, date: "2025-01-30T19:20:00" },
{ open: 121.27, close: 121.41, high: 121.44, low: 120.81, date: "2025-01-30T19:30:00" },
{ open: 121.43, close: 122.06, high: 122.15, low: 121.17, date: "2025-01-30T19:40:00" },
{ open: 122.06, close: 122.08, high: 122.29, low: 121.80, date: "2025-01-30T19:50:00" },
{ open: 122.09, close: 122.26, high: 122.61, low: 121.71, date: "2025-01-30T20:00:00" },
{ open: 122.25, close: 122.77, high: 122.90, low: 122.19, date: "2025-01-30T20:10:00" },
{ open: 122.77, close: 123.21, high: 123.26, low: 122.70, date: "2025-01-30T20:20:00" },
{ open: 123.22, close: 122.04, high: 123.39, low: 122.04, date: "2025-01-30T20:30:00" },
{ open: 122.06, close: 122.96, high: 123.06, low: 121.76, date: "2025-01-30T20:40:00" },
{ open: 122.62, close: 124.44, high: 124.64, low: 122.54, date: "2025-01-30T20:50:00" },
{ open: 123.50, close: 123.65, high: 124.51, low: 123.04, date: "2025-01-31T14:30:00" },
{ open: 123.70, close: 123.46, high: 124.73, low: 123.37, date: "2025-01-31T14:40:00" },
{ open: 123.54, close: 124.77, high: 124.94, low: 123.43, date: "2025-01-31T14:50:00" },
{ open: 124.87, close: 125.19, high: 126.41, low: 124.85, date: "2025-01-31T15:00:00" },
{ open: 125.17, close: 125.50, high: 125.94, low: 124.86, date: "2025-01-31T15:10:00" },
{ open: 125.49, close: 125.99, high: 126.04, low: 125.28, date: "2025-01-31T15:20:00" },
{ open: 125.96, close: 126.24, high: 126.88, low: 125.96, date: "2025-01-31T15:30:00" },
{ open: 126.26, close: 126.05, high: 126.29, low: 125.57, date: "2025-01-31T15:40:00" },
{ open: 126.07, close: 126.62, high: 126.93, low: 125.63, date: "2025-01-31T15:50:00" },
{ open: 126.61, close: 127.02, high: 127.24, low: 126.58, date: "2025-01-31T16:00:00" },
{ open: 127.05, close: 127.48, high: 127.65, low: 126.93, date: "2025-01-31T16:10:00" },
{ open: 127.47, close: 126.56, high: 127.47, low: 126.41, date: "2025-01-31T16:20:00" },
{ open: 126.60, close: 125.48, high: 126.75, low: 125.43, date: "2025-01-31T16:30:00" },
{ open: 125.47, close: 125.36, high: 125.56, low: 124.64, date: "2025-01-31T16:40:00" },
{ open: 125.37, close: 125.24, high: 125.52, low: 124.97, date: "2025-01-31T16:50:00" },
{ open: 125.22, close: 124.81, high: 125.34, low: 124.21, date: "2025-01-31T17:00:00" },
{ open: 124.84, close: 123.92, high: 124.84, low: 123.92, date: "2025-01-31T17:10:00" },
{ open: 123.93, close: 125.10, high: 125.16, low: 123.89, date: "2025-01-31T17:20:00" },
{ open: 125.11, close: 124.80, high: 125.32, low: 124.62, date: "2025-01-31T17:30:00" },
{ open: 124.78, close: 124.78, high: 124.93, low: 124.71, date: "2025-01-31T17:40:00" },
{ open: 124.76, close: 125.68, high: 125.75, low: 124.70, date: "2025-01-31T17:50:00" },
{ open: 125.68, close: 124.81, high: 125.68, low: 124.77, date: "2025-01-31T18:00:00" },
{ open: 124.81, close: 124.44, high: 124.86, low: 124.44, date: "2025-01-31T18:10:00" },
{ open: 124.46, close: 123.97, high: 124.64, low: 123.93, date: "2025-01-31T18:20:00" },
{ open: 123.97, close: 123.92, high: 124.21, low: 123.37, date: "2025-01-31T18:30:00" },
{ open: 123.90, close: 123.54, high: 124.14, low: 123.25, date: "2025-01-31T18:40:00" },
{ open: 123.54, close: 123.66, high: 123.81, low: 123.12, date: "2025-01-31T18:50:00" },
{ open: 123.60, close: 122.86, high: 123.80, low: 122.54, date: "2025-01-31T19:00:00" },
{ open: 122.89, close: 122.57, high: 123.33, low: 122.39, date: "2025-01-31T19:10:00" },
{ open: 122.59, close: 122.83, high: 123.08, low: 122.49, date: "2025-01-31T19:20:00" },
{ open: 122.82, close: 121.89, high: 122.93, low: 121.89, date: "2025-01-31T19:30:00" },
{ open: 121.87, close: 121.80, high: 122.12, low: 121.07, date: "2025-01-31T19:40:00" },
{ open: 121.83, close: 121.69, high: 121.93, low: 121.13, date: "2025-01-31T19:50:00" },
{ open: 121.68, close: 120.79, high: 121.68, low: 120.67, date: "2025-01-31T20:00:00" },
{ open: 120.80, close: 120.54, high: 121.15, low: 120.42, date: "2025-01-31T20:10:00" },
{ open: 120.52, close: 119.92, high: 120.59, low: 119.72, date: "2025-01-31T20:20:00" }
];
const tokenData = {
ETH: { name: 'Ethereum', color: '#627eea', high: '$2,412.50', low: '$2,298.20', volume: '$12.4B', mcap: '$282.1B' },
SNR: { name: 'Sonr', color: 'linear-gradient(135deg, #17c2ff, #0090ff)', high: '$0.52', low: '$0.47', volume: '$1.2M', mcap: '$50M' },
USDC: { name: 'USD Coin', color: '#2775ca', high: '$1.00', low: '$1.00', volume: '$4.2B', mcap: '$42B' },
AVAX: { name: 'Avalanche', color: '#e84142', high: '$29.50', low: '$27.20', volume: '$892M', mcap: '$10.8B' },
ATOM: { name: 'Cosmos', color: '#2b6cb0', high: '$8.65', low: '$8.12', volume: '$245M', mcap: '$2.9B' },
OP: { name: 'Optimism', color: '#ff0420', high: '$1.95', low: '$1.72', volume: '$156M', mcap: '$1.8B' },
MATIC: { name: 'Polygon', color: '#8247e5', high: '$0.55', low: '$0.49', volume: '$312M', mcap: '$4.6B' }
};
function openChartDialog(symbol) {
const token = tokenData[symbol] || tokenData.ETH;
document.getElementById('chart-token-name').textContent = token.name;
document.getElementById('chart-token-symbol').textContent = symbol;
document.getElementById('chart-token-avatar').style.background = token.color;
document.getElementById('chart-token-avatar').setAttribute('initials', symbol.charAt(0));
document.getElementById('chart-stat-high').textContent = token.high;
document.getElementById('chart-stat-low').textContent = token.low;
document.getElementById('chart-stat-volume').textContent = token.volume;
document.getElementById('chart-stat-mcap').textContent = token.mcap;
chartDialog.open = true;
setTimeout(() => {
const container = document.getElementById('candle-chart-container');
if (candleChart) {
candleChart.setData(sampleCandleData);
} else {
candleChart = new CandleChart(container, { data: sampleCandleData });
}
}, 100);
}
document.querySelectorAll('wa-dropdown-item').forEach(item => {
if (item.textContent.includes('View Chart')) {
item.addEventListener('click', function() {
const row = this.closest('tr');
const symbol = row.querySelector('.wa-caption-xs').textContent;
openChartDialog(symbol);
});
}
});
document.getElementById('chart-timeframe-select').addEventListener('wa-change', function(e) {
if (candleChart) {
candleChart.setData(sampleCandleData);
}
});
</script>
</body>
</html>