Add Svelte 5 frontend (App, TitleBar, BlockRing, ModelStack, WeeklyBar, Settings)
This commit is contained in:
parent
14ffcf4bd3
commit
0e8a87fbc5
17 changed files with 779 additions and 0 deletions
77
src/components/BlockRing.svelte
Normal file
77
src/components/BlockRing.svelte
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
<script lang="ts">
|
||||
import type { BlockSummary } from "../types";
|
||||
import { formatTokens, formatCountdown, formatPct } from "../format";
|
||||
|
||||
let {
|
||||
block,
|
||||
cap,
|
||||
nowSeconds,
|
||||
}: {
|
||||
block: BlockSummary | null;
|
||||
cap: number;
|
||||
/** Locally-decremented countdown so we don't IPC just to tick the clock. */
|
||||
nowSeconds: number;
|
||||
} = $props();
|
||||
|
||||
// Geometry.
|
||||
const SIZE = 140;
|
||||
const STROKE = 12;
|
||||
const R = (SIZE - STROKE) / 2;
|
||||
const C = 2 * Math.PI * R;
|
||||
|
||||
let pct = $derived(block && cap > 0 ? Math.min(1, block.total_tokens / cap) : 0);
|
||||
let dash = $derived(C * pct);
|
||||
let color = $derived(
|
||||
pct > 0.95 ? "var(--danger)" : pct > 0.8 ? "var(--warn)" : "var(--accent)",
|
||||
);
|
||||
let pulse = $derived(pct > 0.9);
|
||||
</script>
|
||||
|
||||
<div class="wrap">
|
||||
<svg width={SIZE} height={SIZE} viewBox={`0 0 ${SIZE} ${SIZE}`}>
|
||||
<!-- track -->
|
||||
<circle
|
||||
cx={SIZE / 2}
|
||||
cy={SIZE / 2}
|
||||
r={R}
|
||||
fill="none"
|
||||
stroke="var(--border)"
|
||||
stroke-width={STROKE}
|
||||
/>
|
||||
<!-- progress -->
|
||||
<circle
|
||||
cx={SIZE / 2}
|
||||
cy={SIZE / 2}
|
||||
r={R}
|
||||
fill="none"
|
||||
stroke={color}
|
||||
stroke-width={STROKE}
|
||||
stroke-linecap="round"
|
||||
stroke-dasharray={`${dash} ${C}`}
|
||||
transform={`rotate(-90 ${SIZE / 2} ${SIZE / 2})`}
|
||||
class:pulse
|
||||
/>
|
||||
<text x={SIZE / 2} y={SIZE / 2 - 6} text-anchor="middle" class="big">
|
||||
{block ? formatTokens(block.total_tokens) : "—"}
|
||||
</text>
|
||||
<text x={SIZE / 2} y={SIZE / 2 + 12} text-anchor="middle" class="small">
|
||||
{block ? formatPct(block.total_tokens, cap) : ""}
|
||||
</text>
|
||||
<text x={SIZE / 2} y={SIZE / 2 + 30} text-anchor="middle" class="countdown">
|
||||
{block ? formatCountdown(nowSeconds) : "no activity"}
|
||||
</text>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.wrap { display: flex; justify-content: center; padding: 14px 0 6px; }
|
||||
text { fill: var(--fg); font-family: inherit; }
|
||||
text.big { font-size: 22px; font-weight: 600; }
|
||||
text.small { font-size: 11px; fill: var(--fg-dim); }
|
||||
text.countdown { font-size: 11px; fill: var(--fg-dim); font-variant-numeric: tabular-nums; }
|
||||
.pulse { animation: pulse 1.6s ease-in-out infinite; }
|
||||
@keyframes pulse {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.55; }
|
||||
}
|
||||
</style>
|
||||
Loading…
Add table
Add a link
Reference in a new issue