Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions webviews/src/agent-session/acpmux/composerStates.css
Original file line number Diff line number Diff line change
Expand Up @@ -279,12 +279,27 @@ button.acpmux-send:disabled:not(.acpmux-cancel):not(.acpmux-send-ready) {
(Lawrence, Leo 10-14): the same one-device-pixel rim, never a wider ring or the accent, and clear
with appearance.borders none. Its tone steps 30% toward the text (--acpmux-composer-edge-focus):
the earlier 8% step was below what an eye can see, so a focused composer was pixel-identical to an
idle one in every theme (cg-composer focus audit, 10-14). The card's rim goes round the location
idle one in every theme (cg-composer focus audit, 10-14). Leo 2026-10-19 asked for a subtler focus,
so it steps 22%: still well clear of the invisible 8%. Over art the glass card also catches more
light on its top edge (below). The card's rim goes round the location
strip too (composerLocation.css), so the focused rim stays one outline. Shell mode takes its own accent,
the mode's mark. The prompt itself draws no ring (desktop.css, cx-ncc.57). */
.acpmux-composer,
.nt-composer {
--acpmux-composer-edge-focus: color-mix(in srgb, var(--agent-text) 30%, var(--acpmux-composer-edge));
--acpmux-composer-edge-focus: color-mix(in srgb, var(--agent-text) 22%, var(--acpmux-composer-edge));
}
/* Glass focus: over art (data-cmux-see-through) a focused card's top-lit rim (#21786) brightens, as
light catches a lifted pane of glass, instead of the ring growing heavier. Reduce Transparency
draws no rim layer at all (above), so it keeps the plain step. */
:root[data-cmux-see-through]
:is(
.acpmux-composer-box:has(:focus-visible),
.acpmux-composer:has(> .acpmux-composer-strip :focus-visible) > .acpmux-composer-box
) {
--acpmux-composer-rim: inset 0 1px 0 light-dark(
Comment on lines +294 to +299

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Focus ignores borders off

With data-cmux-see-through and data-borders="none", keyboard focus still brightens the composer's top edge. The border setting clears --acpmux-card-ring and --acpmux-composer-edge-focus, but this new rule changes a separate shadow layer. Exclude data-borders="none" from this rule so focusing the card respects the user's border setting.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaving this as is on purpose. borders none doesn't clear the glass card's top-lit rim at rest either; it's the glass highlight, not a border. With borders none the focus ring is already transparent, so over art this brightening is the only visible keyboard focus cue. Dropping it would leave a focused composer identical to an idle one.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That context makes sense. Since --acpmux-composer-rim is the glass highlight and remains present at rest, data-borders="none" clearing only --acpmux-card-ring and the focus tone is intentional. Removing this override would make keyboard focus indistinguishable from idle over art, so the brightened top rim is a valid remaining focus cue rather than a border violation. I’m withdrawing this finding.

color-mix(in srgb, var(--cmux-tone-light) 85%, transparent),
color-mix(in srgb, var(--cmux-tone-light) 22%, transparent)
);
}
:root[data-borders="none"] :is(.acpmux-composer, .nt-composer) {
--acpmux-composer-edge-focus: transparent;
Expand Down
21 changes: 19 additions & 2 deletions webviews/test/composer-rim-hairline.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ import { warmViteServer } from "./support/warmDevServer";
type Inset = { spread: number; alpha: number };

await requireBrowserLane("composer-rim-hairline.test.ts", async () => {
/** The composer edge's alpha over this page's transparent background, and its quiet focus step: 30% text over the edge. */
/** The composer edge's alpha over this page's transparent background, and its quiet focus step: 22% text over the edge
* (Leo 2026-10-19, a subtler focus; still well past the 8% step an eye could not see). */
const EDGE = 0.18;
const FOCUS = 0.3 + 0.7 * EDGE;
const FOCUS = 0.22 + 0.78 * EDGE;
setDefaultTimeout(120_000);
try {
await (await chromium.launch({ headless: true })).close();
Expand Down Expand Up @@ -160,6 +161,22 @@ await requireBrowserLane("composer-rim-hairline.test.ts", async () => {
await page.close();
});

// Over art the focused glass card catches more light on its top edge (the glass rim, #21786), in
// place of a heavier ring: the ring keeps its one-device-pixel quiet step.
test("over art keyboard focus brightens the glass card's top-lit rim", async () => {
const page = await open(2);
await page.evaluate(() => document.documentElement.setAttribute("data-cmux-see-through", ""));
const topRim = async () => (await insets(page, "composer")).find(({ spread }) => spread === 0)?.alpha ?? 0;
const rest = await topRim();
expect(rest, "the glass card draws its top-lit rim").toBeGreaterThan(0);
await page.focus("#composer-field");
expect(await topRim(), "focus brightens the top-lit rim").toBeGreaterThan(rest);
const ring = (await insets(page, "composer")).filter(({ spread }) => spread > 0);
expect(ring.length, "one ring").toBe(1);
expect(ring[0]?.alpha, "the ring keeps the quiet focus step").toBeCloseTo(FOCUS, 2);
await page.close();
});

test("pointer focus leaves the composer rim quiet while keyboard traversal raises it", async () => {
const page = await open(2);
const rest = await insets(page, "composer");
Expand Down