@uptime.link/statuspage 1.1.0 → 1.3.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 (29) hide show
  1. package/dist_bundle/bundle.js +1814 -917
  2. package/dist_bundle/bundle.js.map +3 -3
  3. package/dist_ts_web/00_commitinfo_data.js +1 -1
  4. package/dist_ts_web/elements/upl-statuspage-assetsselector.js +119 -45
  5. package/dist_ts_web/elements/upl-statuspage-footer.js +81 -27
  6. package/dist_ts_web/elements/upl-statuspage-header.js +79 -19
  7. package/dist_ts_web/elements/upl-statuspage-incidents.js +242 -55
  8. package/dist_ts_web/elements/upl-statuspage-statsgrid.d.ts +3 -0
  9. package/dist_ts_web/elements/upl-statuspage-statsgrid.js +239 -52
  10. package/dist_ts_web/elements/upl-statuspage-statusbar.js +58 -7
  11. package/dist_ts_web/elements/upl-statuspage-statusdetails.js +36 -11
  12. package/dist_ts_web/elements/upl-statuspage-statusmonth.d.ts +2 -0
  13. package/dist_ts_web/elements/upl-statuspage-statusmonth.js +415 -230
  14. package/dist_ts_web/styles/shared.styles.d.ts +22 -0
  15. package/dist_ts_web/styles/shared.styles.js +146 -3
  16. package/dist_watch/bundle.js +1425 -446
  17. package/dist_watch/bundle.js.map +3 -3
  18. package/dist_watch/index.html +1 -0
  19. package/package.json +1 -1
  20. package/ts_web/00_commitinfo_data.ts +1 -1
  21. package/ts_web/elements/upl-statuspage-assetsselector.ts +118 -44
  22. package/ts_web/elements/upl-statuspage-footer.ts +80 -26
  23. package/ts_web/elements/upl-statuspage-header.ts +87 -18
  24. package/ts_web/elements/upl-statuspage-incidents.ts +248 -56
  25. package/ts_web/elements/upl-statuspage-statsgrid.ts +235 -55
  26. package/ts_web/elements/upl-statuspage-statusbar.ts +57 -6
  27. package/ts_web/elements/upl-statuspage-statusdetails.ts +35 -10
  28. package/ts_web/elements/upl-statuspage-statusmonth.ts +436 -252
  29. package/ts_web/styles/shared.styles.ts +166 -2
@@ -108,36 +108,79 @@ export class UplStatuspageIncidents extends DeesElement {
108
108
  background: ${sharedStyles.colors.background.card};
109
109
  padding: ${unsafeCSS(sharedStyles.spacing.xl)};
110
110
  margin-bottom: ${unsafeCSS(sharedStyles.spacing.lg)};
111
- border-radius: ${unsafeCSS(sharedStyles.borderRadius.md)};
111
+ border-radius: ${unsafeCSS(sharedStyles.borderRadius.lg)};
112
112
  border: 1px solid ${sharedStyles.colors.border.default};
113
113
  text-align: center;
114
114
  color: ${sharedStyles.colors.text.secondary};
115
115
  box-shadow: ${unsafeCSS(sharedStyles.shadows.sm)};
116
+ animation: fadeInUp 0.4s ${unsafeCSS(sharedStyles.easings.default)} both;
116
117
  }
117
118
 
119
+ /* Staggered entrance animations */
118
120
  .incident-card {
119
121
  background: ${sharedStyles.colors.background.card};
120
- border-radius: ${unsafeCSS(sharedStyles.borderRadius.md)};
122
+ border-radius: ${unsafeCSS(sharedStyles.borderRadius.lg)};
121
123
  margin-bottom: ${unsafeCSS(sharedStyles.spacing.lg)};
122
124
  overflow: hidden;
123
125
  box-shadow: ${unsafeCSS(sharedStyles.shadows.sm)};
124
126
  border: 1px solid ${sharedStyles.colors.border.default};
125
- transition: all 0.2s ease;
127
+ transition: all ${unsafeCSS(sharedStyles.durations.normal)} ${unsafeCSS(sharedStyles.easings.default)};
128
+ animation: fadeInUp 0.4s ${unsafeCSS(sharedStyles.easings.default)} both;
126
129
  }
