swarm-ui: fix create-agent form field alignment and panel width
TextField and SelectField's shared FormField wrapper had no width of its own, so inside the form's shrink-to-fit flex column each field's input/select resolved its 'width: 100%' against its own shrunk wrapper rather than a shared column width — two fields with differently-long labels ended up with differently-wide controls. FormField now caps its own width the same way the control already does, so every field in a form lines up regardless of label length. Also wrapped the page in a max-width container: Panel has no width opinion of its own, so it filled the full page column, leaving a lot of bare panel to the right of the ~16em-wide form.
This commit is contained in:
parent
7880483b51
commit
f14fc154cc
3 changed files with 69 additions and 40 deletions
|
|
@ -4,7 +4,19 @@
|
||||||
not row: with a second field (hive) added, a row layout put fields of
|
not row: with a second field (hive) added, a row layout put fields of
|
||||||
different natural widths on one baseline and looked misaligned —
|
different natural widths on one baseline and looked misaligned —
|
||||||
mara: "make it a col". Reuses the same base16 slots (../theme.css)
|
mara: "make it a col". Reuses the same base16 slots (../theme.css)
|
||||||
every other component draws from. */
|
every other component draws from.
|
||||||
|
|
||||||
|
`.create-agent-page` caps the panel's own width: `Panel` has no width
|
||||||
|
opinion of its own, so left unconstrained it filled `.shell-body`'s
|
||||||
|
full 60em column — a lot of bare panel to the right of a ~16em-wide
|
||||||
|
form, the "weird empty space" mara flagged alongside the field
|
||||||
|
misalignment. 24em roughly matches the fields' own 16em cap
|
||||||
|
(../ui/form-field/FormField.css) plus the panel's 1em body padding on
|
||||||
|
each side and a little breathing room, so the panel reads as sized to
|
||||||
|
its content instead of to the page column. */
|
||||||
|
.create-agent-page {
|
||||||
|
max-width: 24em;
|
||||||
|
}
|
||||||
.create-agent-intro {
|
.create-agent-intro {
|
||||||
margin: 0 0 1.5em;
|
margin: 0 0 1.5em;
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
|
|
|
||||||
|
|
@ -125,44 +125,48 @@ export function CreateAgentPage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Panel title="create agent">
|
<div class="create-agent-page">
|
||||||
<p class="create-agent-intro">
|
<Panel title="create agent">
|
||||||
Create a new agent's swarm-level identity. This only queues the job — check{' '}
|
<p class="create-agent-intro">
|
||||||
<Link href="/jobs">jobs</Link> to watch it settle.
|
Create a new agent's swarm-level identity. This only queues the job — check{' '}
|
||||||
</p>
|
<Link href="/jobs">jobs</Link> to watch it settle.
|
||||||
{hivesError && <ApiErrorPanel context="failed to load the hive list" problem={hivesError} />}
|
|
||||||
<form class="create-agent-form" onSubmit={submit}>
|
|
||||||
<TextField
|
|
||||||
id="agent-name"
|
|
||||||
label="agent name"
|
|
||||||
value={name}
|
|
||||||
pattern={NAME_PATTERN}
|
|
||||||
title="1-63 chars: lowercase letters, digits, hyphens"
|
|
||||||
required
|
|
||||||
onInput={setName}
|
|
||||||
/>
|
|
||||||
<SelectField
|
|
||||||
id="agent-hive"
|
|
||||||
label="hive"
|
|
||||||
value={hive}
|
|
||||||
onChange={setHive}
|
|
||||||
options={hiveOptions}
|
|
||||||
required
|
|
||||||
disabled={!hivesReady}
|
|
||||||
placeholder={!hives ? 'loading…' : hives.length === 0 ? 'no hives configured' : 'select a hive'}
|
|
||||||
/>
|
|
||||||
<Button variant="primary" type="submit" disabled={result.status === 'submitting' || !hivesReady}>
|
|
||||||
{result.status === 'submitting' ? 'creating…' : 'create'}
|
|
||||||
</Button>
|
|
||||||
</form>
|
|
||||||
{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>
|
</p>
|
||||||
)}
|
{hivesError && <ApiErrorPanel context="failed to load the hive list" problem={hivesError} />}
|
||||||
{result.status === 'error' && (
|
<form class="create-agent-form" onSubmit={submit}>
|
||||||
<ApiErrorPanel context="failed to queue" problem={result.problem} />
|
<TextField
|
||||||
)}
|
id="agent-name"
|
||||||
</Panel>
|
label="agent name"
|
||||||
|
value={name}
|
||||||
|
pattern={NAME_PATTERN}
|
||||||
|
title="1-63 chars: lowercase letters, digits, hyphens"
|
||||||
|
required
|
||||||
|
onInput={setName}
|
||||||
|
/>
|
||||||
|
<SelectField
|
||||||
|
id="agent-hive"
|
||||||
|
label="hive"
|
||||||
|
value={hive}
|
||||||
|
onChange={setHive}
|
||||||
|
options={hiveOptions}
|
||||||
|
required
|
||||||
|
disabled={!hivesReady}
|
||||||
|
placeholder={
|
||||||
|
!hives ? 'loading…' : hives.length === 0 ? 'no hives configured' : 'select a hive'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Button variant="primary" type="submit" disabled={result.status === 'submitting' || !hivesReady}>
|
||||||
|
{result.status === 'submitting' ? 'creating…' : 'create'}
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
|
{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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,24 @@
|
||||||
every control in the kit whether or not it's ever used on a touch
|
every control in the kit whether or not it's ever used on a touch
|
||||||
device, since the alternative is a component that behaves differently
|
device, since the alternative is a component that behaves differently
|
||||||
per input method. Colours are the shared base16-derived vars
|
per input method. Colours are the shared base16-derived vars
|
||||||
(../../theme.css), never literal. */
|
(../../theme.css), never literal.
|
||||||
|
|
||||||
|
The field wrapper repeats `.ui-form-control`'s own `width: 100%;
|
||||||
|
max-width: 16em` rather than leaving the wrapper unconstrained: inside
|
||||||
|
a shrink-to-fit flex column (`CreateAgentPage`'s form is one), an
|
||||||
|
unconstrained wrapper sizes to its own content — and a `width: 100%`
|
||||||
|
*control* inside an auto-width wrapper resolves against that shrunk
|
||||||
|
width, not the intended 16em cap, so two fields with differently-long
|
||||||
|
labels ("agent name" vs "hive") ended up with differently-wide inputs —
|
||||||
|
the misalignment mara reported on the create-agent page. Matching the
|
||||||
|
two declarations here means every field's control width is driven by
|
||||||
|
the same fixed cap regardless of its label's length or its siblings'. */
|
||||||
.ui-form-field {
|
.ui-form-field {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.3em;
|
gap: 0.3em;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 16em;
|
||||||
}
|
}
|
||||||
.ui-form-field-label {
|
.ui-form-field-label {
|
||||||
font-size: 0.85em;
|
font-size: 0.85em;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue