From c78289bfef0fe80ce7cac4ce85da622a29c29752 Mon Sep 17 00:00:00 2001 From: Johannes Date: Mon, 15 Jun 2026 16:39:21 -0400 Subject: [PATCH] fix(aria): replace plain Refresh button with canonical circular auto-refresh control All three list pages (ThreatEvents, PrecursorAlerts, DevicePosture) now use the template's btn-manual-refresh icon button + SVG countdown timer in header-controls, matching the canonical TablePage.svelte pattern. Plain text Refresh button removed from toolbar-right. Co-Authored-By: Claude Sonnet 4.6 --- frontend/src/components/DevicePosture.svelte | 94 +++++++++++++++--- .../src/components/PrecursorAlerts.svelte | 95 ++++++++++++++++--- frontend/src/components/ThreatEvents.svelte | 87 ++++++++++++++++- 3 files changed, 252 insertions(+), 24 deletions(-) diff --git a/frontend/src/components/DevicePosture.svelte b/frontend/src/components/DevicePosture.svelte index cb7aa62..5da8610 100644 --- a/frontend/src/components/DevicePosture.svelte +++ b/frontend/src/components/DevicePosture.svelte @@ -1,5 +1,5 @@
@@ -98,6 +133,34 @@

Device Posture

Per-device security compliance — disk encryption, image integrity, OS currency

+
+ + +
@@ -179,9 +242,6 @@
{totalElements} device{totalElements !== 1 ? 's' : ''} -
- -
@@ -462,12 +522,25 @@ } .toolbar { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; flex-shrink: 0; } .toolbar-count { font-size: var(--font-size-body-sm); color: #6b7280; } - .toolbar-right { display: flex; gap: 0.5rem; } - .btn-refresh { - background: #f3f4f6; color: #374151; border: 1px solid #d1d5db; - border-radius: 6px; padding: 6px 12px; font-size: var(--font-size-body-sm); font-weight: 500; cursor: pointer; + .header-controls { display: flex; align-items: center; gap: 0.5rem; flex-shrink: 0; } + .btn-manual-refresh { + background: rgba(255,255,255,0.15); border: 1px solid rgba(255,255,255,0.3); + color: white; border-radius: 50%; width: 36px; height: 36px; + display: flex; align-items: center; justify-content: center; + font-size: 1.1rem; cursor: pointer; transition: background 0.15s; flex-shrink: 0; } - .btn-refresh:hover { background: #e5e7eb; } + .btn-manual-refresh:hover:not(:disabled) { background: rgba(255,255,255,0.28); } + .btn-manual-refresh:disabled { opacity: 0.5; cursor: not-allowed; } + .refresh-countdown { + flex-shrink: 0; background: none; border: none; cursor: pointer; padding: 0; + border-radius: 50%; display: flex; align-items: center; justify-content: center; + opacity: 0.9; transition: opacity 0.15s, transform 0.15s; + } + .refresh-countdown:hover { opacity: 1; transform: scale(1.08); } + .refresh-countdown.paused { opacity: 0.5; } + .refresh-countdown.paused:hover { opacity: 0.8; } + @keyframes countdown-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } } + :global(.pulsing) { animation: countdown-pulse 0.8s ease-in-out infinite; } /* Table card — canonical */ .table-card { @@ -590,7 +663,6 @@ :global(.dark-mode) .filter-tag-remove { background: #374151; color: #e5e7eb; } :global(.dark-mode) .toolbar-count { color: #9ca3af; } - :global(.dark-mode) .btn-refresh { background: #374151; color: #e5e7eb; border-color: #4b5563; } :global(.dark-mode) .table-card { background: #1f2937; } :global(.dark-mode) thead { background: #111827; border-bottom-color: #374151; } diff --git a/frontend/src/components/PrecursorAlerts.svelte b/frontend/src/components/PrecursorAlerts.svelte index a164fa0..536ffd8 100644 --- a/frontend/src/components/PrecursorAlerts.svelte +++ b/frontend/src/components/PrecursorAlerts.svelte @@ -1,5 +1,5 @@
@@ -98,6 +133,34 @@

Threat Events

IOC match events detected across the fleet

+
+ + +
@@ -229,6 +292,26 @@ padding: 24px 24px 0; } + .header-controls { display: flex; align-items: center; gap: 0.5rem; flex-shrink: 0; } + .btn-manual-refresh { + background: rgba(255,255,255,0.15); border: 1px solid rgba(255,255,255,0.3); + color: white; border-radius: 50%; width: 36px; height: 36px; + display: flex; align-items: center; justify-content: center; + font-size: 1.1rem; cursor: pointer; transition: background 0.15s; flex-shrink: 0; + } + .btn-manual-refresh:hover:not(:disabled) { background: rgba(255,255,255,0.28); } + .btn-manual-refresh:disabled { opacity: 0.5; cursor: not-allowed; } + .refresh-countdown { + flex-shrink: 0; background: none; border: none; cursor: pointer; padding: 0; + border-radius: 50%; display: flex; align-items: center; justify-content: center; + opacity: 0.9; transition: opacity 0.15s, transform 0.15s; + } + .refresh-countdown:hover { opacity: 1; transform: scale(1.08); } + .refresh-countdown.paused { opacity: 0.5; } + .refresh-countdown.paused:hover { opacity: 0.8; } + @keyframes countdown-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } } + :global(.pulsing) { animation: countdown-pulse 0.8s ease-in-out infinite; } + .page-body { display: flex; flex: 1; overflow: hidden; min-height: 0; }