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:
parent
a9f0d61daa
commit
9b81af1fef
2 changed files with 78 additions and 46 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue