fix: the stats bar's controls were dead — pointer-events + button affordance
Live-driving the real browser caught it (the user's report: "they don't work as buttons"): the stats row sits OUTSIDE the composer shell's pointer-events-auto div, inside the sticky scroll wrapper's pointer-events-none — every control on the row was unclickable, including the pre-existing stats-detail popover button. The row now re-enables pointer-events itself. Also, per the user's sizing note: bar text 10px → 11px with a touch more breathing room, and the model + thinking controls gain quiet pill affordance (rounded-full border, card bg, ▾ chevron) — still muted by design, but visibly buttons. Verified live end-to-end in the browser: click opens the model menu ABOVE (366 rows, search autofocused), "qwen flash" narrows to 5, picking qwen3.8-flash persists + flips the label, the thinking menu shows exactly that model's supported levels (Off/Minimal/Low/Medium/High), Medium persists on the record via PUT, labels update. Test session settings restored after the drive. Gates 350/350.
This commit is contained in:
@@ -157,9 +157,10 @@ export function ModelControl({
|
||||
}}
|
||||
aria-expanded={open === "model"}
|
||||
title="Conversation model — applies next turn"
|
||||
className="flex items-center gap-1 transition-colors hover:text-foreground"
|
||||
className="flex items-center gap-1.5 rounded-full border border-border/60 bg-card/70 px-2.5 py-1 transition-colors hover:border-border hover:bg-muted"
|
||||
>
|
||||
<span>{effectiveId ? prettyModel(effectiveId) : "—"}</span>
|
||||
<span className="text-card-foreground">{effectiveId ? prettyModel(effectiveId) : "—"}</span>
|
||||
<span aria-hidden className="text-[9px] text-muted-foreground">▾</span>
|
||||
</button>
|
||||
<span aria-hidden>·</span>
|
||||
<button
|
||||
@@ -171,11 +172,12 @@ export function ModelControl({
|
||||
}}
|
||||
aria-expanded={open === "thinking"}
|
||||
title="Thinking level — applies next turn"
|
||||
className="flex items-center gap-1 transition-colors hover:text-foreground"
|
||||
className="flex items-center gap-1.5 rounded-full border border-border/60 bg-card/70 px-2.5 py-1 transition-colors hover:border-border hover:bg-muted"
|
||||
>
|
||||
<span>
|
||||
<span className="text-card-foreground">
|
||||
{effectiveLevel === undefined ? "Thinking —" : `Thinking: ${LEVEL_LABEL[effectiveLevel] ?? effectiveLevel}`}
|
||||
</span>
|
||||
<span aria-hidden className="text-[9px] text-muted-foreground">▾</span>
|
||||
</button>
|
||||
|
||||
{open === "model" && (
|
||||
|
||||
@@ -44,7 +44,11 @@ export function StatsBar({
|
||||
return (
|
||||
<div
|
||||
data-testid="stats-bar"
|
||||
className="relative flex items-center justify-between gap-3 px-3 pt-1 text-[10px] text-muted-foreground"
|
||||
// pointer-events-auto: the sticky composer wrapper is pointer-events-none
|
||||
// (so its transparent gradient area never blocks scrolling) — this row
|
||||
// must re-enable events or every control on it is dead (the model-
|
||||
// control wave caught this live: buttons rendered, clicks never landed).
|
||||
className="pointer-events-auto relative flex items-center justify-between gap-3 px-3 pt-1.5 text-[11px] text-muted-foreground"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -35,8 +35,11 @@ describe("stats bar", () => {
|
||||
assert.match(html, /data-testid="stats-context">—</);
|
||||
assert.match(html, /data-testid="stats-cost">—</);
|
||||
// no turns, no settings, catalog not loaded → both control labels "—"
|
||||
assert.match(html, /data-testid="stats-model"[^>]*><span>—<\/span>/);
|
||||
assert.match(html, /data-testid="stats-model"[^>]*>\s*<span[^>]*>—<\/span>/);
|
||||
assert.match(html, /Thinking —</);
|
||||
// the control reads as a button: pill border + dropdown chevron
|
||||
assert.match(html, /data-testid="stats-model"[^>]*rounded-full[^>]*>/);
|
||||
assert.match(html, /▾/);
|
||||
});
|
||||
|
||||
it("folds context + cost from the turns log (core/prices, no local math)", () => {
|
||||
@@ -51,7 +54,7 @@ describe("stats bar", () => {
|
||||
assert.match(html, /data-testid="stats-cost">\$0\.0020</);
|
||||
// model button label falls back to the last turn's actual model
|
||||
// (the catalog + settings are what drive it once loaded)
|
||||
assert.match(html, /data-testid="stats-model"[^>]*><span>Glm 5\.3 Flash<\/span>/);
|
||||
assert.match(html, /data-testid="stats-model"[^>]*>\s*<span[^>]*>Glm 5\.3 Flash<\/span>/);
|
||||
});
|
||||
|
||||
it("shows — for cost when every turn is unpriceable, never a fake $0", () => {
|
||||
|
||||
Reference in New Issue
Block a user