From 40663373d4ccc4a58c60a57386ba7b127de1f9dc Mon Sep 17 00:00:00 2001 From: xavix-yo Date: Tue, 4 Aug 2026 23:01:36 +0100 Subject: [PATCH] fix: make the new-chat + menu visible and clickable The menu opened but never appeared: it was absolutely positioned inside .copilot-tabs, whose overflow-x: auto clips on both axes, so the dropdown was cut off inside the tab strip. And once visible, every click would have landed on the transparent full-screen overlay (z-index 99) above the menu (z-index 20), closing it instead of choosing an entry. Anchor the menu to the + button with fixed positioning (the same escape the model dropdown gets from living outside any clipping container) and raise it to z-index 100, above the overlay it shares with the other pills. --- web/components/copilot.js | 13 ++++++++++--- web/css/copilot.css | 6 ++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/web/components/copilot.js b/web/components/copilot.js index a046d7c..d719942 100644 --- a/web/components/copilot.js +++ b/web/components/copilot.js @@ -64,6 +64,7 @@ export class AppCopilot extends I18nMixin(ChatSession) { _activeSessionId: { state: true }, _newTabOpen: { state: true }, _newTabTargets: { state: true }, + _newTabAnchor: { state: true }, _renamingKey: { state: true }, _cmdMenu: { state: true }, _cmdSel: { state: true }, @@ -91,6 +92,7 @@ export class AppCopilot extends I18nMixin(ChatSession) { // be started on (General + the caller's projects), fetched on first open. this._newTabOpen = false; this._newTabTargets = null; + this._newTabAnchor = null; // Key of the tab being renamed inline, if any. this._renamingKey = null; this._onResizeMove = this._onResizeMove.bind(this); @@ -349,8 +351,12 @@ export class AppCopilot extends I18nMixin(ChatSession) { // ── The `+` menu ──────────────────────────────────────────────────────────── - async _toggleNewTab() { + async _toggleNewTab(e) { this._newTabOpen = !this._newTabOpen; + if (this._newTabOpen && e) { + const r = e.currentTarget.getBoundingClientRect(); + this._newTabAnchor = { top: r.bottom + 4, left: r.left }; + } if (!this._newTabOpen || this._newTabTargets) return; // General plus the caller's projects — the two things a chat can be *about*. // A project entry starts a second conversation there, with the coordinator @@ -649,12 +655,13 @@ export class AppCopilot extends I18nMixin(ChatSession) { ${this._tabs.map(tab => this._renderTab(tab))}
${this._newTabOpen ? html`
{ this._newTabOpen = false; }}>
-
+
${this._newTabTargets === null ? html`
${t('chat.new_tab.loading')}
` : this._newTabTargets.map(target => html` diff --git a/web/css/copilot.css b/web/css/copilot.css index 8c625f2..f0d748b 100644 --- a/web/css/copilot.css +++ b/web/css/copilot.css @@ -280,10 +280,8 @@ app-copilot[mode="full"] .copilot-msg { } .copilot-tab-menu { - position: absolute; - top: 100%; - left: 0; - z-index: 20; + position: fixed; + z-index: 100; min-width: 180px; max-height: 260px; overflow-y: auto;