import { DeesElement, property, html, customElement, type TemplateResult, cssManager, css, unsafeCSS } from '@design.estate/dees-element'; import * as domtools from '@design.estate/dees-domtools'; import type { IOverallStatus } from '../interfaces/index.js'; import { fonts, colors } from '../styles/shared.styles.js'; import { demoFunc } from './upl-statuspage-statusbar.demo.js'; declare global { interface HTMLElementTagNameMap { 'upl-statuspage-statusbar': UplStatuspageStatusbar; } } @customElement('upl-statuspage-statusbar') export class UplStatuspageStatusbar extends DeesElement { public static demo = demoFunc; @property({ type: Object }) public overallStatus: IOverallStatus = { status: 'operational', message: 'All Systems Operational', lastUpdated: Date.now(), affectedServices: 0, totalServices: 0 }; @property({ type: Boolean }) public loading: boolean = false; @property({ type: Boolean }) public expandable: boolean = true; constructor() { super(); } public static styles = [ cssManager.defaultStyles, css` :host { padding: 0; display: block; background: transparent; font-family: ${unsafeCSS(fonts.base)}; } .statusbar-container { margin: auto; max-width: 1200px; padding: 0 24px 24px 24px; position: relative; } .statusbar-inner { display: flex; align-items: center; justify-content: space-between; min-height: 56px; padding: 16px 20px; border-radius: 6px; cursor: ${cssManager.bdTheme('default', 'default')}; transition: all 0.2s ease; position: relative; overflow: hidden; font-weight: 500; font-size: 14px; background: ${cssManager.bdTheme('#ffffff', '#0a0a0a')}; border: 1px solid ${cssManager.bdTheme('#e5e7eb', '#27272a')}; box-shadow: ${cssManager.bdTheme('0 1px 2px 0 rgba(0, 0, 0, 0.05)', 'none')}; } .statusbar-inner:hover { background: ${cssManager.bdTheme('#f9fafb', '#0f0f0f')}; } .status-indicator { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; } .statusbar-inner.operational .status-indicator { background: ${colors.status.operational}; } .statusbar-inner.degraded .status-indicator { background: ${colors.status.degraded}; } .statusbar-inner.partial_outage .status-indicator { background: ${colors.status.partial}; } .statusbar-inner.major_outage .status-indicator { background: ${colors.status.major}; } .statusbar-inner.maintenance .status-indicator { background: ${colors.status.maintenance}; } .status-content { display: flex; align-items: center; gap: 12px; flex: 1; } .status-main { display: flex; align-items: center; gap: 12px; color: ${cssManager.bdTheme('#0a0a0a', '#fafafa')}; } .status-details { font-size: 13px; color: ${cssManager.bdTheme('#6b7280', '#a1a1aa')}; } .loading-skeleton { background: ${cssManager.bdTheme('#ffffff', '#0a0a0a')}; border: 1px solid ${cssManager.bdTheme('#e5e7eb', '#27272a')}; border-radius: 6px; height: 56px; position: relative; overflow: hidden; } .loading-skeleton::after { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: ${cssManager.bdTheme( 'linear-gradient(90deg, transparent 0%, rgba(0,0,0,0.03) 50%, transparent 100%)', 'linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.03) 50%, transparent 100%)' )}; animation: loading 1.5s infinite; } @keyframes loading { 0% { transform: translateX(-100%); } 100% { transform: translateX(200%); } } .last-updated { font-size: 12px; color: ${cssManager.bdTheme('#6b7280', '#9ca3af')}; white-space: nowrap; } @media (max-width: 640px) { .statusbar-inner { font-size: 13px; padding: 12px 16px; min-height: 48px; } .status-content { gap: 10px; } .status-indicator { width: 6px; height: 6px; } .last-updated { font-size: 11px; } } `, ] public render(): TemplateResult { const formatLastUpdated = () => { const date = new Date(this.overallStatus.lastUpdated); const now = new Date(); const diff = now.getTime() - date.getTime(); const minutes = Math.floor(diff / 60000); if (minutes < 1) return 'Just now'; if (minutes < 60) return `${minutes}m ago`; const hours = Math.floor(minutes / 60); if (hours < 24) return `${hours}h ago`; return date.toLocaleDateString(); }; return html`
${this.loading ? html`
` : html`
${this.overallStatus.message} ${this.overallStatus.affectedServices > 0 ? html` ยท ${this.overallStatus.affectedServices} of ${this.overallStatus.totalServices} services affected ` : ''}
${formatLastUpdated()}
`}
`; } }