Files
nebula/_migrate/welcome.html

537 lines
17 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<!--
================================================================================
TEMPL MIGRATION GUIDE: welcome.html → views/welcome.templ
================================================================================
PAGE OVERVIEW:
- Onboarding landing page with 3-step stepper (Welcome → Learn → Get Started)
- Routes users to register.html or login.html
- Network status indicator in footer
- VIEWPORT: Optimized for popup/webview (360×540 to 480×680)
VIEWPORT CONSTRAINTS (Auth Popup/Webview):
- Target sizes: 360×540 (small), 420×600 (medium), 480×680 (large)
- Card max-width: 48ch (~384px) fits all viewport sizes
- Padding scales down on smaller viewports via media queries
- Touch targets minimum 44×44px for mobile accessibility
- Footer should remain visible without scrolling on step 1/3
- Scrollable content area for step 2 (feature list)
MAIN TEMPL COMPONENT:
templ WelcomePage() {
@layouts.CenteredCard("Welcome - Sonr Motr Wallet") {
@OnboardingStepper(1)
@WelcomeStep1()
}
}
HTMX INTEGRATION:
- Replace onclick="goToStep(N)" with hx-get="/welcome/step/N" hx-target="#step-content"
- Stepper state managed server-side via URL params or session
- Navigation buttons trigger HTMX partial updates
STATE MANAGEMENT:
- Current step passed as prop: currentStep int
- Step completion status tracked server-side
================================================================================
-->
<html lang="en" class="wa-cloak">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Welcome - 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;
}
.main-centered {
display: flex;
justify-content: center;
align-items: center;
min-height: 100%;
padding: var(--wa-space-l);
box-sizing: border-box;
}
.main-centered wa-card {
width: 100%;
max-width: 48ch;
}
.step {
display: none;
}
.step.active {
display: block;
}
.onboarding-stepper {
display: flex;
justify-content: center;
align-items: center;
gap: var(--wa-space-s);
padding: var(--wa-space-m) 0;
}
.stepper-item {
display: flex;
align-items: center;
gap: var(--wa-space-xs);
}
.stepper-number {
width: 32px;
height: 32px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: var(--wa-font-size-s);
font-weight: 600;
background: var(--wa-color-neutral-200);
color: var(--wa-color-neutral-600);
transition: all 0.3s;
}
.stepper-item.active .stepper-number {
background: var(--wa-color-primary);
color: white;
box-shadow: 0 0 0 4px var(--wa-color-primary-subtle);
}
.stepper-item.completed .stepper-number {
background: var(--wa-color-success);
color: white;
}
.stepper-label {
font-size: var(--wa-font-size-xs);
color: var(--wa-color-neutral-500);
display: none;
}
@media (min-width: 480px) {
.stepper-label {
display: block;
}
}
/* Viewport constraints for popup/webview (360-480px width) */
@media (max-width: 400px) {
.main-centered {
padding: var(--wa-space-m);
}
.main-centered wa-card {
max-width: 100%;
}
.hero-icon {
width: 64px;
height: 64px;
}
.hero-icon wa-icon {
font-size: 32px;
}
.feature-item {
padding: var(--wa-space-s);
}
.feature-icon {
width: 32px;
height: 32px;
}
.action-card {
padding: var(--wa-space-m);
}
.action-card wa-icon {
font-size: 2rem;
}
}
@media (max-height: 600px) {
.hero-icon {
width: 56px;
height: 56px;
margin-bottom: var(--wa-space-m);
}
.hero-icon wa-icon {
font-size: 28px;
}
.onboarding-stepper {
padding: var(--wa-space-s) 0;
}
}
.stepper-item.active .stepper-label {
color: var(--wa-color-primary);
font-weight: 500;
}
.stepper-line {
width: 40px;
height: 2px;
background: var(--wa-color-neutral-200);
transition: background 0.3s;
}
.stepper-line.completed {
background: var(--wa-color-success);
}
.hero-icon {
width: 80px;
height: 80px;
border-radius: var(--wa-radius-l);
background: linear-gradient(135deg, var(--wa-color-primary), #0090ff);
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto var(--wa-space-l);
box-shadow: 0 8px 32px rgba(23, 194, 255, 0.3);
}
.hero-icon wa-icon {
font-size: 40px;
color: white;
}
.feature-item {
display: flex;
align-items: flex-start;
gap: var(--wa-space-m);
padding: var(--wa-space-m);
background: var(--wa-color-surface-alt);
border-radius: var(--wa-radius-m);
}
.feature-icon {
width: 40px;
height: 40px;
border-radius: var(--wa-radius-s);
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.feature-icon.security {
background: var(--wa-color-success-subtle);
color: var(--wa-color-success);
}
.feature-icon.speed {
background: var(--wa-color-primary-subtle);
color: var(--wa-color-primary);
}
.feature-icon.privacy {
background: var(--wa-color-warning-subtle);
color: var(--wa-color-warning);
}
.action-card {
display: flex;
flex-direction: column;
align-items: center;
gap: var(--wa-space-m);
padding: var(--wa-space-xl);
background: var(--wa-color-surface-alt);
border-radius: var(--wa-radius-l);
border: 2px solid transparent;
cursor: pointer;
transition: all 0.2s;
text-align: center;
}
.action-card:hover {
border-color: var(--wa-color-primary);
background: var(--wa-color-primary-subtle);
}
.action-card wa-icon {
font-size: 2.5rem;
color: var(--wa-color-primary);
}
.network-status {
display: flex;
align-items: center;
justify-content: center;
gap: var(--wa-space-xs);
}
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--wa-color-success);
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
</style>
</head>
<body>
<wa-page>
<main class="main-centered">
<wa-card>
<div slot="header">
<div class="onboarding-stepper">
<div class="stepper-item active" data-step="1">
<div class="stepper-number">1</div>
<span class="stepper-label">Welcome</span>
</div>
<div class="stepper-line"></div>
<div class="stepper-item" data-step="2">
<div class="stepper-number">2</div>
<span class="stepper-label">Learn</span>
</div>
<div class="stepper-line"></div>
<div class="stepper-item" data-step="3">
<div class="stepper-number">3</div>
<span class="stepper-label">Get Started</span>
</div>
</div>
</div>
<div class="step active" data-step="1">
<div class="wa-stack wa-gap-l">
<div class="hero-icon">
<wa-icon name="wallet" family="duotone"></wa-icon>
</div>
<div class="wa-stack wa-gap-xs" style="text-align: center;">
<h1 class="wa-heading-xl">Welcome to Sonr</h1>
<p class="wa-caption-m" style="color: var(--wa-color-neutral-600);">
Your self-sovereign identity wallet powered by WebAssembly
</p>
</div>
<wa-divider></wa-divider>
<div class="wa-stack wa-gap-s">
<div class="feature-item">
<div class="feature-icon security">
<wa-icon name="shield-check"></wa-icon>
</div>
<div class="wa-stack wa-gap-2xs">
<span class="wa-heading-xs">Passwordless Security</span>
<span class="wa-caption-s" style="color: var(--wa-color-neutral-500);">
Authenticate with biometrics or hardware keys - no passwords to remember or steal
</span>
</div>
</div>
<div class="feature-item">
<div class="feature-icon speed">
<wa-icon name="bolt"></wa-icon>
</div>
<div class="wa-stack wa-gap-2xs">
<span class="wa-heading-xs">WASM-Powered</span>
<span class="wa-caption-s" style="color: var(--wa-color-neutral-500);">
Wallet runs entirely in your browser - fast, secure, and always available
</span>
</div>
</div>
<div class="feature-item">
<div class="feature-icon privacy">
<wa-icon name="user-shield"></wa-icon>
</div>
<div class="wa-stack wa-gap-2xs">
<span class="wa-heading-xs">You Own Your Data</span>
<span class="wa-caption-s" style="color: var(--wa-color-neutral-500);">
Self-sovereign identity means your keys never leave your device
</span>
</div>
</div>
</div>
<wa-button variant="brand" size="large" style="width: 100%;" onclick="goToStep(2)">
Learn More
<wa-icon slot="end" name="arrow-right"></wa-icon>
</wa-button>
</div>
</div>
<div class="step" data-step="2">
<div class="wa-stack wa-gap-l">
<div class="wa-stack wa-gap-xs" style="text-align: center;">
<h2 class="wa-heading-l">How Motr Works</h2>
<p class="wa-caption-m" style="color: var(--wa-color-neutral-600);">
A next-generation wallet built on WebAuthn and WASM
</p>
</div>
<wa-divider></wa-divider>
<div class="wa-stack wa-gap-m">
<wa-callout variant="neutral">
<wa-icon slot="icon" name="microchip"></wa-icon>
<div class="wa-stack wa-gap-2xs">
<span class="wa-heading-xs">WebAssembly Runtime</span>
<span class="wa-caption-s">Your wallet logic runs as compiled Go code in a secure WASM sandbox, directly in your browser.</span>
</div>
</wa-callout>
<wa-callout variant="neutral">
<wa-icon slot="icon" name="fingerprint"></wa-icon>
<div class="wa-stack wa-gap-2xs">
<span class="wa-heading-xs">Passkey Authentication</span>
<span class="wa-caption-s">Use Face ID, Touch ID, or hardware security keys. Your biometrics stay on your device.</span>
</div>
</wa-callout>
<wa-callout variant="neutral">
<wa-icon slot="icon" name="network-wired"></wa-icon>
<div class="wa-stack wa-gap-2xs">
<span class="wa-heading-xs">Decentralized Identity</span>
<span class="wa-caption-s">Connect to any app with OpenID Connect - you control what data to share.</span>
</div>
</wa-callout>
<wa-callout variant="neutral">
<wa-icon slot="icon" name="key"></wa-icon>
<div class="wa-stack wa-gap-2xs">
<span class="wa-heading-xs">Multi-Chain Support</span>
<span class="wa-caption-s">One wallet for Sonr, Ethereum, Cosmos, Bitcoin and more via IBC.</span>
</div>
</wa-callout>
</div>
<div class="wa-cluster wa-gap-s" style="justify-content: space-between;">
<wa-button variant="neutral" appearance="outlined" onclick="goToStep(1)">
<wa-icon slot="start" name="arrow-left"></wa-icon>
Back
</wa-button>
<wa-button variant="brand" onclick="goToStep(3)">
Get Started
<wa-icon slot="end" name="arrow-right"></wa-icon>
</wa-button>
</div>
</div>
</div>
<div class="step" data-step="3">
<div class="wa-stack wa-gap-l">
<div class="wa-stack wa-gap-xs" style="text-align: center;">
<h2 class="wa-heading-l">Ready to Begin?</h2>
<p class="wa-caption-m" style="color: var(--wa-color-neutral-600);">
Create a new wallet or sign in to an existing one
</p>
</div>
<wa-divider></wa-divider>
<div class="wa-grid" style="--min-column-size: 180px; gap: var(--wa-space-m);">
<div class="action-card" onclick="window.location.href='register.html'">
<wa-icon name="user-plus" family="duotone"></wa-icon>
<div class="wa-stack wa-gap-2xs">
<span class="wa-heading-m">Create Wallet</span>
<span class="wa-caption-s" style="color: var(--wa-color-neutral-500);">
New to Sonr? Set up your wallet in minutes
</span>
</div>
</div>
<div class="action-card" onclick="window.location.href='login.html'">
<wa-icon name="right-to-bracket" family="duotone"></wa-icon>
<div class="wa-stack wa-gap-2xs">
<span class="wa-heading-m">Sign In</span>
<span class="wa-caption-s" style="color: var(--wa-color-neutral-500);">
Access your existing wallet
</span>
</div>
</div>
</div>
<wa-divider>or</wa-divider>
<wa-button variant="neutral" appearance="outlined" style="width: 100%;" onclick="scanQR()">
<wa-icon slot="start" name="qrcode"></wa-icon>
Scan QR Code
</wa-button>
<wa-callout variant="brand" appearance="filled">
<wa-icon slot="icon" name="circle-info"></wa-icon>
<span class="wa-caption-s">
Already have a passkey registered on another device? Use QR code to sync your wallet.
</span>
</wa-callout>
<wa-button variant="neutral" appearance="plain" onclick="goToStep(2)" style="width: 100%;">
<wa-icon slot="start" name="arrow-left"></wa-icon>
Back to How It Works
</wa-button>
</div>
</div>
<footer slot="footer">
<div class="wa-stack wa-gap-m wa-align-items-center">
<div class="network-status">
<div class="status-dot"></div>
<span class="wa-caption-s" style="color: var(--wa-color-neutral-600);">
Sonr Network: <strong style="color: var(--wa-color-success);">Operational</strong>
</span>
</div>
<div class="wa-cluster wa-justify-content-center wa-gap-m">
<wa-button appearance="plain" size="small" onclick="window.open('https://sonr.io', '_blank')">
Learn about Sonr
</wa-button>
<span style="color: var(--wa-color-neutral-300);">|</span>
<wa-button appearance="plain" size="small" onclick="window.open('https://docs.sonr.io', '_blank')">
Documentation
</wa-button>
</div>
</div>
</footer>
</wa-card>
</main>
</wa-page>
<script>
let currentStep = 1;
function goToStep(step) {
document.querySelectorAll('.step').forEach(el => el.classList.remove('active'));
document.querySelectorAll('.stepper-item').forEach(item => {
const itemStep = parseInt(item.dataset.step);
item.classList.remove('active', 'completed');
if (itemStep < step) {
item.classList.add('completed');
} else if (itemStep === step) {
item.classList.add('active');
}
});
document.querySelectorAll('.stepper-line').forEach((line, index) => {
line.classList.toggle('completed', index < step - 1);
});
const targetStep = document.querySelector(`.step[data-step="${step}"]`);
if (targetStep) {
targetStep.classList.add('active');
}
currentStep = step;
}
function scanQR() {
alert('QR Scanner would open here - scan a code from another device to sync your wallet.');
}
</script>
</body>
</html>