@uptime.link/statuspage 1.0.74 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/dist_bundle/bundle.js +5019 -519
  2. package/dist_bundle/bundle.js.map +4 -4
  3. package/dist_ts_web/00_commitinfo_data.js +2 -2
  4. package/dist_ts_web/elements/index.d.ts +3 -0
  5. package/dist_ts_web/elements/index.js +6 -1
  6. package/dist_ts_web/elements/internal/uplinternal-miniheading.d.ts +1 -0
  7. package/dist_ts_web/elements/internal/uplinternal-miniheading.js +78 -28
  8. package/dist_ts_web/elements/upl-statuspage-assetsselector.d.ts +14 -0
  9. package/dist_ts_web/elements/upl-statuspage-assetsselector.demo.d.ts +1 -0
  10. package/dist_ts_web/elements/upl-statuspage-assetsselector.demo.js +575 -0
  11. package/dist_ts_web/elements/upl-statuspage-assetsselector.js +679 -43
  12. package/dist_ts_web/elements/upl-statuspage-footer.d.ts +46 -2
  13. package/dist_ts_web/elements/upl-statuspage-footer.demo.d.ts +1 -0
  14. package/dist_ts_web/elements/upl-statuspage-footer.demo.js +679 -0
  15. package/dist_ts_web/elements/upl-statuspage-footer.js +846 -61
  16. package/dist_ts_web/elements/upl-statuspage-header.d.ts +5 -1
  17. package/dist_ts_web/elements/upl-statuspage-header.demo.d.ts +1 -0
  18. package/dist_ts_web/elements/upl-statuspage-header.demo.js +220 -0
  19. package/dist_ts_web/elements/upl-statuspage-header.js +373 -86
  20. package/dist_ts_web/elements/upl-statuspage-incidents.d.ts +22 -4
  21. package/dist_ts_web/elements/upl-statuspage-incidents.demo.d.ts +1 -0
  22. package/dist_ts_web/elements/upl-statuspage-incidents.demo.js +1147 -0
  23. package/dist_ts_web/elements/upl-statuspage-incidents.js +937 -74
  24. package/dist_ts_web/elements/upl-statuspage-pagetitle.d.ts +15 -0
  25. package/dist_ts_web/elements/upl-statuspage-pagetitle.demo.d.ts +1 -0
  26. package/dist_ts_web/elements/upl-statuspage-pagetitle.demo.js +25 -0
  27. package/dist_ts_web/elements/upl-statuspage-pagetitle.js +148 -0
  28. package/dist_ts_web/elements/upl-statuspage-statsgrid.d.ts +23 -0
  29. package/dist_ts_web/elements/upl-statuspage-statsgrid.demo.d.ts +1 -0
  30. package/dist_ts_web/elements/upl-statuspage-statsgrid.demo.js +295 -0
  31. package/dist_ts_web/elements/upl-statuspage-statsgrid.js +549 -0
  32. package/dist_ts_web/elements/upl-statuspage-statusbar.d.ts +4 -0
  33. package/dist_ts_web/elements/upl-statuspage-statusbar.demo.d.ts +1 -0
  34. package/dist_ts_web/elements/upl-statuspage-statusbar.demo.js +365 -0
  35. package/dist_ts_web/elements/upl-statuspage-statusbar.js +408 -44
  36. package/dist_ts_web/elements/upl-statuspage-statusdetails.d.ts +14 -0
  37. package/dist_ts_web/elements/upl-statuspage-statusdetails.demo.d.ts +1 -0
  38. package/dist_ts_web/elements/upl-statuspage-statusdetails.demo.js +706 -0
  39. package/dist_ts_web/elements/upl-statuspage-statusdetails.js +397 -62
  40. package/dist_ts_web/elements/upl-statuspage-statusmonth.d.ts +17 -0
  41. package/dist_ts_web/elements/upl-statuspage-statusmonth.demo.d.ts +1 -0
  42. package/dist_ts_web/elements/upl-statuspage-statusmonth.demo.js +798 -0
  43. package/dist_ts_web/elements/upl-statuspage-statusmonth.js +662 -103
  44. package/dist_ts_web/interfaces/index.d.ts +84 -0
  45. package/dist_ts_web/interfaces/index.js +4 -0
  46. package/dist_ts_web/pages/index.d.ts +4 -1
  47. package/dist_ts_web/pages/index.js +5 -2
  48. package/dist_ts_web/pages/statuspage-allgreen.d.ts +1 -0
  49. package/dist_ts_web/pages/statuspage-allgreen.js +386 -0
  50. package/dist_ts_web/pages/statuspage-demo.d.ts +1 -0
  51. package/dist_ts_web/pages/statuspage-demo.js +616 -0
  52. package/dist_ts_web/pages/statuspage-maintenance.d.ts +1 -0
  53. package/dist_ts_web/pages/statuspage-maintenance.js +544 -0
  54. package/dist_ts_web/pages/statuspage-outage.d.ts +1 -0
  55. package/dist_ts_web/pages/statuspage-outage.js +543 -0
  56. package/dist_ts_web/styles/shared.styles.d.ts +102 -0
  57. package/dist_ts_web/styles/shared.styles.js +494 -0
  58. package/dist_watch/bundle.js +52265 -32033
  59. package/dist_watch/bundle.js.map +4 -4
  60. package/dist_watch/index.html +1 -0
  61. package/npmextra.json +9 -3
  62. package/package.json +19 -19
  63. package/readme.hints.md +292 -0
  64. package/readme.md +326 -149
  65. package/readme.plan.md +261 -0
  66. package/ts_web/00_commitinfo_data.ts +1 -1
  67. package/ts_web/elements/index.ts +6 -0
  68. package/ts_web/elements/internal/uplinternal-miniheading.ts +24 -17
  69. package/ts_web/elements/upl-statuspage-assetsselector.demo.ts +607 -0
  70. package/ts_web/elements/upl-statuspage-assetsselector.ts +600 -18
  71. package/ts_web/elements/upl-statuspage-footer.demo.ts +744 -0
  72. package/ts_web/elements/upl-statuspage-footer.ts +662 -30
  73. package/ts_web/elements/upl-statuspage-header.demo.ts +241 -0
  74. package/ts_web/elements/upl-statuspage-header.ts +289 -52
  75. package/ts_web/elements/upl-statuspage-incidents.demo.ts +1216 -0
  76. package/ts_web/elements/upl-statuspage-incidents.ts +840 -26
  77. package/ts_web/elements/upl-statuspage-pagetitle.demo.ts +25 -0
  78. package/ts_web/elements/upl-statuspage-pagetitle.ts +89 -0
  79. package/ts_web/elements/upl-statuspage-statsgrid.demo.ts +315 -0
  80. package/ts_web/elements/upl-statuspage-statsgrid.ts +478 -0
  81. package/ts_web/elements/upl-statuspage-statusbar.demo.ts +393 -0
  82. package/ts_web/elements/upl-statuspage-statusbar.ts +332 -20
  83. package/ts_web/elements/upl-statuspage-statusdetails.demo.ts +754 -0
  84. package/ts_web/elements/upl-statuspage-statusdetails.ts +321 -37
  85. package/ts_web/elements/upl-statuspage-statusmonth.demo.ts +876 -0
  86. package/ts_web/elements/upl-statuspage-statusmonth.ts +584 -79
  87. package/ts_web/interfaces/index.ts +95 -0
  88. package/ts_web/pages/index.ts +4 -1
  89. package/ts_web/pages/statuspage-allgreen.ts +412 -0
  90. package/ts_web/pages/statuspage-demo.ts +653 -0
  91. package/ts_web/pages/statuspage-maintenance.ts +570 -0
  92. package/ts_web/pages/statuspage-outage.ts +568 -0
  93. package/ts_web/styles/shared.styles.ts +531 -0
  94. package/dist_ts_web/pages/page1.d.ts +0 -1
  95. package/dist_ts_web/pages/page1.js +0 -11
  96. package/ts_web/pages/page1.ts +0 -11
