Clarify UI status and remove noisy live regions
This commit is contained in:
@@ -1,66 +1,40 @@
|
||||
<script lang="ts">
|
||||
import type { Health } from '$ui/stores/servers.js';
|
||||
import { statusPresentation, statusShapes, type StatusTone } from '$ui/status.js';
|
||||
|
||||
interface Props {
|
||||
health?: Health;
|
||||
state?: string;
|
||||
tone?: StatusTone;
|
||||
size?: 'sm' | 'md';
|
||||
label?: string | null;
|
||||
}
|
||||
|
||||
let { health = 'offline', size = 'md', label = null }: Props = $props();
|
||||
|
||||
let toneClass = $derived(
|
||||
health === 'online' ? 't-online' :
|
||||
health === 'stale' || health === 'starting' || health === 'provisioning' ? 't-warning' :
|
||||
't-danger'
|
||||
);
|
||||
|
||||
let announceLabel = $derived(
|
||||
label ?? (
|
||||
health === 'online' ? 'online' :
|
||||
health === 'starting' ? 'starting' :
|
||||
health === 'provisioning' ? 'provisioning' :
|
||||
health === 'stale' ? 'stale' :
|
||||
'offline'
|
||||
)
|
||||
);
|
||||
let { health = 'offline', state, tone, size = 'md', label = null }: Props = $props();
|
||||
const presentation = $derived(statusPresentation(state ?? health));
|
||||
const resolvedTone = $derived(tone ?? presentation.tone);
|
||||
const shape = $derived(statusShapes[resolvedTone]);
|
||||
</script>
|
||||
|
||||
<span class="pip s-{size} {toneClass}" role="status" aria-label={announceLabel}>
|
||||
<span class="halo" aria-hidden="true"></span>
|
||||
<span class="dot" aria-hidden="true"></span>
|
||||
</span>
|
||||
<span class="pip s-{size} t-{resolvedTone} shape-{shape}" role={label ? 'img' : undefined} aria-label={label ?? undefined} aria-hidden={label ? undefined : true}></span>
|
||||
|
||||
<style>
|
||||
.pip {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.s-sm { width: 8px; height: 8px; }
|
||||
.s-md { width: 10px; height: 10px; }
|
||||
|
||||
.dot {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
/* Halo — opacity+scale only, GPU-cheap, no box-shadow ring. */
|
||||
.halo {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: 50%;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.t-online .dot { background: var(--state-online); box-shadow: 0 0 4px rgba(124, 212, 255, 0.55); }
|
||||
.t-online .halo { background: var(--state-online); animation: pip-breathe 2.4s var(--ease-standard) infinite; }
|
||||
|
||||
.t-warning .dot { background: var(--state-warning); }
|
||||
.t-danger .dot { background: var(--state-danger); opacity: 0.7; }
|
||||
.s-sm { width: 10px; height: 10px; }
|
||||
.s-md { width: 12px; height: 12px; }
|
||||
.t-online { color: var(--state-online); }
|
||||
.t-warning { color: var(--state-warning); }
|
||||
.t-danger { color: var(--state-danger); }
|
||||
.t-info { color: var(--state-info); }
|
||||
.t-neutral { color: var(--state-neutral); }
|
||||
.shape-circle { border-radius: 50%; background: currentColor; }
|
||||
.shape-square { border-radius: 2px; background: currentColor; }
|
||||
.shape-triangle { background: currentColor; clip-path: polygon(50% 0, 100% 100%, 0 100%); }
|
||||
.shape-hollow, .shape-ring { border: 2px solid currentColor; border-radius: 50%; }
|
||||
.shape-ring { border-right-color: transparent; animation: status-spin 1s linear infinite; }
|
||||
@keyframes status-spin { to { transform: rotate(360deg); } }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user