Skip to content

Commit 2a37e85

Browse files
committed
fix(desktop): expand tool activity and solidify gateway menu
1 parent 76c2a2d commit 2a37e85

8 files changed

Lines changed: 91 additions & 17 deletions

File tree

desktop/garyx-desktop/src/renderer/src/GatewaySwitcher.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,9 @@ export function GatewayIdentityBar({
205205
</PopoverTrigger>
206206
<PopoverContent
207207
align="start"
208-
className="menu-popover-surface gateway-switcher-popover"
208+
className="menu-popover-surface menu-popover-surface-opaque gateway-switcher-popover"
209209
side="top"
210-
sideOffset={10}
210+
sideOffset={7}
211211
>
212212
<div className="gateway-switcher-list">
213213
{rows.list.map((profile) => (

desktop/garyx-desktop/src/renderer/src/menu-design-system.test.mjs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,15 @@ test('recipe pins every shared floating slot to the tokens', () => {
113113
]);
114114
expectRecipe(rules, "[data-slot='dropdown-menu-sub-content']", surfaceDeclarations);
115115
expectRecipe(rules, "[data-slot='select-content']", surfaceDeclarations);
116-
expectRecipe(rules, '.menu-popover-surface', surfaceDeclarations);
116+
expectRecipe(rules, '.menu-popover-surface', [
117+
'z-index: var(--z-app-floating)',
118+
...surfaceDeclarations,
119+
]);
120+
expectRecipe(
121+
rules,
122+
'.menu-popover-surface.menu-popover-surface-opaque',
123+
['background: var(--color-token-bg-primary)'],
124+
);
117125
expectRecipe(rules, "[data-slot='select-content'] [data-slot='select-viewport']", [
118126
'padding: var(--menu-surface-padding)',
119127
]);
@@ -212,8 +220,10 @@ test('retired per-surface menu forks stay deleted', () => {
212220
assert.ok(!taskForestCss.includes('#ececea'));
213221
const gatewaySwitcherSource = read('GatewaySwitcher.tsx');
214222
assert.ok(
215-
gatewaySwitcherSource.includes('menu-popover-surface gateway-switcher-popover'),
216-
'gateway popover opts into the shared surface marker',
223+
gatewaySwitcherSource.includes(
224+
'menu-popover-surface menu-popover-surface-opaque gateway-switcher-popover',
225+
),
226+
'gateway popover opts into the shared opaque surface marker',
217227
);
218228
assert.ok(
219229
gatewaySwitcherSource.includes('menu-item-two-line gateway-switcher-item'),

desktop/garyx-desktop/src/renderer/src/sidebar-footer-design.test.mjs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,14 @@ test('gateway and settings controls pin the Codex footer alignment', () => {
108108
expectRule(ownerCss, '.gateway-identity-gear:hover', [
109109
'background: var(--color-token-row-hover)',
110110
]);
111+
expectRule(ownerCss, '.gateway-switcher-popover', [
112+
'width: calc(var(--app-sidebar-width) - 16px)',
113+
'max-width: calc(100vw - 16px)',
114+
'padding: var(--menu-surface-padding)',
115+
]);
116+
117+
const source = read('GatewaySwitcher.tsx');
118+
assert.ok(source.includes('sideOffset={7}'));
111119
});
112120

113121
test('gateway identity keeps Codex icon scale while preserving status semantics', () => {

desktop/garyx-desktop/src/renderer/src/styles/gateway-status.css

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,12 @@
150150
}
151151

152152
.gateway-switcher-popover {
153-
/* Hug the identity bar below. Surface identity comes from the shared
154-
.menu-popover-surface recipe in styles/menus.css. */
155-
width: var(--radix-popover-trigger-width);
153+
/* Match Codex's bottom-left profile menu: span the complete footer row,
154+
preserve an 8px viewport gutter, and use the shared 4px surface inset. */
155+
width: calc(var(--app-sidebar-width) - 16px);
156+
max-width: calc(100vw - 16px);
156157
min-width: 208px;
157-
padding: 8px;
158+
padding: var(--menu-surface-padding);
158159
}
159160

160161
.gateway-switcher-list {

desktop/garyx-desktop/src/renderer/src/styles/menus.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
/* Menu-like popovers opt into the same surface with this marker class;
106106
the consumer keeps only widths, padding, and internal layout local. */
107107
.menu-popover-surface {
108+
z-index: var(--z-app-floating);
108109
border: 0;
109110
border-radius: var(--menu-surface-radius);
110111
background: var(--menu-surface-bg);
@@ -113,6 +114,13 @@
113114
color: var(--color-token-text-primary);
114115
}
115116

117+
/* Some persistent shell popovers sit directly over high-contrast sidebar
118+
content. Keep the Codex geometry/ring/shadow, but provide an opaque shared
119+
variant so labels underneath never bleed through the surface. */
120+
.menu-popover-surface.menu-popover-surface-opaque {
121+
background: var(--color-token-bg-primary);
122+
}
123+
116124
[data-slot='select-content'] [data-slot='select-viewport'] {
117125
padding: var(--menu-surface-padding);
118126
}

desktop/garyx-desktop/src/renderer/src/styles/turn-summary.css

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -284,10 +284,7 @@
284284
.tool-trace-group-list {
285285
display: grid;
286286
gap: 4px;
287-
max-height: 224px;
288-
overflow-x: hidden;
289-
overflow-y: auto;
290-
scrollbar-width: thin;
287+
overflow: visible;
291288
}
292289

293290
.tool-trace {
@@ -629,11 +626,8 @@
629626
.tool-trace-children-scroll {
630627
display: grid;
631628
gap: 4px;
632-
max-height: 112px;
633629
padding: 4px 4px 4px 6px;
634-
overflow-y: auto;
635-
padding-right: 20px;
636-
margin-right: -14px;
630+
overflow: visible;
637631
}
638632

639633
.tool-trace-children-scroll .tool-trace {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import test from 'node:test';
2+
import assert from 'node:assert/strict';
3+
import { readFileSync } from 'node:fs';
4+
import path from 'node:path';
5+
import { fileURLToPath } from 'node:url';
6+
7+
// Expanded Codex activity grows with its content and lets the transcript own
8+
// vertical scrolling. Nested scroll traps make completed commands and results
9+
// look truncated and are especially awkward with a trackpad.
10+
11+
const rendererDir = path.dirname(fileURLToPath(import.meta.url));
12+
const css = readFileSync(path.join(rendererDir, 'styles/turn-summary.css'), 'utf8');
13+
14+
function declarationsFor(selector) {
15+
const stripped = css.replace(/\/\*[\s\S]*?\*\//g, '');
16+
const rulePattern = /([^{}]+)\{([^{}]*)\}/g;
17+
let match;
18+
while ((match = rulePattern.exec(stripped)) !== null) {
19+
const selectors = match[1].split(',').map((part) => part.trim());
20+
if (selectors.includes(selector)) {
21+
return match[2]
22+
.split(';')
23+
.map((part) => part.trim())
24+
.filter(Boolean);
25+
}
26+
}
27+
assert.fail(`missing tool trace rule ${selector}`);
28+
}
29+
30+
test('expanded tool activity grows naturally without nested vertical scrolling', () => {
31+
for (const selector of ['.tool-trace-group-list', '.tool-trace-children-scroll']) {
32+
const declarations = declarationsFor(selector);
33+
assert.ok(
34+
declarations.includes('overflow: visible'),
35+
`${selector} must leave vertical scrolling to the transcript`,
36+
);
37+
assert.ok(
38+
declarations.every((declaration) => !declaration.startsWith('max-height:')),
39+
`${selector} must not cap expanded activity height`,
40+
);
41+
assert.ok(
42+
declarations.every((declaration) => !declaration.startsWith('overflow-y:')),
43+
`${selector} must not create a nested vertical scroller`,
44+
);
45+
}
46+
});

docs/agents/desktop-ui.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
- While a thread is still running, keep active turn containers stable and
1515
reserve Working/Worked rows for real tool activity from `render_state`.
1616
- Pure assistant/reasoning text remains normal assistant text.
17+
- Expanded tool activity grows to its natural height. The transcript owns
18+
vertical scrolling; tool groups and nested activity must not introduce
19+
max-height caps or inner vertical scrollbars.
1720
- Desktop interruption controls must be gateway-backed.
1821
- The local Mac app process may not own the active WebSocket for runs started
1922
elsewhere or after a reload; after trying any local active socket, call the
@@ -31,6 +34,10 @@
3134
typography, or hover washes.
3235
- Menu shortcut hints use the shared `DropdownMenuShortcut` component, not
3336
local spans.
37+
- Persistent sidebar popovers that sit over high-contrast navigation content
38+
may use the shared `.menu-popover-surface-opaque` variant. It changes only
39+
the surface fill; radius, ring, shadow, typography, rows, and spacing still
40+
come from `styles/menus.css`.
3441

3542
## App-Shell Chrome Ownership
3643

0 commit comments

Comments
 (0)