From b1106b98f3ddeb2ecd6ea13e6c2febe38b4fd5d1 Mon Sep 17 00:00:00 2001
From: yhh <359807859@qq.com>
Date: Thu, 5 Nov 2026 22:50:10 -0800
Subject: [PATCH] fix(studio): settings number fields get a visible box, and
the slash menu lays its rows out on one line as the composer board does
---
desktop/frontend-next/src/design/composer.css | 9 +++++++++
desktop/frontend-next/src/design/settings.css | 5 ++++-
.../src/ui/Completion.highlight.interaction.test.tsx | 6 ++++++
desktop/frontend-next/src/ui/Completion.tsx | 1 +
4 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/desktop/frontend-next/src/design/composer.css b/desktop/frontend-next/src/design/composer.css
index 5765f0bb07..0ccfea817c 100644
--- a/desktop/frontend-next/src/design/composer.css
+++ b/desktop/frontend-next/src/design/composer.css
@@ -150,3 +150,12 @@
.composition-menu button.mi { box-sizing: border-box; width: calc(100% - 8px); margin: 0 4px 2px; padding: 7px 10px; }
.composition-menu button.mi .lb { line-height: 1.4; }
.composition-menu button.mi .ds { margin-top: 1px; font: var(--w-reg) var(--fs-meta)/1.45 var(--ui); }
+.slashmenu { max-width: 420px; max-height: 300px; padding: 4px; border-radius: var(--r-md); }
+.slashmenu .mi { min-height: 30px; padding: 4px 8px; border-radius: var(--r-sm); align-items: center; }
+.slashmenu .mi .dot { display: none; }
+.slashmenu .mi .tx { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 12px; }
+.slashmenu .mi .lb { flex: none; min-width: 84px; font: var(--w-semi) var(--fs-micro) var(--mono); }
+.slashmenu .mi .ds { flex: 1; min-width: 0; margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: var(--w-reg) var(--fs-ui)/1.4 var(--ui); }
+.slashmenu .mi .ds ~ .ds { flex-basis: 100%; padding-left: 96px; font-size: var(--fs-meta); color: var(--faint); }
+.slashmenu .mi[data-on]::before { content: none; }
+.slashmenu .mi[data-kind="builtin"] .rt, .slashmenu .mi[data-kind="file"] .rt, .slashmenu .mi[data-kind="dir"] .rt { display: none; }
diff --git a/desktop/frontend-next/src/design/settings.css b/desktop/frontend-next/src/design/settings.css
index 9f6c6d2718..1eb286c219 100644
--- a/desktop/frontend-next/src/design/settings.css
+++ b/desktop/frontend-next/src/design/settings.css
@@ -376,7 +376,10 @@
.prefs-icon:disabled { opacity: .5; cursor: default; }
.prefs-icon:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.prefs-icon .studio-icon { width: 16px; height: 16px; }
-.prefs-card .unit-field { align-items: center; gap: 8px; border: 0; background: none; }
+.prefs-card .unit-field { align-items: center; gap: 6px; height: 28px; padding: 0 10px 0 2px; border: 1px solid var(--hair); border-radius: var(--r-sm); background: transparent; }
+.prefs-card .unit-field input { width: 64px; text-align: right; font: var(--w-reg) var(--fs-meta) var(--mono); }
+.prefs-card .threshold-control { width: auto; justify-content: flex-start; }
+.prefs-card .threshold-control .unit-field { flex: none; }
.prefs-card .unit-field > i { padding: 0; border: 0; color: var(--faint); font: var(--w-reg) var(--fs-meta) var(--ui); font-style: normal; }
.prefs-sheet[data-solo="usage"] .prefs-hd h1 { font-size: var(--fs-display); font-weight: var(--w-semi); }
.usage .uranges button { font: var(--w-reg) var(--fs-meta) var(--ui); }
diff --git a/desktop/frontend-next/src/ui/Completion.highlight.interaction.test.tsx b/desktop/frontend-next/src/ui/Completion.highlight.interaction.test.tsx
index 7b0ea9a50c..d6a6d8530f 100644
--- a/desktop/frontend-next/src/ui/Completion.highlight.interaction.test.tsx
+++ b/desktop/frontend-next/src/ui/Completion.highlight.interaction.test.tsx
@@ -57,3 +57,9 @@ it.each(["ref", "slash"] as const)("keeps %s navigation made as soon as the rows
await act(async () => { render(); });
expect(screen.getByRole("status").textContent).toBe("second");
});
+
+it("tags each row with its kind so the list can leave the obvious ones unlabelled", () => {
+ render( {}} onHover={() => {}}
+ items={[{ label: "/compact", insert: "/compact", kind: "builtin" }, { label: "/review", insert: "/review", kind: "subagent" }]} />);
+ expect(screen.getAllByRole("option").map((o) => o.getAttribute("data-kind"))).toEqual(["builtin", "subagent"]);
+});
diff --git a/desktop/frontend-next/src/ui/Completion.tsx b/desktop/frontend-next/src/ui/Completion.tsx
index a3b4f9bda2..cd7e36963a 100644
--- a/desktop/frontend-next/src/ui/Completion.tsx
+++ b/desktop/frontend-next/src/ui/Completion.tsx
@@ -276,6 +276,7 @@ export function CompletionMenu({ id, items, active, kind, query, kb, onPick, onH
role="option"
aria-selected={i === active}
data-on={i === active ? "" : undefined}
+ data-kind={it.kind}
tabIndex={-1}
onMouseMove={() => onHover(i)}
// mousedown, not click: the textarea must not lose focus first.