Dashboard: stop flex children shrinking (bar text overflowed), wrap the bar, gate saves on loaded layout, fix double v in footer

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Mitchell-Johnson
2026-09-17 14:07:56 -07:00
co-authored by Claude Fable 5.1
parent 1751afc974
commit cd3979efce
3 changed files with 7 additions and 5 deletions
+4 -3
View File
@@ -260,6 +260,7 @@ export default function Dashboard() {
const [err, setErr] = useState('')
const [layout, setLayout] = useState<Layout>(() => normalize({}))
const [editing, setEditing] = useState(false)
const [loaded, setLoaded] = useState(false)
const hist = useRef<Series | null>(null)
const saveTimer = useRef<number | undefined>(undefined)
const intervalRef = useRef(DEFAULT_INTERVAL)
@@ -278,7 +279,7 @@ export default function Dashboard() {
useEffect(() => {
let stop = false
let timer: number | undefined
api.dashPrefs().then((p) => { if (!stop) setLayout(normalize(p)) }).catch(() => { /* defaults */ })
api.dashPrefs().then((p) => { if (!stop) { setLayout(normalize(p)); setLoaded(true) } }).catch(() => setErr('could not load layout'))
const seed = async () => {
try { hist.current = await api.metricsHistory(); setLatest(await api.metrics()); setErr('') }
catch (e) { setErr(e instanceof Error ? e.message : 'failed') }
@@ -364,12 +365,12 @@ export default function Dashboard() {
<select className="btn" value={layout.intervalMs} onChange={(e) => update((l) => ({ ...l, intervalMs: Number(e.target.value) }))}>
{INTERVALS.map((ms) => <option key={ms} value={ms}>{fmtMs(ms)}</option>)}
</select>
· charts show the last {fmtWindow(layout.intervalMs)} · ▲▼ reorder, ✕ hides a module or row
· last {fmtWindow(layout.intervalMs)} · ▲▼ reorder · ✕ hide
</label>
) : <span className="hint">last {fmtWindow(latest.interval_ms || layout.intervalMs)} · {fmtMs(latest.interval_ms || layout.intervalMs)}</span>}
<span className="spacer" />
{editing && <button className="btn" onClick={reset}>Reset</button>}
<button className={'btn' + (editing ? ' on' : '')} onClick={() => setEditing(!editing)}>{editing ? 'Done' : 'Customize'}</button>
<button className={'btn' + (editing ? ' on' : '')} disabled={!loaded} title={loaded ? '' : 'layout not loaded'} onClick={() => setEditing(!editing)}>{editing ? 'Done' : 'Customize'}</button>
</div>
{visible('tile').length > 0 && (
+1 -1
View File
@@ -98,7 +98,7 @@ export default function Shell({ me, onLoggedOut }: { me: Me; onLoggedOut: () =>
setCtrl={(v) => handles.current[activeTerm.id]?.armCtrl(v)} />}
<footer className="footer">
<span>v{me.version}</span>
<span>{me.version.startsWith('v') ? me.version : 'v' + me.version}</span>
<span>up {fmtUptime(me.uptime)}</span>
<span className="spacer" />
<span className="muted">{view === 'dashboard' ? 'Dashboard' : activeTerm ? activeTerm.name : ''}</span>
+2 -1
View File
@@ -81,6 +81,7 @@ button { font: inherit; color: inherit; background: none; border: 0; cursor: poi
/* dashboard */
.dash { position: absolute; inset: 0; overflow-y: auto; padding: 12px; display: flex; flex-direction: column; gap: 12px; background: var(--bg); -webkit-overflow-scrolling: touch; }
.dash > * { flex-shrink: 0; }
.kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 12px; }
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 12px; align-items: start; }
.tile, .card { background: var(--bg2); border: 1px solid var(--border); border-radius: 8px; padding: 12px; min-width: 0; }
@@ -108,7 +109,7 @@ button { font: inherit; color: inherit; background: none; border: 0; cursor: poi
@media (max-width: 800px) { .dash { padding: 8px; gap: 8px; } .kpis, .cards { gap: 8px; } .cards { grid-template-columns: 1fr; } }
/* dashboard: customize mode */
.dash-bar { display: flex; align-items: center; gap: 8px; min-height: 28px; }
.dash-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.dash-bar .hint { color: var(--muted); font-size: 12px; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.dash-bar select.btn { padding: 3px 6px; }
.btn { padding: 5px 10px; background: var(--bg3); border: 1px solid var(--border); border-radius: 5px; font-size: 12px; color: var(--fg); }