swarm-ui: fill create-agent's empty column with an explanatory panel

mara's follow-up on the field-alignment fix: narrowing the form panel
left a lot of bare space next to it, and asked for something that
fills it while helping a new user understand what the page does.

Adds a second panel beside the form (stacks under it on a narrow
viewport) explaining the job chain '/api/agents' actually queues:
an authelia identity, then a forge config repo — no container exists
yet after this page, and deploying one onto the chosen hive is a
separate step that isn't wired up server-side.
This commit is contained in:
iris 2026-08-19 14:28:38 +02:00 committed by mara
commit fc65811d9f
2 changed files with 99 additions and 54 deletions

View file

@ -1,21 +1,42 @@
/* <CreateAgentPage> the create-agent form. Input/button chrome now /* <CreateAgentPage> the create-agent form. Input/button chrome now
comes from the shared `ui/` form kit (`TextField`/`SelectField`/ comes from the shared `ui/` form kit (`TextField`/`SelectField`/
`Button`); this file only owns the page's own layout + copy. Column, `Button`); this file only owns the page's own layout + copy. Column,
not row: with a second field (hive) added, a row layout put fields of not row inside the form itself: with a second field (hive) added, a
different natural widths on one baseline and looked misaligned row layout put fields of different natural widths on one baseline and
mara: "make it a col". Reuses the same base16 slots (../theme.css) looked misaligned mara: "make it a col". Reuses the same base16
every other component draws from. slots (../theme.css) every other component draws from.
`.create-agent-page` caps the panel's own width: `Panel` has no width `.create-agent-page` caps the whole layout's width: `Panel` has no
opinion of its own, so left unconstrained it filled `.shell-body`'s width opinion of its own, so left unconstrained a single form panel
full 60em column a lot of bare panel to the right of a ~16em-wide filled `.shell-body`'s full 60em column a lot of bare panel to the
form, the "weird empty space" mara flagged alongside the field right of a ~16em-wide form, the "weird empty space" mara flagged
misalignment. 24em roughly matches the fields' own 16em cap alongside the original field misalignment. The follow-up ask was to
(../ui/form-field/FormField.css) plus the panel's 1em body padding on fill that space with something that explains the page rather than
each side and a little breathing room, so the panel reads as sized to just narrowing it further `.create-agent-layout` puts the form
its content instead of to the page column. */ beside a second, explanatory panel instead. `.create-agent-form-col`
keeps the same ~24em cap the single-panel version had (fields' own
16em cap, ../ui/form-field/FormField.css, plus body padding and a
little breathing room); `.create-agent-info-col` takes the rest of
the row and wraps under the form on a narrow viewport (`flex-wrap`,
no separate media query needed). */
.create-agent-page { .create-agent-page {
max-width: 24em; max-width: 44em;
}
.create-agent-layout {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
gap: 1.5em;
}
.create-agent-form-col {
flex: 0 1 24em;
}
.create-agent-info-col {
flex: 1 1 16em;
}
.create-agent-info-glyph {
margin: 0 0 0.5em;
font-size: 2em;
} }
.create-agent-intro { .create-agent-intro {
margin: 0 0 1.5em; margin: 0 0 1.5em;

View file

@ -126,47 +126,71 @@ export function CreateAgentPage() {
return ( return (
<div class="create-agent-page"> <div class="create-agent-page">
<Panel title="create agent"> <div class="create-agent-layout">
<p class="create-agent-intro"> <div class="create-agent-form-col">
Create a new agent's swarm-level identity. This only queues the job — check{' '} <Panel title="create agent">
<Link href="/jobs">jobs</Link> to watch it settle. <p class="create-agent-intro">
</p> Create a new agent's swarm-level identity. This only queues the job — check{' '}
{hivesError && <ApiErrorPanel context="failed to load the hive list" problem={hivesError} />} <Link href="/jobs">jobs</Link> to watch it settle.
<form class="create-agent-form" onSubmit={submit}> </p>
<TextField {hivesError && (
id="agent-name" <ApiErrorPanel context="failed to load the hive list" problem={hivesError} />
label="agent name" )}
value={name} <form class="create-agent-form" onSubmit={submit}>
pattern={NAME_PATTERN} <TextField
title="1-63 chars: lowercase letters, digits, hyphens" id="agent-name"
required label="agent name"
onInput={setName} value={name}
/> pattern={NAME_PATTERN}
<SelectField title="1-63 chars: lowercase letters, digits, hyphens"
id="agent-hive" required
label="hive" onInput={setName}
value={hive} />
onChange={setHive} <SelectField
options={hiveOptions} id="agent-hive"
required label="hive"
disabled={!hivesReady} value={hive}
placeholder={ onChange={setHive}
!hives ? 'loading…' : hives.length === 0 ? 'no hives configured' : 'select a hive' options={hiveOptions}
} required
/> disabled={!hivesReady}
<Button variant="primary" type="submit" disabled={result.status === 'submitting' || !hivesReady}> placeholder={
{result.status === 'submitting' ? 'creating…' : 'create'} !hives ? 'loading…' : hives.length === 0 ? 'no hives configured' : 'select a hive'
</Button> }
</form> />
{result.status === 'done' && ( <Button
<p class="create-agent-result create-agent-result-ok"> variant="primary"
queued as job node #{result.nodeId} <Link href="/jobs">watch it in jobs</Link> type="submit"
</p> disabled={result.status === 'submitting' || !hivesReady}
)} >
{result.status === 'error' && ( {result.status === 'submitting' ? 'creating…' : 'create'}
<ApiErrorPanel context="failed to queue" problem={result.problem} /> </Button>
)} </form>
</Panel> {result.status === 'done' && (
<p class="create-agent-result create-agent-result-ok">
queued as job node #{result.nodeId} <Link href="/jobs">watch it in jobs</Link>
</p>
)}
{result.status === 'error' && (
<ApiErrorPanel context="failed to queue" problem={result.problem} />
)}
</Panel>
</div>
<div class="create-agent-info-col">
<Panel title="what this creates">
<p class="create-agent-info-glyph" aria-hidden="true">
🪪
</p>
<p>
This queues a small chain of jobs, not a running agent: first an authelia identity
at the swarm level, then a config repo on the forge with the operator added as a
collaborator. It reserves everything an agent needs before any container exists
actually deploying one onto the hive you pick above is a separate step that isn't
wired up yet.
</p>
</Panel>
</div>
</div>
</div> </div>
); );
} }