swarm-ui: compact refresh-interval picker, moved into the panel header

Per mara's review on this PR: the labelled SelectField-based picker
read as way too heavy for a passive-until-touched setting - a full
label+bordered-control form field row above the table. Replace it with
a compact inline "clock icon - value - chevron" control (a native
<select> still drives the interaction, just stripped of SelectField/
FormField's chrome), quiet until hovered/focused the same way
LinksMenu's header button is.

Also move it out of the panel body entirely: Panel gains an `actions`
slot in its title row (right-aligned via margin-left: auto), so the
picker sits next to the "hives" heading instead of taking its own row
and pushing the table down - per the design guide's own "a control
belongs next to the thing it affects" rule.

Verified with headless chromium screenshots (full page + a tight
close-up crop) against the built bundle: the picker now reads as
"(clock) 30s (chevron)" inline with the panel title, no extra vertical
space taken from the table. Added a Panel "with actions" demo to
ComponentsPage.
This commit is contained in:
iris 2026-08-18 22:49:04 +02:00 • committed by mara
commit fc44891ab5
6 changed files with 139 additions and 21 deletions

View file

@ -2,13 +2,35 @@
// bordered surface with an optional title, no other opinions. Not a
// card-with-actions/footer/whatever kit — those get added the first
// time a real page actually needs one, not speculatively ahead of it.
//
// `actions` is that one addition: a slot in the title row, right-
// aligned, for a control that belongs next to the panel's own heading
// rather than its own row inside the body (design guide: "a control
// belongs next to the thing it affects, not tucked into a catch-all
// menu" — and per mara's review on the refresh-interval PR, not a
// dedicated row stealing vertical space from the panel's actual
// content either). `HivesPage`'s refresh-interval picker is the
// motivating caller.
import type { ComponentChildren } from 'preact';
import './Panel.css';
export function Panel({ title, children }: { title?: string; children: ComponentChildren }) {
export function Panel({
title,
actions,
children,
}: {
title?: string;
actions?: ComponentChildren;
children: ComponentChildren;
}) {
return (
<section class="ui-panel">
{title ? <h2 class="ui-panel-title">{title}</h2> : null}
{title || actions ? (
<div class="ui-panel-header">
{title ? <h2 class="ui-panel-title">{title}</h2> : null}
{actions ? <div class="ui-panel-actions">{actions}</div> : null}
</div>
) : null}
<div class="ui-panel-body">{children}</div>
</section>
);