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: center; min-height: 64px; padding: 16px 24px; border-radius: 8px; cursor: pointer; transition: all 0.2s ease; position: relative; overflow: hidden; font-weight: 500; font-size: 16px; border: 1px solid transparent; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.06); } .statusbar-inner:hover { transform: translateY(-1px); box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.06); } .statusbar-inner:active { transform: translateY(0); } .statusbar-inner.operational { background: ${colors.status.operational}; border-color: ${colors.status.operational}; color: white; } .statusbar-inner.degraded { background: ${colors.status.degraded}; border-color: ${colors.status.degraded}; color: white; } .statusbar-inner.partial_outage { background: ${colors.status.partial}; border-color: ${colors.status.partial}; color: white; } .statusbar-inner.major_outage { background: ${colors.status.major}; border-color: ${colors.status.major}; color: white; } .statusbar-inner.maintenance { background: ${colors.status.maintenance}; border-color: ${colors.status.maintenance}; color: white; } .status-content { display: flex; flex-direction: column; align-items: center; gap: 4px; } .status-main { display: flex; align-items: center; gap: 8px; } .status-icon { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; font-size: 14px; } .loading-skeleton { background: ${cssManager.bdTheme( 'linear-gradient(90deg, #f3f4f6 25%, #e5e7eb 50%, #f3f4f6 75%)', 'linear-gradient(90deg, #1f1f1f 25%, #262626 50%, #1f1f1f 75%)' )}; background-size: 200% 100%; animation: loading 1.5s infinite; height: 64px; border-radius: 8px; } @keyframes loading { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } } .status-details { font-size: 14px; opacity: 0.9; } .last-updated { font-size: 13px; text-align: right; margin-top: 12px; color: ${cssManager.bdTheme('#6b7280', '#9ca3af')}; } @media (max-width: 640px) { .statusbar-inner { font-size: 14px; padding: 12px 16px; min-height: 56px; } .status-icon { width: 18px; height: 18px; font-size: 12px; } } `, ] public render(): TemplateResult { const getStatusIcon = () => { switch (this.overallStatus.status) { case 'operational': return '✓'; case 'degraded': return '!'; case 'partial_outage': return '⚠'; case 'major_outage': return '✕'; case 'maintenance': return '🔧'; default: return ''; } }; const formatLastUpdated = () => { const date = new Date(this.overallStatus.lastUpdated); return date.toLocaleString(); }; const handleClick = () => { if (this.expandable) { this.dispatchEvent(new CustomEvent('statusClick', { detail: { status: this.overallStatus }, bubbles: true, composed: true })); } }; return html`
`; } }