Files
nebula/_migrate/activity.html

883 lines
36 KiB
HTML
Raw Normal View History

<!DOCTYPE html>
<!--
================================================================================
TEMPL MIGRATION GUIDE: activity.html → views/activity.templ
================================================================================
PAGE OVERVIEW:
- Activity dashboard showing sessions, apps, and security events
- Stats cards: Active Sessions, Connected Apps, Pending alerts, Last Active
- Pending Actions section with actionable items (review, sign, block)
- Active Sessions list with revoke capability
- Connected Apps list with permission management
- Activity Log with collapsible day groups and category filtering
MAIN TEMPL COMPONENT:
templ ActivityPage(data ActivityData) {
@layouts.DashboardLayout("activity") {
@PageHeader("Activity", "Sessions, apps, and recent actions")
@ActivityStatsGrid(data.Stats)
@PendingActionsCard(data.PendingActions)
<div class="content-grid">
@ActiveSessionsCard(data.Sessions)
@ConnectedAppsCard(data.Apps)
@ActivityLogCard(data.ActivityLog)
</div>
}
}
HTMX INTEGRATION:
- Refresh button: hx-get="/api/activity" hx-target="#activity-content" hx-indicator="#refresh-icon"
- Pending action buttons: hx-post="/api/activity/action" hx-vals='{"action":"approve","id":"123"}'
- Dismiss action: hx-delete="/api/activity/pending/123" hx-target="closest article" hx-swap="outerHTML"
- Revoke session: hx-delete="/api/sessions/abc" hx-target="closest article" hx-swap="delete"
- Disconnect app: hx-delete="/api/connections/xyz" hx-confirm="Disconnect this app?"
- Activity filter: hx-get="/api/activity/log?filter=security" hx-target="#activity-log"
- Load more: hx-get="/api/activity/log?offset=9" hx-target="#activity-log" hx-swap="beforeend"
- wa-details expansion: Client-side (no HTMX needed)
SUB-COMPONENTS TO EXTRACT:
- ActivityStatsGrid(stats ActivityStats)
- PendingActionsCard(actions []PendingAction)
- PendingActionItem(action PendingAction)
- ActiveSessionsCard(sessions []Session)
- SessionItem(session Session, isCurrent bool)
- ConnectedAppsCard(apps []ConnectedApp)
- AppItem(app ConnectedApp)
- ActivityLogCard(logs []ActivityLogGroup, filter string)
- ActivityLogGroup(date string, entries []ActivityEntry)
- ActivityEntry(entry ActivityEntry)
- ActivityFilterSelect(currentFilter string)
STATE/PROPS:
type ActivityData struct {
Stats ActivityStats
PendingActions []PendingAction
Sessions []Session
Apps []ConnectedApp
ActivityLog []ActivityLogGroup
}
type ActivityStats struct {
ActiveSessions int
ConnectedApps int
PendingCount int
LastActive time.Time
}
type PendingAction struct {
ID string
Type string // "security", "signature", "suspicious", "transaction"
Title string
Description string
Timestamp time.Time
Actions []ActionButton // Review, Dismiss, Sign, Block, etc.
}
type Session struct {
ID string
Device string
Browser string
Location string
IsCurrent bool
LastSeen time.Time
}
type ConnectedApp struct {
ID string
Name string
Domain string
IconColor string
Permissions []string
ConnectedAt time.Time
}
type ActivityLogGroup struct {
Date string
Entries []ActivityEntry
}
type ActivityEntry struct {
Type string // "signin", "auth", "send", "receive", "connect", "swap", "passkey"
Title string
Description string
Timestamp time.Time
Tag string
TagVariant string
}
HTMX PATTERNS:
// Refresh with loading indicator
<wa-button id="refresh-activity"
hx-get="/api/activity/refresh"
hx-target="#activity-content"
hx-indicator="find wa-icon">
// Pending action dismiss with animation
<wa-button hx-delete="/api/activity/pending/{action.ID}"
hx-target="closest article"
hx-swap="outerHTML swap:0.3s"
hx-on::before-request="this.closest('article').style.opacity='0.5'">
// Session revoke
<wa-button hx-delete="/api/sessions/{session.ID}"
hx-target="closest article"
hx-swap="delete"
hx-confirm="Revoke this session?">
// Activity log filtering
<wa-select hx-get="/api/activity/log"
hx-target="#activity-log-entries"
hx-include="this"
name="filter">
// Load more with append
<wa-button hx-get="/api/activity/log?offset=9"
hx-target="#activity-log-entries"
hx-swap="beforeend">
// Sign out all sessions
<wa-button hx-delete="/api/sessions/all"
hx-confirm="Sign out of all other sessions?"
hx-target="#sessions-list">
================================================================================
-->
<html lang="en" class="wa-cloak">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Activity - Sonr Motr Wallet</title>
<script src="https://cdn.sonr.org/wa/autoloader.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: 180px;
margin-bottom: var(--wa-space-xl);
}
.stat-card {
background: var(--wa-color-surface);
}
.content-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--wa-space-xl);
}
@media (max-width: 1024px) {
.content-grid {
grid-template-columns: 1fr;
}
}
.activity-card {
grid-column: 1 / -1;
}
wa-details::part(header) {
font-weight: 600;
}
wa-details::part(content) {
padding-top: var(--wa-space-s);
}
</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">
<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" class="active">
<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">Activity</span>
<span class="wa-caption-s" style="color: var(--wa-color-neutral-500);">Sessions, apps, and recent actions</span>
</div>
<wa-button variant="neutral" appearance="outlined" size="small" id="refresh-activity">
<wa-icon slot="start" name="rotate"></wa-icon>
Refresh
</wa-button>
</div>
</header>
<div class="wa-grid stats-grid">
<wa-card class="stat-card">
<div class="wa-flank">
<wa-avatar shape="rounded" style="background: var(--wa-color-primary-subtle);">
<wa-icon slot="icon" name="desktop" style="color: var(--wa-color-primary);"></wa-icon>
</wa-avatar>
<div class="wa-stack wa-gap-3xs">
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">Active Sessions</span>
<span class="wa-heading-2xl">3</span>
</div>
</div>
</wa-card>
<wa-card class="stat-card">
<div class="wa-flank">
<wa-avatar shape="rounded" style="background: var(--wa-color-success-subtle);">
<wa-icon slot="icon" name="plug" style="color: var(--wa-color-success);"></wa-icon>
</wa-avatar>
<div class="wa-stack wa-gap-3xs">
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">Connected Apps</span>
<span class="wa-heading-2xl">5</span>
</div>
</div>
</wa-card>
<wa-card class="stat-card">
<div class="wa-flank">
<wa-avatar shape="rounded" style="background: var(--wa-color-warning-subtle);">
<wa-icon slot="icon" name="bell" style="color: var(--wa-color-warning);"></wa-icon>
</wa-avatar>
<div class="wa-stack wa-gap-3xs">
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">Pending</span>
<span class="wa-cluster wa-gap-xs">
<span class="wa-heading-2xl">4</span>
<wa-badge variant="warning" attention="pulse" pill>!</wa-badge>
</span>
</div>
</div>
</wa-card>
<wa-card class="stat-card">
<div class="wa-flank">
<wa-avatar shape="rounded" style="background: var(--wa-color-neutral-100);">
<wa-icon slot="icon" name="clock-rotate-left" style="color: var(--wa-color-neutral-600);"></wa-icon>
</wa-avatar>
<div class="wa-stack wa-gap-3xs">
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">Last Active</span>
<wa-relative-time date="2026-01-03T01:49:00" class="wa-heading-s"></wa-relative-time>
</div>
</div>
</wa-card>
</div>
<wa-card style="margin-bottom: var(--wa-space-xl);">
<div slot="header" class="wa-flank">
<span class="wa-heading-m">Pending Actions</span>
<wa-button appearance="plain" size="small">Clear All</wa-button>
</div>
<div class="wa-stack">
<article class="wa-flank:end wa-align-items-baseline" style="--flank-size: auto;">
<div class="wa-flank wa-gap-m" style="flex: 1;">
<wa-icon class="wa-font-size-l" name="shield-halved" style="color: var(--wa-color-warning);"></wa-icon>
<div class="wa-split">
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Security Review Required</span>
<div class="wa-cluster wa-gap-2xs wa-caption-s" style="color: var(--wa-color-neutral-600);">
<span>New device signed in from</span>
<strong>San Francisco, CA</strong>
</div>
</div>
<wa-relative-time date="2026-01-03T01:40:00" class="wa-caption-s"></wa-relative-time>
</div>
</div>
<div class="wa-cluster wa-gap-xs">
<wa-button variant="brand" size="small">Review</wa-button>
<wa-button variant="neutral" appearance="outlined" size="small">Dismiss</wa-button>
</div>
</article>
<wa-divider></wa-divider>
<article class="wa-flank:end wa-align-items-baseline" style="--flank-size: auto;">
<div class="wa-flank wa-gap-m" style="flex: 1;">
<wa-icon class="wa-font-size-l" name="signature" style="color: var(--wa-color-primary);"></wa-icon>
<div class="wa-split">
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Signature Request</span>
<div class="wa-cluster wa-gap-2xs wa-caption-s" style="color: var(--wa-color-neutral-600);">
<a href="#">DeFi Protocol</a>
<span>wants to verify wallet ownership</span>
</div>
</div>
<wa-relative-time date="2026-01-03T01:25:00" class="wa-caption-s"></wa-relative-time>
</div>
</div>
<div class="wa-cluster wa-gap-xs">
<wa-button variant="brand" size="small">Sign</wa-button>
<wa-button variant="danger" appearance="outlined" size="small">Reject</wa-button>
</div>
</article>
<wa-divider></wa-divider>
<article class="wa-flank:end wa-align-items-baseline" style="--flank-size: auto;">
<div class="wa-flank wa-gap-m" style="flex: 1;">
<wa-icon class="wa-font-size-l" name="triangle-exclamation" style="color: var(--wa-color-danger);"></wa-icon>
<div class="wa-split">
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Suspicious Activity</span>
<div class="wa-cluster wa-gap-2xs wa-caption-s" style="color: var(--wa-color-neutral-600);">
<span>Multiple failed logins from IP</span>
<code style="font-size: var(--wa-font-size-xs);">185.234.xx.xx</code>
</div>
</div>
<wa-relative-time date="2026-01-03T00:50:00" class="wa-caption-s"></wa-relative-time>
</div>
</div>
<div class="wa-cluster wa-gap-xs">
<wa-button variant="danger" size="small">Block IP</wa-button>
<wa-button variant="neutral" appearance="outlined" size="small">Details</wa-button>
</div>
</article>
<wa-divider></wa-divider>
<article class="wa-flank:end wa-align-items-baseline" style="--flank-size: auto;">
<div class="wa-flank wa-gap-m" style="flex: 1;">
<wa-icon class="wa-font-size-l" name="arrow-down" style="color: var(--wa-color-success);"></wa-icon>
<div class="wa-split">
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Incoming Transaction</span>
<div class="wa-cluster wa-gap-2xs wa-caption-s" style="color: var(--wa-color-neutral-600);">
<span>From</span>
<a href="#">sonr1k4m...9p3q</a>
</div>
</div>
<wa-relative-time date="2026-01-02T23:50:00" class="wa-caption-s"></wa-relative-time>
</div>
</div>
<wa-tag variant="success">+ 250 SNR</wa-tag>
</article>
</div>
</wa-card>
<div class="content-grid">
<wa-card>
<div slot="header" class="wa-flank">
<span class="wa-heading-m">Active Sessions</span>
<wa-button appearance="plain" size="small" variant="danger">Sign Out All</wa-button>
</div>
<div class="wa-stack">
<article class="wa-flank wa-gap-m">
<wa-icon class="wa-font-size-l" name="desktop" style="color: var(--wa-color-primary);"></wa-icon>
<div class="wa-split">
<div class="wa-stack wa-gap-0">
<div class="wa-cluster wa-gap-xs">
<span class="wa-heading-s">MacBook Pro</span>
<wa-badge variant="success" pill>Current</wa-badge>
</div>
<div class="wa-cluster wa-gap-2xs wa-caption-s" style="color: var(--wa-color-neutral-600);">
<span>Chrome 120</span>
<span>·</span>
<span>San Francisco, CA</span>
</div>
</div>
<span class="wa-caption-xs" style="color: var(--wa-color-success);">Active now</span>
</div>
</article>
<wa-divider></wa-divider>
<article class="wa-flank wa-gap-m">
<wa-icon class="wa-font-size-l" name="mobile" style="color: var(--wa-color-success);"></wa-icon>
<div class="wa-split">
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">iPhone 15 Pro</span>
<div class="wa-cluster wa-gap-2xs wa-caption-s" style="color: var(--wa-color-neutral-600);">
<span>Safari</span>
<span>·</span>
<span>San Francisco, CA</span>
</div>
</div>
<wa-relative-time date="2026-01-02T23:51:00" class="wa-caption-xs"></wa-relative-time>
</div>
<wa-button variant="danger" appearance="plain" size="small">Revoke</wa-button>
</article>
<wa-divider></wa-divider>
<article class="wa-flank wa-gap-m">
<wa-icon class="wa-font-size-l" name="tablet" style="color: var(--wa-color-warning);"></wa-icon>
<div class="wa-split">
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">iPad Air</span>
<div class="wa-cluster wa-gap-2xs wa-caption-s" style="color: var(--wa-color-neutral-600);">
<span>Safari</span>
<span>·</span>
<span>New York, NY</span>
</div>
</div>
<wa-relative-time date="2026-01-02T12:00:00" class="wa-caption-xs"></wa-relative-time>
</div>
<wa-button variant="danger" appearance="plain" size="small">Revoke</wa-button>
</article>
</div>
<div slot="footer">
<a href="#" class="wa-cluster wa-gap-xs wa-caption-s" style="color: var(--wa-color-primary);">
<span>View session history</span>
<wa-icon name="arrow-right"></wa-icon>
</a>
</div>
</wa-card>
<wa-card>
<div slot="header" class="wa-flank">
<span class="wa-heading-m">Connected Apps</span>
<wa-button appearance="plain" size="small">Manage</wa-button>
</div>
<div class="wa-stack">
<article class="wa-flank wa-gap-m">
<wa-avatar initials="D" style="--size: 36px; background: linear-gradient(135deg, #6366f1, #8b5cf6);"></wa-avatar>
<div class="wa-split">
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">DeFi Protocol</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">defi.example.com</span>
</div>
<wa-relative-time date="2025-12-31T12:00:00" class="wa-caption-xs"></wa-relative-time>
</div>
<wa-dropdown>
<wa-icon-button slot="trigger" name="ellipsis-vertical" label="Actions"></wa-icon-button>
<wa-dropdown-item>View Permissions</wa-dropdown-item>
<wa-divider></wa-divider>
<wa-dropdown-item style="color: var(--wa-color-danger);">Disconnect</wa-dropdown-item>
</wa-dropdown>
</article>
<wa-divider></wa-divider>
<article class="wa-flank wa-gap-m">
<wa-avatar initials="N" style="--size: 36px; background: linear-gradient(135deg, #10b981, #059669);"></wa-avatar>
<div class="wa-split">
<div class="wa-stack wa-gap-0">
<div class="wa-cluster wa-gap-xs">
<span class="wa-heading-s">NFT Marketplace</span>
<wa-badge variant="warning" pill>transact</wa-badge>
</div>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">nft.marketplace.io</span>
</div>
<wa-relative-time date="2025-12-27T12:00:00" class="wa-caption-xs"></wa-relative-time>
</div>
<wa-dropdown>
<wa-icon-button slot="trigger" name="ellipsis-vertical" label="Actions"></wa-icon-button>
<wa-dropdown-item>View Permissions</wa-dropdown-item>
<wa-divider></wa-divider>
<wa-dropdown-item style="color: var(--wa-color-danger);">Disconnect</wa-dropdown-item>
</wa-dropdown>
</article>
<wa-divider></wa-divider>
<article class="wa-flank wa-gap-m">
<wa-avatar initials="S" style="--size: 36px; background: linear-gradient(135deg, #f59e0b, #d97706);"></wa-avatar>
<div class="wa-split">
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Staking Dashboard</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">stake.sonr.io</span>
</div>
<wa-relative-time date="2025-12-20T12:00:00" class="wa-caption-xs"></wa-relative-time>
</div>
<wa-dropdown>
<wa-icon-button slot="trigger" name="ellipsis-vertical" label="Actions"></wa-icon-button>
<wa-dropdown-item>View Permissions</wa-dropdown-item>
<wa-divider></wa-divider>
<wa-dropdown-item style="color: var(--wa-color-danger);">Disconnect</wa-dropdown-item>
</wa-dropdown>
</article>
</div>
<div slot="footer">
<a href="connections.html" class="wa-cluster wa-gap-xs wa-caption-s" style="color: var(--wa-color-primary);">
<span>Manage all connections</span>
<wa-icon name="arrow-right"></wa-icon>
</a>
</div>
</wa-card>
<wa-card class="activity-card">
<div slot="header" class="wa-flank">
<span class="wa-heading-m">Activity Log</span>
<div class="wa-cluster wa-gap-s">
<wa-select size="small" value="all" style="min-width: 130px;">
<wa-option value="all">All Activity</wa-option>
<wa-option value="security">Security</wa-option>
<wa-option value="transactions">Transactions</wa-option>
<wa-option value="connections">Connections</wa-option>
</wa-select>
<wa-button appearance="plain" size="small">
<wa-icon slot="start" name="download"></wa-icon>
Export
</wa-button>
</div>
</div>
<div class="wa-stack">
<wa-details open>
<span class="wa-heading-m" slot="summary">Today</span>
<div class="wa-stack">
<article class="wa-flank:end wa-align-items-baseline" style="--flank-size: 10ch;">
<div class="wa-flank wa-gap-m" style="flex: 1;">
<wa-icon name="right-to-bracket" style="color: var(--wa-color-success);"></wa-icon>
<div class="wa-split">
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Signed in</span>
<div class="wa-cluster wa-gap-2xs wa-caption-s" style="color: var(--wa-color-neutral-600);">
<a href="#">MacBook Pro</a>
<span>in San Francisco, CA</span>
</div>
</div>
<wa-format-date date="2026-01-03T01:51:00" hour="numeric" minute="numeric" class="wa-caption-s"></wa-format-date>
</div>
</div>
<wa-tag variant="success" pill>success</wa-tag>
</article>
<wa-divider></wa-divider>
<article class="wa-flank:end wa-align-items-baseline" style="--flank-size: 10ch;">
<div class="wa-flank wa-gap-m" style="flex: 1;">
<wa-icon name="shield-check" style="color: var(--wa-color-primary);"></wa-icon>
<div class="wa-split">
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Passkey authenticated</span>
<span class="wa-caption-s" style="color: var(--wa-color-neutral-600);">WebAuthn verification</span>
</div>
<wa-format-date date="2026-01-03T01:51:00" hour="numeric" minute="numeric" class="wa-caption-s"></wa-format-date>
</div>
</div>
<wa-tag variant="neutral" pill>auth</wa-tag>
</article>
<wa-divider></wa-divider>
<article class="wa-flank:end wa-align-items-baseline" style="--flank-size: 10ch;">
<div class="wa-flank wa-gap-m" style="flex: 1;">
<wa-icon name="arrow-up" style="color: var(--wa-color-danger);"></wa-icon>
<div class="wa-split">
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Sent tokens</span>
<div class="wa-cluster wa-gap-2xs wa-caption-s" style="color: var(--wa-color-neutral-600);">
<span>To</span>
<a href="#">sonr1k4m...9p3q</a>
</div>
</div>
<wa-format-date date="2026-01-03T11:22:00" hour="numeric" minute="numeric" class="wa-caption-s"></wa-format-date>
</div>
</div>
<wa-tag variant="danger">- 500 SNR</wa-tag>
</article>
<wa-divider></wa-divider>
<article class="wa-flank:end wa-align-items-baseline" style="--flank-size: 10ch;">
<div class="wa-flank wa-gap-m" style="flex: 1;">
<wa-icon name="plug" style="color: var(--wa-color-primary);"></wa-icon>
<div class="wa-split">
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Connected app</span>
<div class="wa-cluster wa-gap-2xs wa-caption-s" style="color: var(--wa-color-neutral-600);">
<a href="#">DeFi Protocol</a>
<span>granted access</span>
</div>
</div>
<wa-format-date date="2026-01-03T10:15:00" hour="numeric" minute="numeric" class="wa-caption-s"></wa-format-date>
</div>
</div>
<wa-tag variant="brand" pill>connect</wa-tag>
</article>
</div>
</wa-details>
<wa-details>
<span class="wa-heading-m" slot="summary">Yesterday</span>
<div class="wa-stack">
<article class="wa-flank:end wa-align-items-baseline" style="--flank-size: 10ch;">
<div class="wa-flank wa-gap-m" style="flex: 1;">
<wa-icon name="arrow-down" style="color: var(--wa-color-success);"></wa-icon>
<div class="wa-split">
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Received tokens</span>
<div class="wa-cluster wa-gap-2xs wa-caption-s" style="color: var(--wa-color-neutral-600);">
<span>From</span>
<a href="#">0x7d3e...9f7a</a>
</div>
</div>
<wa-format-date date="2026-01-02T16:48:00" hour="numeric" minute="numeric" class="wa-caption-s"></wa-format-date>
</div>
</div>
<wa-tag variant="success">+ 10 AVAX</wa-tag>
</article>
<wa-divider></wa-divider>
<article class="wa-flank:end wa-align-items-baseline" style="--flank-size: 10ch;">
<div class="wa-flank wa-gap-m" style="flex: 1;">
<wa-icon name="right-to-bracket" style="color: var(--wa-color-success);"></wa-icon>
<div class="wa-split">
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Signed in</span>
<div class="wa-cluster wa-gap-2xs wa-caption-s" style="color: var(--wa-color-neutral-600);">
<a href="#">iPhone 15 Pro</a>
<span>in San Francisco, CA</span>
</div>
</div>
<wa-format-date date="2026-01-02T14:15:00" hour="numeric" minute="numeric" class="wa-caption-s"></wa-format-date>
</div>
</div>
<wa-tag variant="success" pill>success</wa-tag>
</article>
<wa-divider></wa-divider>
<article class="wa-flank:end wa-align-items-baseline" style="--flank-size: 10ch;">
<div class="wa-flank wa-gap-m" style="flex: 1;">
<wa-icon name="signature" style="color: var(--wa-color-neutral-500);"></wa-icon>
<div class="wa-split">
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Signed message</span>
<div class="wa-cluster wa-gap-2xs wa-caption-s" style="color: var(--wa-color-neutral-600);">
<span>For</span>
<a href="#">NFT Marketplace</a>
</div>
</div>
<wa-format-date date="2026-01-02T09:30:00" hour="numeric" minute="numeric" class="wa-caption-s"></wa-format-date>
</div>
</div>
<wa-tag variant="neutral" pill>sign</wa-tag>
</article>
</div>
</wa-details>
<wa-details>
<span class="wa-heading-m" slot="summary">January 1, 2026</span>
<div class="wa-stack">
<article class="wa-flank:end wa-align-items-baseline" style="--flank-size: 10ch;">
<div class="wa-flank wa-gap-m" style="flex: 1;">
<wa-icon name="arrow-right-arrow-left" style="color: var(--wa-color-primary);"></wa-icon>
<div class="wa-split">
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Swapped tokens</span>
<div class="wa-cluster wa-gap-2xs wa-caption-s" style="color: var(--wa-color-neutral-600);">
<span>0.5 ETH</span>
<wa-icon name="arrow-right" style="font-size: 10px;"></wa-icon>
<span>1,172.50 USDC</span>
</div>
</div>
<wa-format-date date="2026-01-01T09:15:00" hour="numeric" minute="numeric" class="wa-caption-s"></wa-format-date>
</div>
</div>
<wa-tag variant="brand" pill>swap</wa-tag>
</article>
<wa-divider></wa-divider>
<article class="wa-flank:end wa-align-items-baseline" style="--flank-size: 10ch;">
<div class="wa-flank wa-gap-m" style="flex: 1;">
<wa-icon name="key" style="color: var(--wa-color-warning);"></wa-icon>
<div class="wa-split">
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Added passkey</span>
<div class="wa-cluster wa-gap-2xs wa-caption-s" style="color: var(--wa-color-neutral-600);">
<span>From</span>
<a href="#">iPad Air</a>
</div>
</div>
<wa-format-date date="2026-01-01T08:00:00" hour="numeric" minute="numeric" class="wa-caption-s"></wa-format-date>
</div>
</div>
<wa-tag variant="warning" pill>security</wa-tag>
</article>
</div>
</wa-details>
</div>
<div slot="footer" class="wa-flank" style="width: 100%;">
<span class="wa-caption-s" style="color: var(--wa-color-neutral-500);">Showing last 9 activities</span>
<wa-button appearance="plain" size="small">
Load More
<wa-icon slot="end" name="chevron-down"></wa-icon>
</wa-button>
</div>
</wa-card>
</div>
</main>
</div>
</wa-page>
<script>
document.getElementById('refresh-activity').addEventListener('click', function() {
const icon = this.querySelector('wa-icon');
icon.style.animation = 'spin 0.5s linear';
setTimeout(() => icon.style.animation = '', 500);
});
document.querySelectorAll('[data-action="dismiss"]').forEach(btn => {
btn.addEventListener('click', function() {
const article = this.closest('article');
article.style.opacity = '0';
article.style.transition = 'opacity 0.3s';
setTimeout(() => {
const divider = article.nextElementSibling;
if (divider?.tagName === 'WA-DIVIDER') divider.remove();
article.remove();
}, 300);
});
});
const style = document.createElement('style');
style.textContent = '@keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }';
document.head.appendChild(style);
</script>
</body>
</html>