| class MetricsCard extends HTMLElement { |
| static get observedAttributes() { |
| return ['title', 'icon', 'value', 'change', 'color']; |
| } |
|
|
| constructor() { |
| super(); |
| this.attachShadow({ mode: 'open' }); |
| } |
|
|
| connectedCallback() { |
| this.render(); |
| } |
|
|
| attributeChangedCallback(name, oldValue, newValue) { |
| if (oldValue !== newValue) { |
| this.render(); |
| } |
| } |
|
|
| render() { |
| const title = this.getAttribute('title') || ''; |
| const icon = this.getAttribute('icon') || 'activity'; |
| const value = this.getAttribute('value') || '0'; |
| const change = parseFloat(this.getAttribute('change') || '0'); |
| const color = this.getAttribute('color') || 'primary'; |
|
|
| const changeClass = change > 0 ? 'change-positive' : change < 0 ? 'change-negative' : 'change-neutral'; |
| const changeIcon = change > 0 ? 'trending-up' : change < 0 ? 'trending-down' : 'minus'; |
| const changeText = change > 0 ? `+${change}` : change; |
|
|
| this.shadowRoot.innerHTML = ` |
| <style> |
| .card { |
| transition: all 0.3s ease; |
| } |
| .card:hover { |
| transform: translateY(-2px); |
| box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); |
| } |
| </style> |
| <div class="card bg-white dark:bg-gray-800 rounded-xl shadow p-6 hover:shadow-md transition-all duration-300"> |
| <div class="flex justify-between items-start"> |
| <div> |
| <p class="text-gray-500 dark:text-gray-400 text-sm font-medium">${title}</p> |
| <h3 class="text-2xl font-bold mt-1">${value}</h3> |
| </div> |
| <div class="w-10 h-10 rounded-lg flex items-center justify-center bg-${color}-100 dark:bg-${color}-900/30"> |
| <i data-feather="${icon}" class="text-${color}-600 dark:text-${color}-400"></i> |
| </div> |
| </div> |
| <div class="mt-4 flex items-center ${changeClass}"> |
| <i data-feather="${changeIcon}" class="w-4 h-4 mr-1"></i> |
| <span class="text-sm font-medium">${changeText}%</span> |
| <span class="text-xs ml-1 opacity-70">vs last update</span> |
| </div> |
| </div> |
| `; |
| feather.replace(); |
| } |
| } |
|
|
| customElements.define('metrics-card', MetricsCard); |