Watch
0
0
Fork
You've already forked hyperhive
0

swarm-ui: the classifier settings under the ACP runtime line up on one grid

The two groups of fields had different column counts, so their edges never met,
and the price labels carried their unit, which wrapped in a monospace font and
pushed those inputs below their neighbours. Every group is one CSS grid now. The
provider fields sit under a "provider" heading, with the URL and the model each
on a full row so their placeholders are not cut off, shorter price labels and
the unit said once under them.
This commit is contained in:
iris 2026-11-06 17:33:20 +01:00 • committed by mara
commit 9b81af1fef
3 changed files with 78 additions and 46 deletions

View file

@ -296,7 +296,9 @@ API key runtime the model is free text, one word as claude's `--model` takes
it, such as `haiku` or `sonnet`. Choosing ACP shows the provider's fields in
place of the model: its `https://` URL, its model name, and what it charges in
USD per million tokens for input and output, with optional cache read and
cache write prices. The effort is one of low, medium, high, xhigh and max, or
cache write prices. The provider's fields sit under their own **provider**
heading, the URL and the model each on a row of their own and the prices in a
grid on the same columns as the fields above. The effort is one of low, medium, high, xhigh and max, or
the runtime's own default. Concurrent reviews is a whole number from 1 to 8;
try-outs don't count toward it.

View file

@ -6,13 +6,31 @@
gap: 1em;
margin-top: 1em;
}
/* One grid for every group of fields: each field has the same width and the
same edges at any width, and a label that wraps cannot push one input lower
than its neighbour's. */
.ui-classifier-settings-fields {
display: flex;
flex-wrap: wrap;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(14em, 1fr));
gap: 0.75em;
}
.ui-classifier-settings-fields > * {
flex: 1 1 14em;
/* A field that needs the whole row (a URL, a model name). */
.ui-classifier-settings-wide {
grid-column: 1 / -1;
}
/* The provider fields, under their own heading. */
.ui-classifier-settings-group {
display: flex;
flex-direction: column;
gap: 0.75em;
margin: 0;
padding: 0;
border: 0;
}
.ui-classifier-settings-group > legend {
padding: 0;
margin-bottom: 0.5em;
font-weight: 600;
}
.ui-classifier-settings-actions {
display: flex;

View file

@ -176,48 +176,60 @@ export function ClassifierSettings() {
/>
</div>
{draft.runtime === "acp" ? (
<div class="ui-classifier-settings-fields">
<TextField
id="classifier-acp-url"
label="provider URL"
value={draft.acpUrl}
placeholder="https://llm.example/v1"
onInput={(acpUrl) => edit({ ...draft, acpUrl })}
/>
<TextField
id="classifier-acp-model"
label="provider model"
value={draft.acpModel}
placeholder="Qwen/Qwen3-35B"
onInput={(acpModel) => edit({ ...draft, acpModel })}
/>
<TextField
id="classifier-acp-price-input"
label="input price (USD per million tokens)"
value={draft.priceInput}
onInput={(priceInput) => edit({ ...draft, priceInput })}
/>
<TextField
id="classifier-acp-price-output"
label="output price (USD per million tokens)"
value={draft.priceOutput}
onInput={(priceOutput) => edit({ ...draft, priceOutput })}
/>
<TextField
id="classifier-acp-price-cache-read"
label="cache read price (optional)"
value={draft.priceCacheRead}
onInput={(priceCacheRead) => edit({ ...draft, priceCacheRead })}
/>
<TextField
id="classifier-acp-price-cache-write"
label="cache write price (optional)"
value={draft.priceCacheWrite}
onInput={(priceCacheWrite) =>
edit({ ...draft, priceCacheWrite })
}
/>
</div>
<fieldset class="ui-classifier-settings-group">
<legend>provider</legend>
<div class="ui-classifier-settings-fields">
<div class="ui-classifier-settings-wide">
<TextField
id="classifier-acp-url"
label="URL"
value={draft.acpUrl}
placeholder="https://llm.example/v1"
onInput={(acpUrl) => edit({ ...draft, acpUrl })}
/>
</div>
<div class="ui-classifier-settings-wide">
<TextField
id="classifier-acp-model"
label="model"
value={draft.acpModel}
placeholder="Qwen/Qwen3-35B"
onInput={(acpModel) => edit({ ...draft, acpModel })}
/>
</div>
<TextField
id="classifier-acp-price-input"
label="input price"
value={draft.priceInput}
onInput={(priceInput) => edit({ ...draft, priceInput })}
/>
<TextField
id="classifier-acp-price-output"
label="output price"
value={draft.priceOutput}
onInput={(priceOutput) => edit({ ...draft, priceOutput })}
/>
<TextField
id="classifier-acp-price-cache-read"
label="cache read price (optional)"
value={draft.priceCacheRead}
onInput={(priceCacheRead) =>
edit({ ...draft, priceCacheRead })
}
/>
<TextField
id="classifier-acp-price-cache-write"
label="cache write price (optional)"
value={draft.priceCacheWrite}
onInput={(priceCacheWrite) =>
edit({ ...draft, priceCacheWrite })
}
/>
</div>
<p class="ui-classifier-settings-note">
Prices are in USD per million tokens.
</p>
</fieldset>
) : null}
{saveError ? (
<ApiErrorPanel