(null)
const [busy, setBusy] = useState(false)
@@ -156,13 +157,14 @@ export default function PresetsPage() {
const refreshList = () => {
api.listPresets().then((list) => {
setPresets(list)
+ setPresetsLoaded(true)
// 拉每个 preset 的 config 填表格列(best-effort,失败列显示 —)。
list.forEach((p) => {
api.getPreset(p.name)
.then((c) => setConfigCache((m) => ({ ...m, [p.name]: c })))
.catch(() => {})
})
- }).catch(() => setPresets([]))
+ }).catch(() => { setPresets([]); setPresetsLoaded(true) })
}
// ── 选 preset 切换 ──
@@ -228,14 +230,12 @@ export default function PresetsPage() {
// ── 首次拿到列表后:自动选最近一个,省一次「切换」点击 ──
const autoSelectedRef = useRef(false)
useEffect(() => {
- if (autoSelectedRef.current) return
- if (presets.length > 0 && selected === null) {
- autoSelectedRef.current = true
- setSelected(presets[0].name)
- } else if (presets.length === 0 && schema) {
- autoSelectedRef.current = true
- }
- }, [presets, selected, schema])
+ // Wait for the list itself: the schema can arrive first, and an empty
+ // list at that moment is "not loaded yet", not "no presets".
+ if (autoSelectedRef.current || !presetsLoaded) return
+ autoSelectedRef.current = true
+ if (presets.length > 0 && selected === null) setSelected(presets[0].name)
+ }, [presets, presetsLoaded, selected])
// 编辑器开着时 Esc 关闭(dirty 时仍可关 —— 改动留在内存,跟切 preset 一致)。
useEffect(() => {
@@ -632,7 +632,7 @@ export default function PresetsPage() {
| {cfgRank(c)} |
{cfgRes(c)} |
- {c?.optimizer_type ? schemaEnumLabel('optimizer_type', String(c.optimizer_type), t) : '—'} |
+ {c?.optimizer_type ? schemaEnumLabel('optimizer_type', String(c.optimizer_type), t) : '—'} |
{fmtUpdated(p.updated_at)} |
e.stopPropagation()}>
diff --git a/studio/web/src/styles/tokens.css b/studio/web/src/styles/tokens.css
index 2acb82e..04e00b7 100644
--- a/studio/web/src/styles/tokens.css
+++ b/studio/web/src/styles/tokens.css
@@ -202,12 +202,12 @@ select option:checked { background-color: var(--accent-soft); color: var(--accen
/* Button — Tailark Mist `buttonVariants`: h-9 px-4 rounded-md text-sm font-medium;
outline = bg-background ring-1 ring-foreground/10 shadow-sm; ghost = hover:bg-foreground/5 */
.btn {
- display: inline-flex; align-items: center; justify-content: center; gap: 8px;
- min-height: 36px;
- padding: 0 16px;
+ display: inline-flex; align-items: center; justify-content: center; gap: 7px;
+ min-height: 32px;
+ padding: 0 11px;
border-radius: var(--r-md);
border: 1px solid transparent;
- font-size: var(--t-sm); font-weight: 500;
+ font-size: 12.5px; font-weight: 500;
letter-spacing: -0.005em;
transition: background-color 200ms ease, border-color 200ms ease, color 200ms ease, box-shadow 200ms ease, filter 200ms ease, transform 200ms ease;
white-space: nowrap; line-height: 1.2;
@@ -217,7 +217,7 @@ select option:checked { background-color: var(--accent-soft); color: var(--accen
.btn:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--bg-surface), 0 0 0 4px var(--ring); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
.btn-primary {
- background: var(--accent-fill); color: var(--accent-fg); font-weight: 600;
+ background: var(--accent-fill); color: var(--accent-fg); font-weight: 600; padding: 0 14px;
}
.btn-primary:hover:not(:disabled) { background: var(--accent); }
.btn-secondary {
@@ -233,7 +233,7 @@ select option:checked { background-color: var(--accent-soft); color: var(--accen
.btn-danger:hover:not(:disabled) { background: #fbdcdc; }
.btn-warn { background: var(--warn-soft); color: var(--warn); box-shadow: inset 0 0 0 1px var(--warn-line); }
.btn-warn:hover:not(:disabled) { filter: brightness(0.95); }
-.btn-sm { min-height: 32px; padding: 0 12px; font-size: var(--t-sm); gap: 6px; }
+.btn-sm { min-height: 26px; padding: 0 10px; font-size: 12px; gap: 6px; }
.btn-xs { min-height: 24px; padding: 0 8px; font-size: var(--t-xs); font-weight: 500; border-radius: var(--r-sm); gap: 4px; }
/* Card — Tailark Mist `cardVariants.default`: bg-card rounded-xl shadow ring-1 ring-foreground/5 */
@@ -259,10 +259,9 @@ select option:checked { background-color: var(--accent-soft); color: var(--accen
.badge {
display: inline-flex; align-items: center; gap: 5px;
- font-family: var(--font-sans); font-size: var(--t-xs); font-weight: 500;
- padding: 1px 8px; border-radius: var(--r-pill); letter-spacing: 0;
- white-space: nowrap; line-height: 1.5;
- box-shadow: inset 0 0 0 1px var(--badge-line, transparent);
+ font-family: var(--font-sans); font-size: 11px; font-weight: 500;
+ min-height: 21px; padding: 0 9px; border-radius: var(--r-pill); letter-spacing: 0;
+ white-space: nowrap; line-height: 1.2;
}
.badge-ok { background: var(--ok-soft); color: var(--ok); --badge-line: var(--ok-line); }
.badge-warn { background: var(--warn-soft); color: var(--warn); --badge-line: var(--warn-line); }
@@ -285,8 +284,8 @@ select option:checked { background-color: var(--accent-soft); color: var(--accen
background: var(--bg-surface);
border: 1px solid var(--border-default);
border-radius: var(--r-md);
- padding: 7px 12px;
- font-size: var(--t-sm); line-height: 20px; color: var(--fg-primary);
+ padding: 6px 11px;
+ font-size: 12.5px; line-height: 18px; color: var(--fg-primary);
outline: none; width: 100%; min-width: 0;
box-shadow: var(--sh-sm);
transition: color 150ms ease, border-color 150ms ease, box-shadow 150ms ease;
@@ -294,7 +293,7 @@ select option:checked { background-color: var(--accent-soft); color: var(--accen
.input:focus { border-color: var(--ring); box-shadow: var(--ring-focus); }
.input:disabled { background: var(--bg-sunken); opacity: 0.6; cursor: not-allowed; }
.input::placeholder { color: var(--fg-tertiary); }
-.input-mono { font-family: var(--font-mono); font-size: var(--t-sm); letter-spacing: 0; }
+.input-mono { font-family: var(--font-mono); font-size: 11.5px; letter-spacing: 0; }
textarea.input { line-height: 1.55; }
/* Select — Tailark SelectTrigger: ChevronsUpDown icon at 50% opacity */
select.input {
|