feat: extend the record-row design system to Host Overview, Alerts, and About
Extract the settings redesign's tokens and components into shared static/hbd-ui.css + hbd-ui.js and dedupe settings.html against them. About becomes yaml-key sections with kv rows; Alerts gets stat tiles, chip filters, and alert record rows (same fetch/ack logic); Host Overview keeps its DOM and live-update JS but is re-skinned to the token system with a page toolbar. Live Dashboard intentionally untouched pending its own redesign. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NfPpSpccTWBfZg1FTveyaU
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
/* hbd-ui.css — shared design system for hbd pages.
|
||||
*
|
||||
* Green-biased neutrals, teal accent, mono identifiers. Pages link this
|
||||
* after static/style.css and build on the tokens + components below.
|
||||
* Introduced with the settings-page redesign; see settings.html for the
|
||||
* fullest use of the row/editor idiom.
|
||||
*/
|
||||
|
||||
:root {
|
||||
--st-paper: #f4f6f4;
|
||||
--st-surface: #ffffff;
|
||||
--st-surface-2: #eef1ee;
|
||||
--st-ink: #1d2420;
|
||||
--st-muted: #5f6a63;
|
||||
--st-faint: #8a948d;
|
||||
--st-line: #dde3de;
|
||||
--st-line-soft: #e8ece8;
|
||||
--st-accent: #0e7280;
|
||||
--st-accent-ink: #ffffff;
|
||||
--st-accent-soft: #e0eef0;
|
||||
--st-ok: #3f9c5a;
|
||||
--st-ok-soft: #e2f2e7;
|
||||
--st-warn: #d9982a;
|
||||
--st-warn-soft: #f9efdc;
|
||||
--st-crit: #d64545;
|
||||
--st-crit-soft: #f9e3e3;
|
||||
--st-badge-owner: #ede7f6; --st-badge-owner-ink: #5e35b1;
|
||||
--st-badge-mgr: #e3f2fd; --st-badge-mgr-ink: #1565c0;
|
||||
--st-mono: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;
|
||||
}
|
||||
html[data-theme="dark"] {
|
||||
--st-paper: #131816;
|
||||
--st-surface: #1b211e;
|
||||
--st-surface-2: #222925;
|
||||
--st-ink: #e4eae6;
|
||||
--st-muted: #9aa69e;
|
||||
--st-faint: #6e7a72;
|
||||
--st-line: #2c342f;
|
||||
--st-line-soft: #252c28;
|
||||
--st-accent: #4cc4d4;
|
||||
--st-accent-ink: #0d2326;
|
||||
--st-accent-soft: #143b40;
|
||||
--st-ok: #5cba77;
|
||||
--st-ok-soft: #1c2f22;
|
||||
--st-warn: #e0ad4e;
|
||||
--st-warn-soft: #33290f;
|
||||
--st-crit: #e06c6c;
|
||||
--st-crit-soft: #3a1a1a;
|
||||
--st-badge-owner: #33294a; --st-badge-owner-ink: #b39ddb;
|
||||
--st-badge-mgr: #1b3350; --st-badge-mgr-ink: #90caf9;
|
||||
}
|
||||
|
||||
/* ── sticky toolbar under the site nav ── */
|
||||
.st-toolbar {
|
||||
position: sticky; top: var(--nav-h, 48px); z-index: 90;
|
||||
display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
|
||||
padding: 9px 20px;
|
||||
background: var(--st-surface); border-bottom: 1px solid var(--st-line);
|
||||
}
|
||||
.st-toolbar .brand { font-family: var(--st-mono); font-size: 15px; font-weight: 700; letter-spacing: -.02em; color: var(--st-ink); }
|
||||
.st-toolbar .brand .tld { color: var(--st-accent); }
|
||||
.st-toolbar .hintline { font-size: 12px; color: var(--st-faint); }
|
||||
.st-toolbar .spacer { flex: 1; }
|
||||
|
||||
/* ── ECG pulse divider ── */
|
||||
.pulse { display: block; width: 100%; height: 14px; }
|
||||
.pulse polyline { fill: none; stroke: var(--st-accent); stroke-width: 1.5; opacity: .55; }
|
||||
|
||||
/* ── buttons ── */
|
||||
.btn {
|
||||
font: 600 13px/1 inherit; border: 1px solid var(--st-line); border-radius: 6px;
|
||||
background: var(--st-surface); color: var(--st-ink); padding: 7px 14px; cursor: pointer;
|
||||
}
|
||||
.btn:focus-visible, a:focus-visible { outline: 2px solid var(--st-accent); outline-offset: 2px; }
|
||||
.btn.primary { background: var(--st-accent); border-color: var(--st-accent); color: var(--st-accent-ink); }
|
||||
.btn.quiet { border-color: transparent; background: transparent; color: var(--st-muted); }
|
||||
.btn.small { padding: 4px 10px; font-size: 12px; }
|
||||
.btn.danger { color: var(--st-crit); }
|
||||
.btn:disabled { opacity: .6; cursor: default; }
|
||||
|
||||
/* ── section headers as config keys ── */
|
||||
section.st { margin-top: 26px; scroll-margin-top: calc(var(--bars-h, 94px) + 12px); }
|
||||
.sec-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 8px; flex-wrap: wrap; }
|
||||
.sec-head h2 { margin: 0; font-family: var(--st-mono); font-size: 15px; font-weight: 700; color: var(--st-ink); }
|
||||
.sec-head h2 .colon { color: var(--st-accent); }
|
||||
.sec-head .count { font-family: var(--st-mono); font-size: 11.5px; color: var(--st-faint); }
|
||||
.sec-head .sub { font-size: 12px; color: var(--st-muted); }
|
||||
.sec-head .add { margin-left: auto; }
|
||||
|
||||
/* ── record list + row ── */
|
||||
.list { background: var(--st-surface); border: 1px solid var(--st-line); border-radius: 8px; overflow: hidden; }
|
||||
.row {
|
||||
display: grid; grid-template-columns: 190px minmax(0,1fr) auto;
|
||||
gap: 4px 14px; align-items: center;
|
||||
padding: 8px 14px; border-bottom: 1px solid var(--st-line-soft);
|
||||
transition: background .12s ease;
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) { .row { transition: none; } }
|
||||
.row:last-child { border-bottom: none; }
|
||||
.row:hover { background: var(--st-surface-2); }
|
||||
.row .id { font-family: var(--st-mono); font-size: 13px; font-weight: 600; color: var(--st-ink); display: flex; align-items: center; gap: 8px; min-width: 0; }
|
||||
.row .id .name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.row .act { display: flex; gap: 4px; justify-content: flex-end; }
|
||||
|
||||
.dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
|
||||
.dot.ok { background: var(--st-ok); }
|
||||
.dot.warn { background: var(--st-warn); }
|
||||
.dot.crit { background: var(--st-crit); }
|
||||
.dot.off { background: transparent; border: 1.5px solid var(--st-faint); }
|
||||
|
||||
.facts { display: flex; flex-wrap: wrap; gap: 4px 6px; align-items: center; min-width: 0; }
|
||||
.chip {
|
||||
display: inline-flex; align-items: center; gap: 4px;
|
||||
font-family: var(--st-mono); font-size: 11px; line-height: 1.3;
|
||||
padding: 3px 7px; border-radius: 4px;
|
||||
background: var(--st-surface-2); color: var(--st-muted);
|
||||
}
|
||||
.chip.owner { background: var(--st-badge-owner); color: var(--st-badge-owner-ink); }
|
||||
.chip.mgr { background: var(--st-badge-mgr); color: var(--st-badge-mgr-ink); }
|
||||
.chip.level { background: transparent; border: 1px solid var(--st-line); }
|
||||
.chip.private { background: transparent; border: 1px dashed var(--st-badge-owner-ink); color: var(--st-badge-owner-ink); }
|
||||
.chip.ok { background: var(--st-ok-soft); color: var(--st-ok); }
|
||||
.chip.warn { background: var(--st-warn-soft); color: var(--st-warn); }
|
||||
.chip.crit { background: var(--st-crit-soft); color: var(--st-crit); }
|
||||
.chip .k { color: var(--st-faint); }
|
||||
.chip .w { color: var(--st-warn); font-weight: 700; }
|
||||
.chip .c { color: var(--st-crit); font-weight: 700; }
|
||||
|
||||
/* ── key/value rows (server groups, about page) ── */
|
||||
.kv .row { grid-template-columns: 230px minmax(0,1fr); padding: 6px 14px; }
|
||||
.group {
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
padding: 7px 14px 5px; font-family: var(--st-mono); font-size: 11px; color: var(--st-faint);
|
||||
background: var(--st-surface); border-bottom: 1px solid var(--st-line-soft);
|
||||
}
|
||||
.group .gbtn { margin-left: auto; }
|
||||
.kv .val { font-family: var(--st-mono); font-size: 12.5px; color: var(--st-muted); min-width: 0; }
|
||||
.kv .val a { color: var(--st-accent); text-decoration: none; }
|
||||
.kv .val a:hover { text-decoration: underline; }
|
||||
.kv .desc { display: block; font-size: 11px; color: var(--st-faint); margin-top: 2px; }
|
||||
.val-masked { color: var(--st-faint); letter-spacing: 2px; }
|
||||
|
||||
.note { margin: 8px 2px 0; font-size: 12px; color: var(--st-faint); }
|
||||
|
||||
/* ── handheld defaults for rows ── */
|
||||
@media (max-width: 760px) {
|
||||
.st-toolbar { padding: 8px 10px; }
|
||||
.st-toolbar .hintline { display: none; }
|
||||
.row { grid-template-columns: minmax(0,1fr) auto; padding: 9px 12px; }
|
||||
.row .id { grid-row: 1; grid-column: 1; }
|
||||
.row .act { grid-row: 1; grid-column: 2; }
|
||||
.row .facts { grid-column: 1 / -1; }
|
||||
.kv .row { grid-template-columns: 1fr; }
|
||||
section.st { scroll-margin-top: calc(var(--bars-h, 94px) + 50px); }
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/* hbd-ui.js — shared helpers for pages using hbd-ui.css.
|
||||
*
|
||||
* Keeps sticky toolbars stuck just below the fixed site nav, whose height
|
||||
* varies with viewport width and wrapping.
|
||||
*/
|
||||
|
||||
function _setStickyOffsets() {
|
||||
const nav = document.querySelector('.nav');
|
||||
const tb = document.querySelector('.st-toolbar');
|
||||
const navH = nav ? nav.offsetHeight : 48;
|
||||
const barsH = navH + (tb ? tb.offsetHeight : 46);
|
||||
document.documentElement.style.setProperty('--nav-h', navH + 'px');
|
||||
document.documentElement.style.setProperty('--bars-h', barsH + 'px');
|
||||
}
|
||||
window.addEventListener('resize', _setStickyOffsets);
|
||||
document.addEventListener('DOMContentLoaded', _setStickyOffsets);
|
||||
Reference in New Issue
Block a user