@@ -0,0 +1,241 @@
1
+ import { html } from '@design.estate/dees-element';
2
+
3
+ export const demoFunc = () => html`
4
+ <style>
5
+ .demo-container {
6
+ display: flex;
7
+ flex-direction: column;
8
+ gap: 20px;
9
+ }
10
+ .demo-section {
11
+ border: 1px solid #ddd;
12
+ border-radius: 8px;
13
+ padding: 20px;
14
+ background: #f5f5f5;
15
+ }
16
+ .demo-title {
17
+ font-size: 14px;
18
+ font-weight: 600;
19
+ margin-bottom: 16px;
20
+ color: #333;
21
+ }
22
+ .demo-controls {
23
+ display: flex;
24
+ gap: 10px;
25
+ margin-top: 16px;
26
+ flex-wrap: wrap;
27
+ }
28
+ .demo-button {
29
+ padding: 6px 12px;
30
+ border: 1px solid #ddd;
31
+ background: white;
32
+ border-radius: 4px;
33
+ cursor: pointer;
34
+ font-size: 13px;
35
+ }
36
+ .demo-button:hover {
37
+ background: #f0f0f0;
38
+ }
39
+ </style>
40
+
41
+ <div class="demo-container">
42
+ <!-- Basic Header -->
43
+ <div class="demo-section">
44
+ <div class="demo-title">Basic Header with Dynamic Title</div>
45
+ <dees-demowrapper
46
+ .runAfterRender=${async (wrapperElement: any) => {
47
+ const header = wrapperElement.querySelector('upl-statuspage-header') as any;
48
+
49
+ // Demo different titles
50
+ const titles = [
51
+ 'MyService Status Page',
52
+ 'Production Environment Status',
53
+ 'API Health Dashboard',
54
+ 'Global Infrastructure Status',
55
+ '🚀 Rocket Systems Monitor',
56
+ 'Multi-Region Service Status'
57
+ ];
58
+
59
+ let titleIndex = 0;
60
+ header.pageTitle = titles[titleIndex];
61
+
62
+ // Add event listeners
63
+ header.addEventListener('reportNewIncident', (event: CustomEvent) => {
64
+ console.log('Report incident clicked');
65
+ alert('Report Incident form would open here');
66
+ });
67
+
68
+ header.addEventListener('statusSubscribe', (event: CustomEvent) => {
69
+ console.log('Subscribe clicked');
70
+ alert('Subscribe modal would open here');
71
+ });
72
+
73
+ // Cycle through titles
74
+ setInterval(() => {
75
+ titleIndex = (titleIndex + 1) % titles.length;
76
+ header.pageTitle = titles[titleIndex];
77
+ }, 2000);
78
+ }}
79
+ >
80
+ <upl-statuspage-header></upl-statuspage-header>
81
+ </dees-demowrapper>
82
+ </div>
83
+
84
+ <!-- Header with Hidden Buttons -->
85
+ <div class="demo-section">
86
+ <div class="demo-title">Header with Configurable Buttons</div>
87
+ <dees-demowrapper
88
+ .runAfterRender=${async (wrapperElement: any) => {
89
+ const header = wrapperElement.querySelector('upl-statuspage-header') as any;
90
+ header.pageTitle = 'Configurable Button States';
91
+
92
+ // Add properties to control button visibility
93
+ header.showReportButton = true;
94
+ header.showSubscribeButton = true;
95
+
96
+ const controls = document.createElement('div');
97
+ controls.className = 'demo-controls';
98
+ controls.innerHTML = `
99
+ <button class="demo-button" id="toggleReport">Toggle Report Button</button>
100
+ <button class="demo-button" id="toggleSubscribe">Toggle Subscribe Button</button>
101
+ <button class="demo-button" id="toggleBoth">Hide Both</button>
102
+ <button class="demo-button" id="showBoth">Show Both</button>
103
+ `;
104
+ wrapperElement.appendChild(controls);
105
+
106
+ controls.querySelector('#toggleReport')?.addEventListener('click', () => {
107
+ header.showReportButton = !header.showReportButton;
108
+ });
109
+
110
+ controls.querySelector('#toggleSubscribe')?.addEventListener('click', () => {
111
+ header.showSubscribeButton = !header.showSubscribeButton;
112
+ });
113
+
114
+ controls.querySelector('#toggleBoth')?.addEventListener('click', () => {
115
+ header.showReportButton = false;
116
+ header.showSubscribeButton = false;
117
+ });
118
+
119
+ controls.querySelector('#showBoth')?.addEventListener('click', () => {
120
+ header.showReportButton = true;
121
+ header.showSubscribeButton = true;
122
+ });
123
+ }}
124
+ >
125
+ <upl-statuspage-header></upl-statuspage-header>
126
+ </dees-demowrapper>
127
+ </div>
128
+
129
+ <!-- Header with Custom Styling -->
130
+ <div class="demo-section">
131
+ <div class="demo-title">Header with Custom Branding</div>
132
+ <dees-demowrapper
133
+ .runAfterRender=${async (wrapperElement: any) => {
134
+ const header = wrapperElement.querySelector('upl-statuspage-header') as any;
135
+ header.pageTitle = 'Enterprise Cloud Platform';
136
+
137
+ // Custom branding properties
138
+ header.brandColor = '#1976D2';
139
+ header.logoUrl = 'https://via.placeholder.com/120x40/1976D2/ffffff?text=LOGO';
140
+ header.customStyles = true;
141
+
142
+ // Simulate different brand states
143
+ const brands = [
144
+ { title: 'Enterprise Cloud Platform', color: '#1976D2', logo: 'ENTERPRISE' },
145
+ { title: 'StartUp SaaS Monitor', color: '#00BCD4', logo: 'STARTUP' },
146
+ { title: 'Government Services Status', color: '#4CAF50', logo: 'GOV' },
147
+ { title: 'Financial Systems Health', color: '#673AB7', logo: 'FINTECH' }
148
+ ];
149
+
150
+ let brandIndex = 0;
151
+ setInterval(() => {
152
+ brandIndex = (brandIndex + 1) % brands.length;
153
+ const brand = brands[brandIndex];
154
+ header.pageTitle = brand.title;
155
+ header.brandColor = brand.color;
156
+ header.logoUrl = `https://via.placeholder.com/120x40/${brand.color.slice(1)}/ffffff?text=${brand.logo}`;
157
+ }, 3000);
158
+ }}
159
+ >
160
+ <upl-statuspage-header></upl-statuspage-header>
161
+ </dees-demowrapper>
162
+ </div>
163
+
164
+ <!-- Header with Loading State -->
165
+ <div class="demo-section">
166
+ <div class="demo-title">Header with Loading States</div>
167
+ <dees-demowrapper
168
+ .runAfterRender=${async (wrapperElement: any) => {
169
+ const header = wrapperElement.querySelector('upl-statuspage-header') as any;
170
+ header.pageTitle = 'Loading State Demo';
171
+ header.loading = true;
172
+
173
+ // Simulate loading completion
174
+ setTimeout(() => {
175
+ header.loading = false;
176
+ header.pageTitle = 'Status Page Loaded';
177
+ }, 2000);
178
+
179
+ // Add loading toggle
180
+ const controls = document.createElement('div');
181
+ controls.className = 'demo-controls';
182
+ controls.innerHTML = `
183
+ <button class="demo-button" id="toggleLoading">Toggle Loading State</button>
184
+ `;
185
+ wrapperElement.appendChild(controls);
186
+
187
+ controls.querySelector('#toggleLoading')?.addEventListener('click', () => {
188
+ header.loading = !header.loading;
189
+ if (header.loading) {
190
+ header.pageTitle = 'Loading...';
191
+ setTimeout(() => {
192
+ header.loading = false;
193
+ header.pageTitle = 'Status Page Ready';
194
+ }, 2000);
195
+ }
196
+ });
197
+ }}
198
+ >
199
+ <upl-statuspage-header></upl-statuspage-header>
200
+ </dees-demowrapper>
201
+ </div>
202
+
203
+ <!-- Header with Event Counter -->
204
+ <div class="demo-section">
205
+ <div class="demo-title">Header with Event Tracking</div>
206
+ <dees-demowrapper
207
+ .runAfterRender=${async (wrapperElement: any) => {
208
+ const header = wrapperElement.querySelector('upl-statuspage-header') as any;
209
+ header.pageTitle = 'Event Tracking Demo';
210
+
211
+ let reportCount = 0;
212
+ let subscribeCount = 0;
213
+
214
+ // Create counter display
215
+ const counterDisplay = document.createElement('div');
216
+ counterDisplay.style.marginTop = '16px';
217
+ counterDisplay.style.fontSize = '14px';
218
+ counterDisplay.innerHTML = `
219
+ <div>Report Clicks: <strong id="reportCount">0</strong></div>
220
+ <div>Subscribe Clicks: <strong id="subscribeCount">0</strong></div>
221
+ `;
222
+ wrapperElement.appendChild(counterDisplay);
223
+
224
+ header.addEventListener('reportNewIncident', () => {
225
+ reportCount++;
226
+ counterDisplay.querySelector('#reportCount').textContent = reportCount.toString();
227
+ console.log(`Report incident clicked ${reportCount} times`);
228
+ });
229
+
230
+ header.addEventListener('statusSubscribe', () => {
231
+ subscribeCount++;
232
+ counterDisplay.querySelector('#subscribeCount').textContent = subscribeCount.toString();
233
+ console.log(`Subscribe clicked ${subscribeCount} times`);
234
+ });
235
+ }}
236
+ >
237
+ <upl-statuspage-header></upl-statuspage-header>
238
+ </dees-demowrapper>
239
+ </div>
240
+ </div>
241
+ `;
@@ -1,5 +1,7 @@
1
- import { DeesElement, property, html, customElement, type TemplateResult, css, cssManager } from '@design.estate/dees-element';
1
+ import { DeesElement, property, html, customElement, type TemplateResult, css, cssManager, unsafeCSS } from '@design.estate/dees-element';
2
2
  import * as domtools from '@design.estate/dees-domtools';
3
+ import * as sharedStyles from '../styles/shared.styles.js';
4
+ import { demoFunc } from './upl-statuspage-header.demo.js';
3
5
 
4
6
  declare global {
5
7
  interface HTMLElementTagNameMap {
@@ -10,13 +12,23 @@ declare global {
10
12
  @customElement('upl-statuspage-header')
11
13
  export class UplStatuspageHeader extends DeesElement {
12
14
  // STATIC
13
- public static demo = () => html`
14
- <upl-statuspage-header></upl-statuspage-header>
15
- `;
15
+ public static demo = demoFunc;
16
16
 
17
17
  // INSTANCE
18
- @property()
19
- public pageTitle: string = "Statuspage Title";
18
+ @property({ type: String })
19
+ accessor pageTitle: string = "Statuspage Title";
20
+
21
+ @property({ type: Boolean })
22
+ accessor showReportButton: boolean = true;
23
+
24
+ @property({ type: Boolean })
25
+ accessor showSubscribeButton: boolean = true;
26
+
27
+ @property({ type: String })
28
+ accessor logoUrl: string = '';
29
+
30
+ @property({ type: Boolean })
31
+ accessor loading: boolean = false;
20
32
 
21
33
 
22
34
  constructor() {
@@ -27,72 +39,297 @@ export class UplStatuspageHeader extends DeesElement {
27
39
  domtools.elementBasic.staticStyles,
28
40
  css`
