Phase 7: polish — overview health, reduced-motion, mobile, a11y, copy-ids

- Overview health hero derives from subsystem probes when the backend gives no
  overall status, so it never says "Unknown" next to an all-Healthy Subsystems
  card (the audit's most jarring contradiction). Home error copy now uses the
  Phase-2 describeError instead of raw backend strings.
- Global prefers-reduced-motion guard (transitions, loops, aurora field) +
  motion-reduce on the sidebar width transition.
- Mobile: content reserves a top row (pt-16 md:p-6) so the floating hamburger
  never overlaps the page H1.
- A11y: collapsed rail items get an explicit aria-label.
- Monitoring: disk "busiest mount" tile shows the % as the value and the long
  mount path as a truncated caption, so it no longer clips mid-word.
- New CopyId component (click-to-copy UUIDs), wired into Profile.

Typecheck 36→36, 24-route sweep clean. Remaining items (lib a11y labels,
table aria-sort, dev-only monitoring data) noted in the spec.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
jules
2026-07-14 14:40:58 +10:00
parent a03fbd9e9b
commit 3fcdddefda
6 changed files with 129 additions and 15 deletions

View File

@@ -334,7 +334,15 @@ export default function MonitoringRoute() {
/>
<KpiTile
label="Disk (busiest mount)"
value={busiestDiskLabel(data.host.disks)}
// The percentage alone is the metric — keep it in `value` so it
// never clips. The mount path (which can be long) goes in the
// caption, truncated with the full path on hover.
value={busiestDiskValue(data.host.disks)}
caption={
<span className="block truncate" title={busiestDiskMount(data.host.disks)}>
{busiestDiskMount(data.host.disks)}
</span>
}
icon={<Database className="size-4" />}
tone={
busiestDiskPct(data.host.disks) > 90
@@ -691,10 +699,18 @@ function busiestDiskPct(disks: HostStats["disks"]): number {
return disks.reduce((m, d) => Math.max(m, d.used_pct), 0)
}
function busiestDiskLabel(disks: HostStats["disks"]): string {
if (disks.length === 0) return "—"
const busiest = disks.reduce((a, b) => (b.used_pct > a.used_pct ? b : a))
return `${busiest.used_pct}% (${busiest.mount})`
function busiestDisk(disks: HostStats["disks"]) {
if (disks.length === 0) return null
return disks.reduce((a, b) => (b.used_pct > a.used_pct ? b : a))
}
function busiestDiskValue(disks: HostStats["disks"]): string {
const d = busiestDisk(disks)
return d ? `${d.used_pct}%` : "—"
}
function busiestDiskMount(disks: HostStats["disks"]): string {
return busiestDisk(disks)?.mount ?? "no mounts"
}
function barColor(pct: number): string {