Skip to content

Commit f2fa768

Browse files
authored
feat(quick-entry): glassmorphism redesign of the quick entry widget
Rebuilds the overlay chrome to the glass design spec while reusing the existing editor machinery (useTiptapEditor: chips, @-mentions, /skills, history, attachments) and task-creation flow. - Window: 920px wide (clamped to work area), panel top at ~26% of the screen, taller transparent window so autogrow + popovers don't clip; backdrop click dismisses. - Glass panel: smoke tint + 28px backdrop blur (code constants), hairline border, layered shadows, and an accent glow while the input is focused. - Accent follows mode: Plan is amber, agentic modes orange; drives caret, focus glow, mode label, selected menu items, and the send button. Vars live on <html> so portaled popovers inherit them. - Layout per spec: header row with mono repo/branch glass chips and a shortcut keycap (live binding); borderless 16px editor; attachment chip row; toolbar with paperclip, mode/model/effort glass pickers (adapter switch kept in the model menu), hint text, and a 30x30 accent send button. - Branch chip only selects a base branch (worktree mode); it never checks branches out from the overlay. Local mode shows the checked-out branch. - Submit shows an in-panel confirmation for 1.2s (new completeSubmit procedure dismisses and reveals the app afterwards; requestCreateTask no longer hides the overlay itself). - prefers-reduced-transparency falls back to an opaque gray-2 panel; prefers-reduced-motion drops the transitions. - ui: re-export EditorContent (editorSurface.ts) so host renderers build custom chrome on the same @tiptap/react instance. - dev: CDP port overridable via POSTHOG_CODE_CDP_PORT (Chrome squats 9222). Generated-By: PostHog Code Task-Id: 9f9e8d97-4bed-4d34-9681-685014ed68cc
1 parent d88866e commit f2fa768

8 files changed

Lines changed: 910 additions & 129 deletions

File tree

apps/code/src/main/bootstrap.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,13 @@ app.commandLine.appendSwitch("log-level", "0");
6060

6161
// In dev, expose the renderer over CDP (:9222) for the test-electron-app skill.
6262
// electron-vite launches Electron itself, so this is set in-process rather than
63-
// via a CLI flag.
63+
// via a CLI flag. Overridable because Chrome's debugger also defaults to 9222
64+
// and grabs it first when running.
6465
if (isDev) {
65-
app.commandLine.appendSwitch("remote-debugging-port", "9222");
66+
app.commandLine.appendSwitch(
67+
"remote-debugging-port",
68+
process.env.POSTHOG_CODE_CDP_PORT ?? "9222",
69+
);
6670
}
6771

6872
crashReporter.start({ uploadToServer: false });

apps/code/src/main/quick-entry-window.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,13 @@ const MAIN_WINDOW_VITE_NAME = "main_window";
1515
const __filename = fileURLToPath(import.meta.url);
1616
const __dirname = path.dirname(__filename);
1717

18-
const QUICK_ENTRY_WIDTH = 960;
19-
const QUICK_ENTRY_HEIGHT = 170;
20-
const QUICK_ENTRY_BOTTOM_MARGIN = 120;
18+
const QUICK_ENTRY_WIDTH = 920;
19+
// Window is taller than the visible glass panel: the transparent slack below
20+
// hosts dropdown popovers and the textarea's autogrow without clipping.
21+
const QUICK_ENTRY_HEIGHT = 520;
22+
const QUICK_ENTRY_MIN_SIDE_MARGIN = 32;
23+
// Panel top sits ~26% down the work area (Raycast-style), not bottom-docked.
24+
const QUICK_ENTRY_TOP_RATIO = 0.26;
2125

2226
let quickEntryWindow: BrowserWindow | null = null;
2327
let registeredAccelerator: string | null = null;
@@ -116,11 +120,17 @@ export function showQuickEntryWindow(): boolean {
116120
const cursor = screen.getCursorScreenPoint();
117121
const display = screen.getDisplayNearestPoint(cursor);
118122
const { x: dx, y: dy, width: dw, height: dh } = display.workArea;
119-
const x = Math.round(dx + (dw - QUICK_ENTRY_WIDTH) / 2);
120-
const y = Math.round(
121-
dy + dh - QUICK_ENTRY_HEIGHT - QUICK_ENTRY_BOTTOM_MARGIN,
123+
const width = Math.min(
124+
QUICK_ENTRY_WIDTH,
125+
dw - QUICK_ENTRY_MIN_SIDE_MARGIN * 2,
122126
);
123-
window.setPosition(x, y, false);
127+
const height = Math.min(QUICK_ENTRY_HEIGHT, dh);
128+
const x = Math.round(dx + (dw - width) / 2);
129+
const y = Math.round(dy + dh * QUICK_ENTRY_TOP_RATIO);
130+
// resizable:false blocks programmatic setBounds on macOS; lift it briefly.
131+
window.setResizable(true);
132+
window.setBounds({ x, y, width, height }, false);
133+
window.setResizable(false);
124134

125135
window.show();
126136
window.focus();

apps/code/src/main/services/quick-entry/service.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,10 +163,16 @@ export class QuickEntryService extends TypedEventEmitter<QuickEntryServiceEvents
163163
this.emit(QuickEntryServiceEvent.Hide, true);
164164
}
165165

166+
// Kicks off task creation in the main window but leaves the overlay up so
167+
// the renderer can show its confirmation state; the renderer then calls
168+
// completeSubmit() to dismiss and reveal the app.
166169
requestCreateTask(request: CreateTaskRequest): void {
170+
this.emit(QuickEntryServiceEvent.CreateTaskRequested, request);
171+
}
172+
173+
completeSubmit(): void {
167174
this.hide();
168175
showAndFocusMainWindow();
169-
this.emit(QuickEntryServiceEvent.CreateTaskRequested, request);
170176
}
171177

172178
async getRecentRepos(limit = 8): Promise<RecentRepoEntry[]> {

apps/code/src/main/trpc/routers/quick-entry.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ export const quickEntryRouter = router({
7676
getService().requestCreateTask(input);
7777
}),
7878

79+
completeSubmit: publicProcedure.mutation(() => {
80+
getService().completeSubmit();
81+
}),
82+
7983
getRecentRepos: publicProcedure
8084
.input(
8185
z.object({ limit: z.number().int().positive().optional() }).optional(),

0 commit comments

Comments
 (0)