+ {/* Sentinel element that sits just above the sticky title */}
+
+
-
+
{isSingleColumnLayout ?
From 515a52c1af01dacb6c6277e43d98173bd7ecb90d Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 15 Dec 2025 10:52:01 +0000
Subject: [PATCH 10/19] Fix subtitle visibility and remove side borders/shadows
Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com>
---
webviews/editorWebview/index.css | 35 +++++++-------------------------
1 file changed, 7 insertions(+), 28 deletions(-)
diff --git a/webviews/editorWebview/index.css b/webviews/editorWebview/index.css
index 9f13b21b75..3b3ce738c2 100644
--- a/webviews/editorWebview/index.css
+++ b/webviews/editorWebview/index.css
@@ -59,44 +59,24 @@ textarea:focus,
background: var(--vscode-editor-background);
}
-/* Shadow effect when stuck */
-.title::before {
+/* Shadow effect when stuck - only on bottom */
+.title.stuck::after {
content: '';
position: absolute;
- top: 0;
- left: -32px;
- right: -32px;
bottom: 0;
- background: var(--vscode-editor-background);
+ left: 0;
+ right: 0;
+ height: 1px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
- opacity: 0;
- transition: opacity 0.2s ease;
pointer-events: none;
- z-index: -1;
-}
-
-.title.stuck::before {
- opacity: 1;
}
/* Hide subtitle when stuck */
-.title .subtitle {
- transition: opacity 0.2s ease, max-height 0.2s ease;
- max-height: 100px;
- overflow: hidden;
-}
-
.title.stuck .subtitle {
- opacity: 0;
- max-height: 0;
- pointer-events: none;
+ display: none;
}
/* Adjust title size when stuck */
-.title .overview-title h2 {
- transition: font-size 0.2s ease;
-}
-
.title.stuck .overview-title h2 {
font-size: 18px;
}
@@ -1259,9 +1239,8 @@ code {
border-bottom: 1px solid var(--vscode-contrastBorder);
}
-.vscode-high-contrast .title.stuck::before {
+.vscode-high-contrast .title.stuck::after {
box-shadow: none;
- border: 1px solid var(--vscode-contrastBorder);
}
.vscode-high-contrast .diff .diffLine {
From 53ff457e944ad20eb396cd8b5dd7df62e328030e Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 15 Dec 2025 11:07:13 +0000
Subject: [PATCH 11/19] Fix subtitle visibility by adding flex: 1 to .details
Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com>
---
webviews/editorWebview/index.css | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/webviews/editorWebview/index.css b/webviews/editorWebview/index.css
index 3b3ce738c2..bcc1f03919 100644
--- a/webviews/editorWebview/index.css
+++ b/webviews/editorWebview/index.css
@@ -59,6 +59,10 @@ textarea:focus,
background: var(--vscode-editor-background);
}
+.title .details {
+ flex: 1;
+}
+
/* Shadow effect when stuck - only on bottom */
.title.stuck::after {
content: '';
From 3375693d5da45c8642251d330b0a2f251cebf2b1 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 15 Dec 2025 17:03:59 +0000
Subject: [PATCH 12/19] Fix IntersectionObserver to prevent stuck state on page
load
Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com>
---
webviews/editorWebview/overview.tsx | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/webviews/editorWebview/overview.tsx b/webviews/editorWebview/overview.tsx
index 5ccbc70278..5813c8f8e6 100644
--- a/webviews/editorWebview/overview.tsx
+++ b/webviews/editorWebview/overview.tsx
@@ -42,11 +42,13 @@ export const Overview = (pr: PullRequest) => {
return;
}
- // Use IntersectionObserver to detect when the sentinel leaves the viewport
- // This indicates the title is stuck
+ // Use IntersectionObserver to detect when the title becomes sticky
+ // The sentinel is positioned right above the title
+ // When sentinel scrolls out of view (top of viewport), title becomes stuck
const observer = new IntersectionObserver(
([entry]) => {
- // When sentinel is not intersecting, title is stuck
+ // When sentinel is visible, title hasn't become stuck yet
+ // When sentinel is not visible (scrolled past top), title is stuck
if (entry.isIntersecting) {
title.classList.remove('stuck');
} else {
@@ -54,8 +56,9 @@ export const Overview = (pr: PullRequest) => {
}
},
{
- threshold: [1],
- rootMargin: '0px'
+ // Use rootMargin to trigger slightly before reaching the top
+ rootMargin: '-1px 0px 0px 0px',
+ threshold: [1]
}
);
@@ -67,8 +70,8 @@ export const Overview = (pr: PullRequest) => {
}, []);
return <>
- {/* Sentinel element that sits just above the sticky title */}
-
+ {/* Sentinel element positioned just before the sticky title - must have height to be observable */}
+
From afd4627a390eb4f15301ac645e3de74e51aecd26 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 16 Dec 2025 10:54:10 +0000
Subject: [PATCH 13/19] Fix sentinel observer to use threshold 0 without
negative rootMargin
Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com>
---
webviews/editorWebview/overview.tsx | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/webviews/editorWebview/overview.tsx b/webviews/editorWebview/overview.tsx
index 5813c8f8e6..e0bc1e06a8 100644
--- a/webviews/editorWebview/overview.tsx
+++ b/webviews/editorWebview/overview.tsx
@@ -43,12 +43,12 @@ export const Overview = (pr: PullRequest) => {
}
// Use IntersectionObserver to detect when the title becomes sticky
- // The sentinel is positioned right above the title
- // When sentinel scrolls out of view (top of viewport), title becomes stuck
+ // The sentinel is positioned right before the title
+ // When sentinel is fully scrolled out of view (past the top), title becomes stuck
const observer = new IntersectionObserver(
([entry]) => {
- // When sentinel is visible, title hasn't become stuck yet
- // When sentinel is not visible (scrolled past top), title is stuck
+ // When sentinel is intersecting (visible), title is NOT stuck
+ // When sentinel is not intersecting (scrolled past top), title IS stuck
if (entry.isIntersecting) {
title.classList.remove('stuck');
} else {
@@ -56,9 +56,8 @@ export const Overview = (pr: PullRequest) => {
}
},
{
- // Use rootMargin to trigger slightly before reaching the top
- rootMargin: '-1px 0px 0px 0px',
- threshold: [1]
+ // No rootMargin - just detect when sentinel leaves viewport naturally
+ threshold: [0]
}
);
@@ -70,7 +69,7 @@ export const Overview = (pr: PullRequest) => {
}, []);
return <>
- {/* Sentinel element positioned just before the sticky title - must have height to be observable */}
+ {/* Sentinel element positioned just before the sticky title */}
From 863c9f497fe881db7187492371989087d0bf0728 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 16 Dec 2025 11:22:40 +0000
Subject: [PATCH 14/19] Explicitly remove stuck class on mount and use
threshold 1
Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com>
---
webviews/editorWebview/overview.tsx | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/webviews/editorWebview/overview.tsx b/webviews/editorWebview/overview.tsx
index e0bc1e06a8..f0b7b96971 100644
--- a/webviews/editorWebview/overview.tsx
+++ b/webviews/editorWebview/overview.tsx
@@ -42,9 +42,12 @@ export const Overview = (pr: PullRequest) => {
return;
}
+ // Initially ensure title is not stuck
+ title.classList.remove('stuck');
+
// Use IntersectionObserver to detect when the title becomes sticky
// The sentinel is positioned right before the title
- // When sentinel is fully scrolled out of view (past the top), title becomes stuck
+ // When sentinel scrolls out of view (past the top), title becomes stuck
const observer = new IntersectionObserver(
([entry]) => {
// When sentinel is intersecting (visible), title is NOT stuck
@@ -56,8 +59,9 @@ export const Overview = (pr: PullRequest) => {
}
},
{
- // No rootMargin - just detect when sentinel leaves viewport naturally
- threshold: [0]
+ // Use threshold 1 to only trigger when sentinel is fully visible/invisible
+ // This prevents false positives when sentinel is partially visible
+ threshold: [1]
}
);
From 030cf1ca0e8abb324edf0c9745936ac01c5cc901 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 16 Dec 2025 14:01:22 +0000
Subject: [PATCH 15/19] Replace IntersectionObserver with scroll-based position
detection
Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com>
---
webviews/editorWebview/overview.tsx | 43 ++++++++++++-----------------
1 file changed, 18 insertions(+), 25 deletions(-)
diff --git a/webviews/editorWebview/overview.tsx b/webviews/editorWebview/overview.tsx
index f0b7b96971..27802397fd 100644
--- a/webviews/editorWebview/overview.tsx
+++ b/webviews/editorWebview/overview.tsx
@@ -32,49 +32,42 @@ const useMediaQuery = (query: string) => {
export const Overview = (pr: PullRequest) => {
const isSingleColumnLayout = useMediaQuery('(max-width: 768px)');
const titleRef = React.useRef(null);
- const sentinelRef = React.useRef(null);
React.useEffect(() => {
- const sentinel = sentinelRef.current;
const title = titleRef.current;
- if (!sentinel || !title) {
+ if (!title) {
return;
}
// Initially ensure title is not stuck
title.classList.remove('stuck');
- // Use IntersectionObserver to detect when the title becomes sticky
- // The sentinel is positioned right before the title
- // When sentinel scrolls out of view (past the top), title becomes stuck
- const observer = new IntersectionObserver(
- ([entry]) => {
- // When sentinel is intersecting (visible), title is NOT stuck
- // When sentinel is not intersecting (scrolled past top), title IS stuck
- if (entry.isIntersecting) {
- title.classList.remove('stuck');
- } else {
- title.classList.add('stuck');
- }
- },
- {
- // Use threshold 1 to only trigger when sentinel is fully visible/invisible
- // This prevents false positives when sentinel is partially visible
- threshold: [1]
+ // Use scroll event to detect when title actually becomes sticky
+ // Check if the title's top position is at the viewport top (sticky position)
+ const handleScroll = () => {
+ const rect = title.getBoundingClientRect();
+ // Title is stuck when its top is at position 0 (sticky top: 0)
+ // Add small threshold to account for sub-pixel rendering
+ if (rect.top <= 1) {
+ title.classList.add('stuck');
+ } else {
+ title.classList.remove('stuck');
}
- );
+ };
+
+ // Check initial state after a brief delay to ensure layout is settled
+ const timeoutId = setTimeout(handleScroll, 100);
- observer.observe(sentinel);
+ window.addEventListener('scroll', handleScroll, { passive: true });
return () => {
- observer.disconnect();
+ clearTimeout(timeoutId);
+ window.removeEventListener('scroll', handleScroll);
};
}, []);
return <>
- {/* Sentinel element positioned just before the sticky title */}
-
From 99f5a0c2b49d25acc56a9c08df47e52f6b224dba Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 16 Dec 2025 14:04:28 +0000
Subject: [PATCH 16/19] Add requestAnimationFrame throttling and extract
threshold constant
Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com>
---
webviews/editorWebview/overview.tsx | 25 +++++++++++++++++--------
1 file changed, 17 insertions(+), 8 deletions(-)
diff --git a/webviews/editorWebview/overview.tsx b/webviews/editorWebview/overview.tsx
index 27802397fd..e6ac8a4471 100644
--- a/webviews/editorWebview/overview.tsx
+++ b/webviews/editorWebview/overview.tsx
@@ -43,16 +43,25 @@ export const Overview = (pr: PullRequest) => {
// Initially ensure title is not stuck
title.classList.remove('stuck');
- // Use scroll event to detect when title actually becomes sticky
+ // Small threshold to account for sub-pixel rendering
+ const STICKY_THRESHOLD = 1;
+
+ // Use scroll event with requestAnimationFrame to detect when title becomes sticky
// Check if the title's top position is at the viewport top (sticky position)
+ let ticking = false;
const handleScroll = () => {
- const rect = title.getBoundingClientRect();
- // Title is stuck when its top is at position 0 (sticky top: 0)
- // Add small threshold to account for sub-pixel rendering
- if (rect.top <= 1) {
- title.classList.add('stuck');
- } else {
- title.classList.remove('stuck');
+ if (!ticking) {
+ window.requestAnimationFrame(() => {
+ const rect = title.getBoundingClientRect();
+ // Title is stuck when its top is at position 0 (sticky top: 0)
+ if (rect.top <= STICKY_THRESHOLD) {
+ title.classList.add('stuck');
+ } else {
+ title.classList.remove('stuck');
+ }
+ ticking = false;
+ });
+ ticking = true;
}
};
From 8c2d4bba828f981380ff78fd6ac4558843f08ad6 Mon Sep 17 00:00:00 2001
From: Alex Ross <38270282+alexr00@users.noreply.github.com>
Date: Wed, 17 Dec 2025 10:36:03 +0100
Subject: [PATCH 17/19] reduce diff
---
src/@types/vscode.proposed.chatParticipantAdditions.d.ts | 1 -
src/@types/vscode.proposed.chatSessionsProvider.d.ts | 5 -----
2 files changed, 6 deletions(-)
diff --git a/src/@types/vscode.proposed.chatParticipantAdditions.d.ts b/src/@types/vscode.proposed.chatParticipantAdditions.d.ts
index aa7001a3d2..71520fa1ec 100644
--- a/src/@types/vscode.proposed.chatParticipantAdditions.d.ts
+++ b/src/@types/vscode.proposed.chatParticipantAdditions.d.ts
@@ -105,7 +105,6 @@ declare module 'vscode' {
isComplete?: boolean;
toolSpecificData?: ChatTerminalToolInvocationData;
fromSubAgent?: boolean;
- presentation?: 'hidden' | 'hiddenAfterComplete' | undefined;
constructor(toolName: string, toolCallId: string, isError?: boolean);
}
diff --git a/src/@types/vscode.proposed.chatSessionsProvider.d.ts b/src/@types/vscode.proposed.chatSessionsProvider.d.ts
index 772fc387b9..bd4e624430 100644
--- a/src/@types/vscode.proposed.chatSessionsProvider.d.ts
+++ b/src/@types/vscode.proposed.chatSessionsProvider.d.ts
@@ -95,11 +95,6 @@ declare module 'vscode' {
*/
description?: string | MarkdownString;
- /**
- * An optional badge that provides additional context about the chat session.
- */
- badge?: string | MarkdownString;
-
/**
* An optional status indicating the current state of the session.
*/
From 0d5f9a81b49938860fde1be64a06d1f2f5da1f24 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 17 Dec 2025 09:38:52 +0000
Subject: [PATCH 18/19] Hide edit title button when in sticky mode
Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com>
---
webviews/editorWebview/index.css | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/webviews/editorWebview/index.css b/webviews/editorWebview/index.css
index bcc1f03919..4cf451c172 100644
--- a/webviews/editorWebview/index.css
+++ b/webviews/editorWebview/index.css
@@ -80,6 +80,11 @@ textarea:focus,
display: none;
}
+/* Hide edit button when stuck */
+.title.stuck .overview-title button[title="Rename"] {
+ display: none;
+}
+
/* Adjust title size when stuck */
.title.stuck .overview-title h2 {
font-size: 18px;
From 86aa087ea5e94099d7d5c223b24044377e206994 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 17 Dec 2025 10:01:33 +0000
Subject: [PATCH 19/19] Use ID instead of title attribute for edit button
selector
Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com>
---
webviews/common/constants.ts | 5 +++++
webviews/components/header.tsx | 3 ++-
webviews/editorWebview/index.css | 2 +-
3 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/webviews/common/constants.ts b/webviews/common/constants.ts
index f556c0be96..55a0367153 100644
--- a/webviews/common/constants.ts
+++ b/webviews/common/constants.ts
@@ -7,3 +7,8 @@
* ID for the main comment textarea element in the PR description page.
*/
export const COMMENT_TEXTAREA_ID = 'comment-textarea';
+
+/**
+ * ID for the edit title button in the PR/Issue header.
+ */
+export const EDIT_TITLE_BUTTON_ID = 'edit-title-button';
diff --git a/webviews/components/header.tsx b/webviews/components/header.tsx
index 9418515e19..7b65839d49 100644
--- a/webviews/components/header.tsx
+++ b/webviews/components/header.tsx
@@ -11,6 +11,7 @@ import { copilotEventToStatus, CopilotPRStatus, mostRecentCopilotEvent } from '.
import { CopilotStartedEvent, TimelineEvent } from '../../src/common/timelineEvent';
import { GithubItemStateEnum, StateReason } from '../../src/github/interface';
import { CodingAgentContext, OverviewContext, PullRequest } from '../../src/github/views';
+import { EDIT_TITLE_BUTTON_ID } from '../common/constants';
import PullRequestContext from '../common/context';
import { useStateProp } from '../common/hooks';
@@ -129,7 +130,7 @@ function Title({ title, titleHTML, number, url, inEditMode, setEditMode, setCurr
{canEdit ?
-