mk068's picture
https://app.uizard.io/templates/3oz60VMMKPIrngd1V6nz/overview
91cefef verified
// CryptoVista Header Component
class CustomHeader extends HTMLElement {
connectedCallback() {
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
<style>
:host {
display: block;
margin-bottom: 1.5rem;
}
.header {
display: flex;
flex-direction: column;
gap: 1rem;
}
@media (min-width: 768px) {
.header {
flex-direction: row;
align-items: center;
justify-content: space-between;
}
}
.title-section {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.welcome-text {
display: flex;
align-items: center;
gap: 0.5rem;
color: #94a3b8;
font-size: 0.875rem;
}
.welcome-icon {
width: 20px;
height: 20px;
background: linear-gradient(135deg, #0ea5e9, #d946ef);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.main-title {
font-size: 1.875rem;
font-weight: 700;
color: white;
line-height: 1.2;
position: relative;
display: inline-block;
}
.subtitle {
color: #64748b;
font-size: 0.875rem;
}
.header-stats {
display: flex;
gap: 1rem;
margin-top: 0.5rem;
flex-wrap: wrap;
}
.stat-item {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 0;
}
.stat-icon {
width: 36px;
height: 36px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
background: rgba(30, 41, 59, 0.5);
}
.stat-value {
display: flex;
flex-direction: column;
}
.stat-number {
font-size: 1.125rem;
font-weight: 600;
color: white;
}
.stat-label {
font-size: 0.75rem;
color: #94a3b8;
}
.action-buttons {
display: flex;
gap: 0.75rem;
align-items: center;
flex-wrap: wrap;
}
.btn-icon {
width: 40px;
height: 40px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
background: rgba(30, 41, 59, 0.5);
color: #94a3b8;
transition: all 0.2s ease;
cursor: pointer;
border: none;
}
.btn-icon:hover {
background: rgba(30, 41, 59, 0.8);
color: white;
transform: translateY(-2px);
}
.btn-primary {
padding: 0.625rem 1.25rem;
background: linear-gradient(135deg, #0ea5e9, #d946ef);
color: white;
border-radius: 0.75rem;
font-weight: 500;
transition: all 0.2s ease;
display: flex;
align-items: center;
gap: 0.5rem;
text-decoration: none;
cursor: pointer;
border: none;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 10px 25px rgba(14, 165, 233, 0.3);
}
.search-container {
position: relative;
width: 100%;
max-width: 400px;
}
.search-input {
width: 100%;
padding: 0.75rem 1rem 0.75rem 3rem;
background: rgba(30, 41, 59, 0.5);
border: 1px solid rgba(30, 41, 59, 0.8);
border-radius: 0.75rem;
color: white;
font-size: 0.875rem;
transition: all 0.2s ease;
}
.search-input:focus {
outline: none;
border-color: #0ea5e9;
box-shadow: 0 0 0 3px rgba(14, 165, 233, 0.1);
}
.search-icon {
position: absolute;
left: 1rem;
top: 50%;
transform: translateY(-50%);
color: #64748b;
pointer-events: none;
}
/* Glowing effect for active dashboard */
.glow-text {
position: relative;
}
.glow-text::after {
content: '';
position: absolute;
bottom: -2px;
left: 0;
width: 100%;
height: 2px;
background: linear-gradient(90deg, transparent, #0ea5e9, #d946ef, transparent);
opacity: 0.6;
animation: glow 3s ease-in-out infinite;
}
@keyframes glow {
0%, 100% { opacity: 0.3; }
50% { opacity: 0.8; }
}
/* Responsive adjustments */
@media (max-width: 767px) {
.main-title {
font-size: 1.5rem;
}
.action-buttons {
width: 100%;
}
.btn-primary {
width: 100%;
justify-content: center;
}
}
</style>
<div class="header">
<div class="title-section">
<div class="welcome-text">
<div class="welcome-icon">
<i data-feather="compass" class="w-3 h-3 text-white"></i>
</div>
<span>Welcome back, Demo User</span>
</div>
<div>
<h1 class="main-title glow-text">Trading Dashboard</h1>
<p class="subtitle">Real-time crypto market insights and portfolio tracking</p>
</div>
<div class="header-stats">
<div class="stat-item">
<div class="stat-icon">
<i data-feather="trending-up" class="w-4 h-4 text-green-400"></i>
</div>
<div class="stat-value">
<span class="stat-number">+2.34%</span>
<span class="stat-label">Today's gain</span>
</div>
</div>
<div class="stat-item">
<div class="stat-icon">
<i data-feather="dollar-sign" class="w-4 h-4 text-secondary-400"></i>
</div>
<div class="stat-value">
<span class="stat-number">$42,580</span>
<span class="stat-label">Portfolio value</span>
</div>
</div>
<div class="stat-item">
<div class="stat-icon">
<i data-feather="zap" class="w-4 h-4 text-yellow-400"></i>
</div>
<div class="stat-value">
<span class="stat-number">87ms</span>
<span class="stat-label">Avg. latency</span>
</div>
</div>
</div>
</div>
<div class="action-buttons">
<div class="search-container">
<i data-feather="search" class="search-icon w-4 h-4"></i>
<input
type="text"
class="search-input"
placeholder="Search coins, tokens..."
id="cryptoSearch"
>
<div id="searchResults" class="hidden absolute top-full left-0 right-0 mt-2 bg-dark-800 border border-dark-700 rounded-xl shadow-xl z-50"></div>
</div>
<button class="btn-icon" title="Refresh Data">
<i data-feather="refresh-cw" class="w-5 h-5"></i>
</button>
<button class="btn-icon" title="Download Report">
<i data-feather="download" class="w-5 h-5"></i>
</button>
<a href="/trade" class="btn-primary">
<i data-feather="arrow-up-right" class="w-5 h-5"></i>
Trade Now
</a>
</div>
</div>
`;
this.initializeComponent();
}
initializeComponent() {
setTimeout(() => {
this.setupEventListeners();
if (window.feather) {
window.feather.replace();
}
}, 0);
}
setupEventListeners() {
// Search functionality
const searchInput = this.shadowRoot.getElementById('cryptoSearch');
const searchResults = this.shadowRoot.getElementById('searchResults');
if (searchInput && searchResults) {
searchInput.addEventListener('input', this.handleSearch.bind(this));
// Hide results when clicking outside
document.addEventListener('click', (e) => {
if (!this.shadowRoot.contains(e.target)) {
searchResults.classList.add('hidden');
}
});
}
// Refresh button
const refreshButton = this.shadowRoot.querySelectorAll('.btn-icon')[0];
if (refreshButton) {
refreshButton.addEventListener('click', () => {
// Add loading animation
const icon = refreshButton.querySelector('i[data-feather]');
refreshButton.disabled = true;
// Dispatch refresh event
document.dispatchEvent(new CustomEvent('dashboard:refresh'));
// Re-enable after 2 seconds
setTimeout(() => {
refreshButton.disabled = false;
}, 2000);
});
}
// Download button
const downloadButton = this.shadowRoot.querySelectorAll('.btn-icon')[1];
if (downloadButton) {
downloadButton.addEventListener('click', () => {
// Simulate download
this.generateReport();