Files
electric-cherry/src/lib/ui/components/primitives/StatusPip.svelte
T

82 lines
1.9 KiB
Svelte

<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', 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} t-{resolvedTone} shape-{shape}"
role={label ? 'img' : undefined}
aria-label={label ?? undefined}
aria-hidden={label ? undefined : true}
></span>
<style>
.pip {
display: inline-flex;
flex-shrink: 0;
box-sizing: border-box;
}
.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>