feat(hosts): a host's health tiles span the card and the gaps match; Add host is a dialog on the list (#5290, #5291)
CI / lint (push) Successful in 3s
CI / integration (push) Successful in 54s
CI / unit (push) Successful in 1m18s
CI / publish (push) Successful in 1m23s

#5290 "Host page: the health tiles span the card's width; even spacing above Ansible":
the four tiles take equal quarters (halves on a phone) and their sparklines stretch
across them; the Monitors + Agent row drops the Agent card's own margin, so the gap
above Ansible is 1rem like every other.

#5291 "Add host opens as a dialog over the Hosts list": a native <dialog> on /hosts/,
opened by Add host or /hosts/?add=1. A name clash re-renders the list with it open,
the error and what was typed. GET /hosts/new is gone; hosts/form.html is Edit only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-07 18:22:48 -04:00
co-authored by Claude Opus 5.5
parent bfe3618e88
commit fb20415a38
13 changed files with 136 additions and 52 deletions
+17
View File
@@ -299,6 +299,23 @@ a.stat-tile:hover { border-color: var(--border-mid); background: var(--bg-elevat
/* The host page's health header (_host_vitals.html). */
.host-health-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.35rem 0.75rem; margin-bottom: 0.75rem; }
.host-health-summary { font-size: 0.92rem; }
/* Its four tiles share the card's width (two a row on a phone); each sparkline
stretches across its tile. */
.host-health-tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.host-health-tiles .stat-tile { min-width: 0; }
.host-health-tiles .stat-tile-hint { margin-top: 0.25rem; }
@media (max-width: 640px) { .host-health-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* Monitors and Agent side by side: equal height, and the row keeps the same
1rem gap below it as every other card (the panel's own card margin would add
a second). */
.host-pair { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(420px, 100%), 1fr)); gap: 1rem; margin-bottom: 1rem; }
.host-pair > * { min-width: 0; }
.host-pair .card { margin-bottom: 0; height: 100%; }
/* A small form over the page (native <dialog>; Esc closes it). */
.modal { width: min(560px, calc(100vw - 2rem)); padding: 1.25rem; color: var(--text); background: var(--bg-card);
border: 1px solid var(--border); border-radius: var(--fs-radius-md); box-shadow: var(--fs-shadow-3); }
.modal::backdrop { background: var(--fs-overlay); }
.modal-title { font-family: var(--font-serif); font-size: 1.25rem; font-weight: 500; margin: 0 0 1rem; }
/* A filled bar for a percentage; the fill takes its grade from status_class. */
.meter { height: 8px; background: var(--bg-elevated); border: 1px solid var(--border); border-radius: 4px; overflow: hidden; }
.meter-fill { height: 100%; }