127
130
 
128
- .incident-card.expanded {
131
+ .incident-card:nth-child(1) { animation-delay: 0ms; }
132
+ .incident-card:nth-child(2) { animation-delay: 50ms; }
133
+ .incident-card:nth-child(3) { animation-delay: 100ms; }
134
+ .incident-card:nth-child(4) { animation-delay: 150ms; }
135
+ .incident-card:nth-child(5) { animation-delay: 200ms; }
136
+
137
+ .incident-card:hover {
138
+ transform: translateY(-2px);
129
139
  box-shadow: ${unsafeCSS(sharedStyles.shadows.md)};
140
+ border-color: ${sharedStyles.colors.border.muted};
141
+ }
142
+
143
+ .incident-card.expanded {
144
+ box-shadow: ${unsafeCSS(sharedStyles.shadows.lg)};
145
+ }
146
+
147
+ /* Active incident pulse effect */
148
+ .incident-card.active-incident {
149
+ animation: fadeInUp 0.4s ${unsafeCSS(sharedStyles.easings.default)} both,
150
+ incident-pulse 3s ease-in-out infinite;
151
+ }
152
+
153
+ @keyframes fadeInUp {
154
+ from {
155
+ opacity: 0;
156
+ transform: translateY(16px);
157
+ }
158
+ to {
159
+ opacity: 1;
160
+ transform: translateY(0);
161
+ }
162
+ }
163
+
164
+ @keyframes incident-pulse {
165
+ 0%, 100% {
166
+ box-shadow: ${unsafeCSS(sharedStyles.shadows.sm)};
167
+ }
168
+ 50% {
169
+ box-shadow: ${unsafeCSS(sharedStyles.shadows.md)},
170
+ 0 0 0 2px ${cssManager.bdTheme('rgba(239, 68, 68, 0.15)', 'rgba(248, 113, 113, 0.2)')};
171
+ }
130
172
  }
131
173
 
132
174
  .incident-header {
133
- padding: ${unsafeCSS(sharedStyles.spacing.lg)} ${unsafeCSS(sharedStyles.spacing.lg)};
175
+ padding: ${unsafeCSS(sharedStyles.spacing.lg)} ${unsafeCSS(sharedStyles.spacing.xl)};
134
176
  border-left: 4px solid;
135
177
  display: flex;
136
178
  align-items: start;
137
179
  justify-content: space-between;
138
180
  gap: ${unsafeCSS(sharedStyles.spacing.md)};
139
181
  cursor: pointer;
140
- transition: background-color 0.2s ease;
182
+ transition: background-color ${unsafeCSS(sharedStyles.durations.fast)} ${unsafeCSS(sharedStyles.easings.default)};
183
+ position: relative;
141
184
  }
142
185
 
143
186
  .incident-header:hover {
@@ -161,10 +204,11 @@ export class UplStatuspageIncidents extends DeesElement {
161
204
  }
162
205
 
163
206
  .incident-title {
164
- font-size: 18px;
207
+ font-size: 17px;
165
208
  font-weight: 600;
166
209
  margin: 0;
167
- line-height: 1.3;
210
+ line-height: 1.4;
211
+ letter-spacing: -0.01em;
168
212
  }
169
213
 
170
214
  .incident-meta {
@@ -176,17 +220,24 @@ export class UplStatuspageIncidents extends DeesElement {
176
220
  flex-wrap: wrap;
177
221
  }
178
222
 
223
+ .incident-meta span {
224
+ display: flex;
225
+ align-items: center;
226
+ gap: 4px;
227
+ }
228
+
179
229
  .incident-status {
180
230
  display: inline-flex;
181
231
  align-items: center;
182
- gap: ${unsafeCSS(sharedStyles.spacing.xs)};
183
- padding: ${unsafeCSS(sharedStyles.spacing.xs)} ${unsafeCSS(sharedStyles.spacing.md)};
232
+ gap: 6px;
233
+ padding: 6px 12px;
184
234
  border-radius: ${unsafeCSS(sharedStyles.borderRadius.full)};
185
- font-size: 12px;
235
+ font-size: 11px;
186
236
  font-weight: 600;
187
237
  text-transform: uppercase;
188
- letter-spacing: 0.02em;
238
+ letter-spacing: 0.04em;
189
239
  flex-shrink: 0;
240
+ transition: all ${unsafeCSS(sharedStyles.durations.fast)} ${unsafeCSS(sharedStyles.easings.default)};
190
241
  }
191
242
 
192
243
  .incident-status.investigating {
@@ -214,68 +265,165 @@ export class UplStatuspageIncidents extends DeesElement {
214
265
  color: ${cssManager.bdTheme('#4b5563', '#d1d5db')};
215
266
  }
216
267
 
268
+ /* Pulse for investigating status */
269
+ .incident-status.investigating .status-dot {
270
+ animation: status-pulse 1.5s ease-in-out infinite;
271
+ }
272
+
273
+ @keyframes status-pulse {
274
+ 0%, 100% { opacity: 1; transform: scale(1); }
275
+ 50% { opacity: 0.6; transform: scale(1.2); }
276
+ }
277
+
217
278
  .incident-body {
218
- padding: 0 ${unsafeCSS(sharedStyles.spacing.lg)} ${unsafeCSS(sharedStyles.spacing.lg)} ${unsafeCSS(sharedStyles.spacing.lg)};
279
+ padding: 0 ${unsafeCSS(sharedStyles.spacing.xl)} ${unsafeCSS(sharedStyles.spacing.xl)} ${unsafeCSS(sharedStyles.spacing.xl)};
280
+ animation: slideDown 0.3s ${unsafeCSS(sharedStyles.easings.default)};
281
+ }
282
+
283
+ @keyframes slideDown {
284
+ from {
285
+ opacity: 0;
286
+ transform: translateY(-8px);
287
+ }
288
+ to {
289
+ opacity: 1;
290
+ transform: translateY(0);
291
+ }
219
292
  }
220
293
 
221
294
  .incident-impact {
222
295
  margin: ${unsafeCSS(sharedStyles.spacing.md)} 0;
223
- padding: ${unsafeCSS(sharedStyles.spacing.md)};
296
+ padding: ${unsafeCSS(sharedStyles.spacing.md)} ${unsafeCSS(sharedStyles.spacing.lg)};
224
297
  background: ${sharedStyles.colors.background.secondary};
225
298
  border-radius: ${unsafeCSS(sharedStyles.borderRadius.base)};
226
299
  font-size: 14px;
227
300
  line-height: 1.6;
301
+ border-left: 3px solid ${sharedStyles.colors.border.muted};
228
302
  }
229
303
 
230
304
  .affected-services {
231
- margin-top: ${unsafeCSS(sharedStyles.spacing.md)};
305
+ margin-top: ${unsafeCSS(sharedStyles.spacing.lg)};
232
306
  }
233
307
 
234
308
  .affected-services-title {
235
- font-size: 13px;
309
+ font-size: 12px;
236
310
  font-weight: 600;
237
311
  margin-bottom: ${unsafeCSS(sharedStyles.spacing.sm)};
238
- color: ${sharedStyles.colors.text.primary};
312
+ color: ${sharedStyles.colors.text.secondary};
313
+ text-transform: uppercase;
314
+ letter-spacing: 0.04em;
239
315
  }
240
316
 
241
317
  .service-tag {
242
318
  display: inline-block;
243
- padding: ${unsafeCSS(sharedStyles.spacing.xs)} ${unsafeCSS(sharedStyles.spacing.sm)};
319
+ padding: 4px 10px;
244
320
  margin: 2px;
245
321
  background: ${sharedStyles.colors.background.muted};
246
322
  border-radius: ${unsafeCSS(sharedStyles.borderRadius.sm)};
247
323
  font-size: 12px;
248
324
  color: ${sharedStyles.colors.text.secondary};
325
+ transition: all ${unsafeCSS(sharedStyles.durations.fast)} ${unsafeCSS(sharedStyles.easings.default)};
249
326
  }
250
327
 
328
+ .service-tag:hover {
329
+ background: ${sharedStyles.colors.background.secondary};
330
+ color: ${sharedStyles.colors.text.primary};
331
+ }
332
+
333
+ /* Timeline visualization for updates */
251
334
  .incident-updates {
252
- margin-top: ${unsafeCSS(sharedStyles.spacing.lg)};
335
+ margin-top: ${unsafeCSS(sharedStyles.spacing.xl)};
253
336
  border-top: 1px solid ${sharedStyles.colors.border.default};
254
337
  padding-top: ${unsafeCSS(sharedStyles.spacing.lg)};
255
338
  }
256
339
 
340
+ .updates-title {
341
+ font-size: 12px;
342
+ font-weight: 600;
343
+ text-transform: uppercase;
344
+ letter-spacing: 0.04em;
345
+ margin: 0 0 ${unsafeCSS(sharedStyles.spacing.lg)} 0;
346
+ color: ${sharedStyles.colors.text.secondary};
347
+ }
348
+
349
+ .timeline {
350
+ position: relative;
351
+ padding-left: 24px;
352
+ }
353
+
354
+ /* Vertical connector line */
355
+ .timeline::before {
356
+ content: '';
357
+ position: absolute;
358
+ left: 7px;
359
+ top: 10px;
360
+ bottom: calc(100% - 10px);
361
+ height: auto;
362
+ width: 2px;
363
+ background: ${cssManager.bdTheme(
364
+ 'linear-gradient(to bottom, #e5e7eb 0%, #d1d5db 50%, #e5e7eb 100%)',
365
+ 'linear-gradient(to bottom, #27272a 0%, #3f3f46 50%, #27272a 100%)'
366
+ )};
367
+ border-radius: 1px;
368
+ }
369
+
257
370
  .update-item {
258
371
  position: relative;
259
372
  padding-left: ${unsafeCSS(sharedStyles.spacing.lg)};
260
- margin-bottom: ${unsafeCSS(sharedStyles.spacing.md)};
373
+ padding-bottom: ${unsafeCSS(sharedStyles.spacing.lg)};
374
+ animation: fadeInUp 0.3s ${unsafeCSS(sharedStyles.easings.default)} both;
375
+ }
376
+
377
+ .update-item:last-child {
378
+ padding-bottom: 0;
261
379
  }
262
380
 
381
+ /* Timeline dot */
263
382
  .update-item::before {
264
383
  content: '';
265
384
  position: absolute;
266
- left: 0;
267
- top: 6px;
268
- width: 8px;
269
- height: 8px;
270
- border-radius: ${unsafeCSS(sharedStyles.borderRadius.full)};
271
- background: ${sharedStyles.colors.border.muted};
385
+ left: -22px;
386
+ top: 4px;
387
+ width: 12px;
388
+ height: 12px;
389
+ border-radius: 50%;
390
+ background: ${sharedStyles.colors.background.card};
391
+ border: 2px solid ${sharedStyles.colors.border.muted};
392
+ z-index: 1;
393
+ transition: all ${unsafeCSS(sharedStyles.durations.fast)} ${unsafeCSS(sharedStyles.easings.default)};
394
+ }
395
+
396
+ .update-item:first-child::before {
397
+ border-color: ${sharedStyles.colors.status.operational};
398
+ background: ${sharedStyles.colors.status.operational};
399
+ box-shadow: 0 0 0 3px ${cssManager.bdTheme('rgba(22, 163, 74, 0.15)', 'rgba(34, 197, 94, 0.2)')};
400
+ }
401
+
402
+ .update-item:hover::before {
403
+ transform: scale(1.2);
404
+ border-color: ${sharedStyles.colors.text.secondary};
272
405
  }
273
406
 
274
407
  .update-time {
275
- font-size: 12px;
276
- color: ${sharedStyles.colors.text.secondary};
277
- margin-bottom: ${unsafeCSS(sharedStyles.spacing.xs)};
408
+ font-size: 11px;
409
+ color: ${sharedStyles.colors.text.muted};
410
+ margin-bottom: 4px;
278
411
  font-family: ${unsafeCSS(sharedStyles.fonts.mono)};
412
+ display: flex;
413
+ align-items: center;
414
+ gap: 8px;
415
+ }
416
+
417
+ .update-status-badge {
418
+ display: inline-flex;
419
+ padding: 2px 6px;
420
+ border-radius: 4px;
421
+ font-size: 10px;
422
+ font-weight: 600;
423
+ text-transform: uppercase;
424
+ letter-spacing: 0.02em;
425
+ background: ${sharedStyles.colors.background.muted};
426
+ color: ${sharedStyles.colors.text.secondary};
279
427
  }
280
428
 
281
429
  .update-message {
@@ -286,9 +434,11 @@ export class UplStatuspageIncidents extends DeesElement {
286
434
 
287
435
  .update-author {
288
436
  font-size: 12px;
289
- color: ${sharedStyles.colors.text.secondary};
290
- margin-top: ${unsafeCSS(sharedStyles.spacing.xs)};
291
- font-style: italic;
437
+ color: ${sharedStyles.colors.text.muted};
438
+ margin-top: 4px;
439
+ display: flex;
440
+ align-items: center;
441
+ gap: 4px;
292
442
  }
293
443
 
294
444
  .loading-skeleton {
@@ -298,33 +448,34 @@ export class UplStatuspageIncidents extends DeesElement {
298
448
  'linear-gradient(90deg, #1f1f1f 25%, #262626 50%, #1f1f1f 75%)'
299
449
  )};
300
450
  background-size: 200% 100%;
301
- animation: loading 1.5s infinite;
302
- border-radius: ${unsafeCSS(sharedStyles.borderRadius.md)};
451
+ animation: shimmer 1.5s infinite;
452
+ border-radius: ${unsafeCSS(sharedStyles.borderRadius.lg)};
303
453
  margin-bottom: ${unsafeCSS(sharedStyles.spacing.lg)};
304
454
  }
305
455
 
306
- @keyframes loading {
456
+ @keyframes shimmer {
307
457
  0% { background-position: 200% 0; }
308
458
  100% { background-position: -200% 0; }
309
459
  }
310
460
 
311
461
  .show-more {
312
462
  text-align: center;
313
- margin-top: ${unsafeCSS(sharedStyles.spacing.lg)};
463
+ margin-top: ${unsafeCSS(sharedStyles.spacing.xl)};
314
464
  }
315
465
 
316
466
  .show-more-button {
317
467
  display: inline-flex;
318
468
  align-items: center;
319
469
  justify-content: center;
320
- padding: ${unsafeCSS(sharedStyles.spacing.sm)} ${unsafeCSS(sharedStyles.spacing.lg)};
470
+ gap: 8px;
471
+ padding: 10px 20px;
321
472
  background: transparent;
322
473
  border: 1px solid ${sharedStyles.colors.border.default};
323
474
  border-radius: ${unsafeCSS(sharedStyles.borderRadius.base)};
324
475
  cursor: pointer;
325
476
  font-size: 14px;
326
477
  font-weight: 500;
327
- transition: all 0.2s ease;
478
+ transition: all ${unsafeCSS(sharedStyles.durations.fast)} ${unsafeCSS(sharedStyles.easings.default)};
328
479
  color: ${sharedStyles.colors.text.primary};
329
480
  font-family: ${unsafeCSS(sharedStyles.fonts.base)};
330
481
  }
@@ -332,7 +483,8 @@ export class UplStatuspageIncidents extends DeesElement {
332
483
  .show-more-button:hover {
333
484
  background: ${sharedStyles.colors.background.secondary};
334
485
  border-color: ${sharedStyles.colors.border.muted};
335
- transform: translateY(-1px);
486
+ transform: translateY(-2px);
487
+ box-shadow: ${unsafeCSS(sharedStyles.shadows.sm)};
336
488
  }
337
489
 
338
490
  .show-more-button:active {
@@ -351,15 +503,15 @@ export class UplStatuspageIncidents extends DeesElement {
351
503
  .subscribe-button {
352
504
  display: inline-flex;
353
505
  align-items: center;
354
- gap: ${unsafeCSS(sharedStyles.spacing.xs)};
355
- padding: ${unsafeCSS(sharedStyles.spacing.xs)} ${unsafeCSS(sharedStyles.spacing.md)};
506
+ gap: 6px;
507
+ padding: 8px 14px;
356
508
  background: transparent;
357
509
  border: 1px solid ${sharedStyles.colors.border.default};
358
510
  border-radius: ${unsafeCSS(sharedStyles.borderRadius.base)};
359
511
  cursor: pointer;
360
512
  font-size: 13px;
361
- font-weight: 400;
362
- transition: all 0.2s ease;
513
+ font-weight: 500;
514
+ transition: all ${unsafeCSS(sharedStyles.durations.fast)} ${unsafeCSS(sharedStyles.easings.default)};
363
515
  color: ${sharedStyles.colors.text.primary};
364
516
  font-family: ${unsafeCSS(sharedStyles.fonts.base)};
365
517
  }
@@ -367,14 +519,15 @@ export class UplStatuspageIncidents extends DeesElement {
367
519
  .subscribe-button:hover {
368
520
  background: ${sharedStyles.colors.background.secondary};
369
521
  border-color: ${sharedStyles.colors.border.muted};
522
+ transform: translateY(-1px);
370
523
  }
371
-
524
+
372
525
  .subscribe-button.subscribed {
373
526
  background: ${cssManager.bdTheme('#f0fdf4', '#064e3b')};
374
527
  border-color: ${cssManager.bdTheme('#86efac', '#047857')};
375
528
  color: ${cssManager.bdTheme('#047857', '#86efac')};
376
529
  }
377
-
530
+
378
531
  .subscribe-button.subscribed:hover {
379
532
  background: ${cssManager.bdTheme('#dcfce7', '#065f46')};
380
533
  }
@@ -387,6 +540,15 @@ export class UplStatuspageIncidents extends DeesElement {
387
540
  opacity: 0.8;
388
541
  }
389
542
 
543
+ /* Expand icon animation */
544
+ .expand-icon {
545
+ transition: transform ${unsafeCSS(sharedStyles.durations.normal)} ${unsafeCSS(sharedStyles.easings.default)};
546
+ }
547
+
548
+ .expand-icon.rotated {
549
+ transform: rotate(180deg);
550
+ }
551
+
390
552
  @media (max-width: 640px) {
391
553
  .container {
392
554
  padding: 0 ${unsafeCSS(sharedStyles.spacing.md)} ${unsafeCSS(sharedStyles.spacing.md)} ${unsafeCSS(sharedStyles.spacing.md)};
@@ -396,10 +558,28 @@ export class UplStatuspageIncidents extends DeesElement {
396
558
  padding: ${unsafeCSS(sharedStyles.spacing.md)};
397
559
  }
398
560
 
561
+ .incident-body {
562
+ padding: 0 ${unsafeCSS(sharedStyles.spacing.md)} ${unsafeCSS(sharedStyles.spacing.md)} ${unsafeCSS(sharedStyles.spacing.md)};
563
+ }
564
+
399
565
  .incident-meta {
400
566
  flex-direction: column;
401
567
  gap: ${unsafeCSS(sharedStyles.spacing.xs)};
402
568
  }
569
+
570
+ .timeline {
571
+ padding-left: 20px;
572
+ }
573
+
574
+ .timeline::before {
575
+ left: 4px;
576
+ }
577
+
578
+ .update-item::before {
579
+ left: -18px;
580
+ width: 10px;
581
+ height: 10px;
582
+ }
403
583
  }
404
584
  `,
405
585
  ];
@@ -438,12 +618,14 @@ export class UplStatuspageIncidents extends DeesElement {
438
618
 
439
619
  private renderIncident(incident: IIncidentDetails, isCurrent: boolean): TemplateResult {
440
620
  const latestUpdate = incident.updates[incident.updates.length - 1];
441
- const duration = incident.endTime ?
621
+ const duration = incident.endTime ?
442
622
  this.formatDuration(incident.endTime - incident.startTime) :
443
623
  this.formatDuration(Date.now() - incident.startTime);
444
-
624
+
625
+ const isActive = isCurrent && latestUpdate?.status !== 'resolved';
626
+
445
627
  return html`
446
- <div class="incident-card ${this.expandedIncidents.has(incident.id) ? 'expanded' : ''}">
628
+ <div class="incident-card ${this.expandedIncidents.has(incident.id) ? 'expanded' : ''} ${isActive ? 'active-incident' : ''}">
447
629
  <div class="incident-header ${incident.severity}" @click=${() => this.toggleIncident(incident.id)}>
448
630
  <div>
449
631
  <h3 class="incident-title">${incident.title}</h3>
@@ -520,8 +702,10 @@ export class UplStatuspageIncidents extends DeesElement {
520
702
 
521
703
  ${incident.updates.length > 0 ? html`
522
704
  <div class="incident-updates">
523
- <h4 style="font-size: 14px; margin: 0 0 12px 0;">Updates</h4>
524
- ${incident.updates.slice(-3).reverse().map(update => this.renderUpdate(update))}
705
+ <h4 class="updates-title">Updates</h4>
706
+ <div class="timeline">
707
+ ${incident.updates.slice(-3).reverse().map((update, index) => this.renderUpdate(update, index))}
708
+ </div>
525
709
  </div>
526
710
  ` : ''}
527
711
 
@@ -571,25 +755,33 @@ export class UplStatuspageIncidents extends DeesElement {
571
755
  `;
572
756
  }
573
757
 
574
- private renderUpdate(update: any): TemplateResult {
758
+ private renderUpdate(update: any, index: number = 0): TemplateResult {
575
759
  return html`
576
- <div class="update-item">
577
- <div class="update-time">${this.formatDate(update.timestamp)}</div>
760
+ <div class="update-item" style="animation-delay: ${index * 50}ms">
761
+ <div class="update-time">
762
+ ${this.formatDate(update.timestamp)}
763
+ ${update.status ? html`<span class="update-status-badge">${update.status}</span>` : ''}
764
+ </div>
578
765
  <div class="update-message">${update.message}</div>
579
766
  ${update.author ? html`
580
- <div class="update-author">— ${update.author}</div>
767
+ <div class="update-author">
768
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
769
+ <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
770
+ <circle cx="12" cy="7" r="4"></circle>
771
+ </svg>
772
+ ${update.author}
773
+ </div>
581
774
  ` : ''}
582
775
  </div>
583
776
  `;
584
777
  }
585
778
 
586
779
  private getStatusIcon(status: string): TemplateResult {
587
- return html`<span style="
780
+ return html`<span class="status-dot" style="
588
781
  display: inline-block;
589
782
  width: 6px;
590
783
  height: 6px;
591
784
  border-radius: 50%;
592
- margin-right: 4px;
593
785
  background: ${status === 'resolved' ? sharedStyles.colors.status.operational :
594
786
  status === 'monitoring' ? sharedStyles.colors.status.maintenance :
595
787
  status === 'identified' ? sharedStyles.colors.status.degraded :