feat: Reduce server vitials panel height
This commit is contained in:
@@ -273,13 +273,13 @@ export default function ServerDetailPage() {
|
||||
* (z-40) and under the nav drawer (z-50). The scroll container is
|
||||
* AppShell's column, not the window, which is what sticky anchors to.
|
||||
*/}
|
||||
<div className="sticky top-14 z-20 border-b border-border bg-background/90 px-4 pt-4 backdrop-blur sm:px-6 lg:top-0 lg:px-8">
|
||||
<div className="sticky top-14 z-20 border-b border-border bg-background/90 px-4 pt-3 backdrop-blur sm:pt-4 sm:px-6 lg:top-0 lg:px-8">
|
||||
<Link href="/servers" className="text-sm text-text-secondary transition-colors hover:text-text-primary">
|
||||
← Servers
|
||||
</Link>
|
||||
|
||||
<div className="mt-2 flex flex-wrap items-center gap-x-3 gap-y-2">
|
||||
<h1 className="text-2xl font-bold text-text-primary">{server.hostname}</h1>
|
||||
<div className="mt-1.5 flex flex-wrap items-center gap-x-3 gap-y-2 sm:mt-2">
|
||||
<h1 className="text-xl font-bold text-text-primary sm:text-2xl">{server.hostname}</h1>
|
||||
<Badge variant={statusVariant(server.status)}>{server.status}</Badge>
|
||||
<span className="font-mono text-sm text-text-secondary">{server.ip_address}</span>
|
||||
<div className="ml-auto">
|
||||
@@ -287,7 +287,7 @@ export default function ServerDetailPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-2">
|
||||
<div className="mt-1.5 sm:mt-2">
|
||||
<TagChips serverId={server.server_id} tags={server.tags} editable />
|
||||
</div>
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import { formatBytes, relativeAge } from "./format";
|
||||
function Meter({ pct }: { pct: number }) {
|
||||
const clamped = Math.max(0, Math.min(100, pct));
|
||||
return (
|
||||
<div className="mt-2 h-[3px] w-full overflow-hidden rounded-full bg-well">
|
||||
<div className="mt-1.5 h-[3px] w-full overflow-hidden rounded-full bg-well sm:mt-2">
|
||||
<div
|
||||
className={clsx("h-full rounded-full transition-[width] duration-500", clamped >= 90 ? "bg-danger" : clamped >= 75 ? "bg-warning" : "bg-accent")}
|
||||
style={{ width: `${clamped}%` }}
|
||||
@@ -28,13 +28,16 @@ function Meter({ pct }: { pct: number }) {
|
||||
|
||||
function Vital({ label, value, pct, sub }: { label: string; value: string; pct?: number; sub?: string }) {
|
||||
return (
|
||||
<div className="min-w-0 bg-surface px-4 py-3">
|
||||
<div className="flex items-baseline justify-between gap-3">
|
||||
<span className="font-mono text-[0.62rem] uppercase tracking-[0.16em] text-text-secondary">{label}</span>
|
||||
<span className="font-mono text-sm font-semibold tabular-nums text-text-primary">{value}</span>
|
||||
// Label over value below sm: on a phone the two side by side wrap the
|
||||
// value onto a second line, and four cells each a line taller is the
|
||||
// whole viewport gone before the tabs.
|
||||
<div className="min-w-0 bg-surface px-3 py-2.5 sm:px-4 sm:py-3">
|
||||
<div className="flex flex-col gap-0.5 sm:flex-row sm:items-baseline sm:justify-between sm:gap-3">
|
||||
<span className="truncate font-mono text-[0.58rem] uppercase tracking-[0.14em] text-text-secondary sm:text-[0.62rem] sm:tracking-[0.16em]">{label}</span>
|
||||
<span className="truncate font-mono text-[0.8rem] font-semibold tabular-nums text-text-primary sm:text-sm">{value}</span>
|
||||
</div>
|
||||
{pct !== undefined ? <Meter pct={pct} /> : <div className="mt-2 h-[3px] w-full rounded-full bg-well" />}
|
||||
{sub && <p className="mt-1.5 truncate text-xs text-text-tertiary">{sub}</p>}
|
||||
{pct !== undefined ? <Meter pct={pct} /> : <div className="mt-1.5 h-[3px] w-full rounded-full bg-well sm:mt-2" />}
|
||||
{sub && <p className="mt-1 truncate text-[0.68rem] text-text-tertiary sm:mt-1.5 sm:text-xs">{sub}</p>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -47,6 +50,17 @@ function primaryPartition(inv: Inventory) {
|
||||
return parts.find((p) => p.mountpoint === "/") ?? parts.reduce((worst, p) => (p.used_bytes / (p.total_bytes || 1) > worst.used_bytes / (worst.total_bytes || 1) ? p : worst));
|
||||
}
|
||||
|
||||
/** "10.8 / 16.0 GB" rather than "10.8 GB / 16.0 GB" when both halves carry the
|
||||
* same unit — the repeated unit is what pushes the memory cell onto a second
|
||||
* line on a phone, and it says nothing the right-hand half does not. */
|
||||
function pair(used: number, total: number) {
|
||||
const u = formatBytes(used);
|
||||
const t = formatBytes(total);
|
||||
const uu = u.split(" ")[1];
|
||||
const tu = t.split(" ")[1];
|
||||
return uu && uu === tu ? `${u.split(" ")[0]} / ${t}` : `${u} / ${t}`;
|
||||
}
|
||||
|
||||
export function VitalsRail({ server, agentUpToDate }: { server: Server; agentUpToDate?: boolean }) {
|
||||
const inv = server.inventory;
|
||||
const disk = inv ? primaryPartition(inv) : undefined;
|
||||
@@ -58,7 +72,7 @@ export function VitalsRail({ server, agentUpToDate }: { server: Server; agentUpT
|
||||
return (
|
||||
// One hairline grid rather than four cards: these are readings off one
|
||||
// machine, and four bordered panels would read as four subjects.
|
||||
<div className="mt-4 grid grid-cols-2 gap-px overflow-hidden rounded border border-border-soft bg-border-soft lg:grid-cols-4">
|
||||
<div className="mt-3 grid grid-cols-2 gap-px sm:mt-4 overflow-hidden rounded border border-border-soft bg-border-soft lg:grid-cols-4">
|
||||
{inv ? (
|
||||
<>
|
||||
<Vital
|
||||
@@ -69,15 +83,15 @@ export function VitalsRail({ server, agentUpToDate }: { server: Server; agentUpT
|
||||
/>
|
||||
<Vital
|
||||
label="Memory"
|
||||
value={`${formatBytes(inv.memory.used_bytes)} / ${formatBytes(inv.memory.total_bytes)}`}
|
||||
value={pair(inv.memory.used_bytes, inv.memory.total_bytes)}
|
||||
pct={memPct}
|
||||
sub={inv.swap_total_bytes > 0 ? `swap ${formatBytes(inv.swap_used_bytes)} / ${formatBytes(inv.swap_total_bytes)}` : "no swap"}
|
||||
sub={inv.swap_total_bytes > 0 ? `swap ${pair(inv.swap_used_bytes, inv.swap_total_bytes)}` : "no swap"}
|
||||
/>
|
||||
<Vital
|
||||
label={disk ? `Disk ${disk.mountpoint}` : "Disk"}
|
||||
value={disk ? `${diskPct.toFixed(0)}%` : "—"}
|
||||
pct={disk ? diskPct : undefined}
|
||||
sub={disk ? `${formatBytes(disk.used_bytes)} / ${formatBytes(disk.total_bytes)}${disk.fstype ? ` · ${disk.fstype}` : ""}` : "no partitions reported"}
|
||||
sub={disk ? `${pair(disk.used_bytes, disk.total_bytes)}${disk.fstype ? ` · ${disk.fstype}` : ""}` : "no partitions reported"}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user