29
41
  :host {
30
- display: block;
31
- background: ${cssManager.bdTheme('#eeeeeb', '#222222')};
32
- font-family: Inter;
33
- color: ${cssManager.bdTheme('#333333', '#ffffff')};
42
+ display: block;
43
+ background: ${cssManager.bdTheme(
44
+ 'rgba(255, 255, 255, 0.85)',
45
+ 'rgba(9, 9, 11, 0.85)'
46
+ )};
47
+ font-family: ${unsafeCSS(sharedStyles.fonts.base)};
48
+ color: ${sharedStyles.colors.text.primary};
49
+ border-bottom: 1px solid ${cssManager.bdTheme(
50
+ 'rgba(0, 0, 0, 0.06)',
51
+ 'rgba(255, 255, 255, 0.06)'
52
+ )};
53
+ position: sticky;
54
+ top: 0;
55
+ z-index: 40;
56
+ backdrop-filter: blur(16px) saturate(180%);
57
+ -webkit-backdrop-filter: blur(16px) saturate(180%);
58
+ }
59
+
60
+ .header-container {
61
+ max-width: 1200px;
62
+ margin: 0 auto;
63
+ padding: 0 ${unsafeCSS(sharedStyles.spacing.lg)};
64
+ }
65
+
66
+ .header-nav {
67
+ display: flex;
68
+ align-items: center;
69
+ justify-content: space-between;
70
+ height: 64px;
71
+ }
72
+
73
+ .header-left {
74
+ display: flex;
75
+ align-items: center;
76
+ gap: ${unsafeCSS(sharedStyles.spacing.md)};
77
+ }
78
+
79
+ .header-actions {
80
+ display: flex;
81
+ align-items: center;
82
+ gap: ${unsafeCSS(sharedStyles.spacing.sm)};
83
+ }
84
+
85
+ .actionButton {
86
+ font-family: ${unsafeCSS(sharedStyles.fonts.base)};
87
+ font-size: 13px;
88
+ font-weight: 500;
89
+ padding: 0 14px;
90
+ border-radius: ${unsafeCSS(sharedStyles.borderRadius.base)};
91
+ cursor: pointer;
92
+ user-select: none;
93
+ transition: all ${unsafeCSS(sharedStyles.durations.fast)} ${unsafeCSS(sharedStyles.easings.default)};
94
+ display: inline-flex;
95
+ align-items: center;
96
+ justify-content: center;
97
+ gap: 6px;
98
+ height: 36px;
99
+ background: transparent;
100
+ border: 1px solid ${sharedStyles.colors.border.default};
101
+ color: ${sharedStyles.colors.text.primary};
102
+ letter-spacing: -0.01em;
103
+ position: relative;
104
+ overflow: hidden;
105
+ }
106
+
107
+ .actionButton::before {
108
+ content: '';
109
+ position: absolute;
110
+ inset: 0;
111
+ background: ${cssManager.bdTheme(
112
+ 'linear-gradient(135deg, rgba(0, 0, 0, 0.02) 0%, transparent 100%)',
113
+ 'linear-gradient(135deg, rgba(255, 255, 255, 0.03) 0%, transparent 100%)'
114
+ )};
115
+ opacity: 0;
116
+ transition: opacity ${unsafeCSS(sharedStyles.durations.fast)} ${unsafeCSS(sharedStyles.easings.default)};
117
+ }
118
+
119
+ .actionButton:hover {
120
+ background: ${sharedStyles.colors.background.secondary};
121
+ border-color: ${sharedStyles.colors.border.muted};
122
+ box-shadow: ${unsafeCSS(sharedStyles.shadows.sm)};
123
+ transform: translateY(-1px);
124
+ }
125
+
126
+ .actionButton:hover::before {
127
+ opacity: 1;
128
+ }
129
+
130
+ .actionButton:active {
131
+ transform: translateY(0) scale(0.98);
132
+ transition-duration: ${unsafeCSS(sharedStyles.durations.fast)};
133
+ box-shadow: none;
134
+ }
135
+
136
+ .actionButton:focus-visible {
137
+ outline: 2px solid ${sharedStyles.colors.accent.focus};
138
+ outline-offset: 2px;
139
+ }
140
+
141
+ /* Button icon styles */
142
+ .actionButton svg {
143
+ width: 14px;
144
+ height: 14px;
145
+ flex-shrink: 0;
146
+ transition: transform ${unsafeCSS(sharedStyles.durations.fast)} ${unsafeCSS(sharedStyles.easings.default)};
147
+ }
148
+
149
+ .actionButton:hover svg {
150
+ transform: scale(1.1);
151
+ }
152
+
153
+ .site-title {
154
+ font-size: 17px;
155
+ font-weight: 600;
156
+ letter-spacing: -0.02em;
157
+ color: ${sharedStyles.colors.text.primary};
158
+ transition: color ${unsafeCSS(sharedStyles.durations.fast)} ${unsafeCSS(sharedStyles.easings.default)};
159
+ }
160
+
161
+ .site-title:hover {
162
+ color: ${sharedStyles.colors.text.secondary};
163
+ }
164
+
165
+ .logo {
166
+ height: 28px;
167
+ width: auto;
168
+ filter: ${cssManager.bdTheme('none', 'brightness(0) invert(1)')};
169
+ transition: all ${unsafeCSS(sharedStyles.durations.normal)} ${unsafeCSS(sharedStyles.easings.default)};
170
+ }
171
+
172
+ .logo:hover {
173
+ opacity: 0.8;
174
+ transform: scale(1.02);
175
+ }
176
+
177
+ .page-info {
178
+ padding: ${unsafeCSS(sharedStyles.spacing.lg)} 0 ${unsafeCSS(sharedStyles.spacing.xl)} 0;
179
+ }
180
+
181
+ .page-title {
182
+ font-size: 48px;
183
+ font-weight: 700;
184
+ letter-spacing: -0.03em;
185
+ line-height: 1.1;
186
+ color: ${sharedStyles.colors.text.primary};
187
+ margin: 0 0 16px 0;
188
+ }
189
+
190
+ .page-subtitle {
191
+ font-size: 18px;
192
+ color: ${sharedStyles.colors.text.secondary};
193
+ margin: 0;
194
+ line-height: 1.5;
195
+ }
196
+
197
+ /* Primary button variant */
198
+ .actionButton.primary {
199
+ background: ${sharedStyles.colors.accent.primary};
200
+ color: ${sharedStyles.colors.background.primary};
201
+ border-color: transparent;
202
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
203
+ }
204
+
205
+ .actionButton.primary::before {
206
+ background: linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, transparent 100%);
207
+ }
208
+
209
+ .actionButton.primary:hover {
210
+ background: ${sharedStyles.colors.accent.hover};
211
+ box-shadow: ${unsafeCSS(sharedStyles.shadows.md)};
212
+ }
213
+
214
+ .loading-skeleton {
215
+ height: 64px;
216
+ background: ${sharedStyles.colors.background.secondary};
217
+ border-bottom: 1px solid ${sharedStyles.colors.border.default};
218
+ position: relative;
219
+ overflow: hidden;
220
+ }
221
+
222
+ .loading-skeleton::after {
223
+ content: '';
224
+ position: absolute;
225
+ inset: 0;
226
+ background: ${cssManager.bdTheme(
227
+ 'linear-gradient(90deg, transparent 0%, rgba(0,0,0,0.04) 50%, transparent 100%)',
228
+ 'linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.04) 50%, transparent 100%)'
229
+ )};
230
+ animation: shimmer 1.5s ${unsafeCSS(sharedStyles.easings.default)} infinite;
231
+ }
232
+
233
+ @keyframes shimmer {
234
+ 0% { transform: translateX(-100%); }
235
+ 100% { transform: translateX(200%); }
236
+ }
237
+
238
+ @media (max-width: 768px) {
239
+ .header-container {
240
+ padding: 0 ${unsafeCSS(sharedStyles.spacing.md)};
34
241
  }
35
242
 
36
- .mainbox {
37
- margin: auto;
38
- max-width: 900px;
243
+ .header-nav {
244
+ height: 56px;
39
245
  }
40
246
 
41
- .mainbox .actions {
42
- display: flex;
43
- justify-content: flex-end;
44
- padding: 20px 0px 40px 0px;
247
+ .header-left {
248
+ gap: ${unsafeCSS(sharedStyles.spacing.sm)};
45
249
  }
46
250
 
47
- .mainbox .actions .actionButton {
48
- background: ${cssManager.bdTheme('#00000000', '#ffffff00')};
49
-
251
+ .site-title {
252
+ font-size: 15px;
253
+ }
254
+
255
+ .logo {
256
+ height: 24px;
257
+ }
258
+ }
259
+
260
+ @media (max-width: 640px) {
261
+ .actionButton {
50
262
  font-size: 12px;
51
- border: 1px solid ${cssManager.bdTheme('#333', '#CCC')};
52
- padding: 6px 10px 7px 10px;
53
- margin-left: 10px;
54
- border-radius: 3px;
55
- cursor: pointer;
56
- user-select: none;
263
+ padding: 0 10px;
264
+ height: 32px;
265
+ gap: 4px;
57
266
  }
58
267
 
59
- .mainbox .actions .actionButton:hover {
60
- background: ${cssManager.bdTheme('#333333', '#efefef')};
61
- border: 1px solid ${cssManager.bdTheme('#333333', '#efefef')};
62
- color: ${cssManager.bdTheme('#fff', '#333333')};
268
+ .actionButton svg {
269
+ width: 12px;
270
+ height: 12px;
63
271
  }
64
272
 
65
- h1 {
66
- margin: 0px;
67
- text-align: center;
68
- font-weight: 600;
69
- font-size: 35px;
273
+ .actionButton .button-text {
274
+ display: none;
70
275
  }
71
276
 
72
- h2 {
73
- margin: 0px;
74
- margin-top: 10px;
75
- text-align: center;
76
- font-weight: 600;
77
- font-size: 18px;
277
+ .page-title {
278
+ font-size: 32px;
78
279
  }
280
+
281
+ .page-subtitle {
282
+ font-size: 16px;
283
+ }
284
+
285
+ .header-actions {
286
+ gap: 6px;
287
+ }
288
+ }
79
289
  `
80
290
  ]
81
291
 
82
292
  public render(): TemplateResult {
293
+ if (this.loading) {
294
+ return html`
295
+ <div class="loading-skeleton"></div>
296
+ `;
297
+ }
298
+
83
299
  return html`
84
- ${domtools.elementBasic.styles}
85
- <style>
86
-
87
- </style>
88
- <div class="mainbox">
89
- <div class="actions">
90
- <div class="actionButton" @click=${this.dispatchReportNewIncident}>report new incident</div>
91
- <div class="actionButton" @click=${this.dispatchStatusSubscribe}>subscribe</div>
300
+ <header>
301
+ <div class="header-container">
302
+ <nav class="header-nav">
303
+ <div class="header-left">
304
+ ${this.logoUrl ? html`
305
+ <img src="${this.logoUrl}" alt="${this.pageTitle}" class="logo">
306
+ ` : ''}
307
+ <h1 class="site-title">${this.pageTitle}</h1>
308
+ </div>
309
+ <div class="header-actions">
310
+ ${this.showReportButton ? html`
311
+ <button class="actionButton" @click=${this.dispatchReportNewIncident}>
312
+ <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
313
+ <path d="M7.86 2h8.28L22 7.86v8.28L16.14 22H7.86L2 16.14V7.86L7.86 2z"></path>
314
+ <line x1="12" y1="8" x2="12" y2="12"></line>
315
+ <line x1="12" y1="16" x2="12.01" y2="16"></line>
316
+ </svg>
317
+ <span class="button-text">Report Issue</span>
318
+ </button>
319
+ ` : ''}
320
+ ${this.showSubscribeButton ? html`
321
+ <button class="actionButton primary" @click=${this.dispatchStatusSubscribe}>
322
+ <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
323
+ <path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"></path>
324
+ <path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"></path>
325
+ </svg>
326
+ <span class="button-text">Subscribe</span>
327
+ </button>
328
+ ` : ''}
329
+ </div>
330
+ </nav>
92
331
  </div>
93
- <h1>${this.pageTitle}</h1>
94
- <h2>STATUS BOARD</h2>
95
- </div>
332
+ </header>
96
333
  `;
97
334
  }
98
335