Skip to content

Commit 8c5f75b

Browse files
btuckerclaude
andcommitted
Fix pinned user message flashing when overlapping next prompt
The pinned message was flashing because hiding it changed offsetHeight to 0, which shifted the threshold calculations and caused unstable show/hide behavior. Fix by caching the pinned message height and using the cached value when the element is hidden. Also simplified the threshold logic to use a single pinnedAreaBottom value for both determining what to pin and detecting overlap. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent d1e51f5 commit 8c5f75b

File tree

1 file changed

+20
-9
lines changed

1 file changed

+20
-9
lines changed

src/claude_code_transcripts/templates/code_view.js

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,6 +1137,9 @@ async function init() {
11371137
return promptNum;
11381138
}
11391139

1140+
// Cache the pinned message height to avoid flashing when it's hidden
1141+
let cachedPinnedHeight = 0;
1142+
11401143
function updatePinnedUserMessage() {
11411144
if (!pinnedUserMessage || !transcriptContent || !transcriptPanel) return;
11421145
if (isInitializing || isScrollingToTarget) return; // Skip during scrolling to avoid repeated updates
@@ -1150,15 +1153,24 @@ async function init() {
11501153

11511154
const panelRect = transcriptPanel.getBoundingClientRect();
11521155
const headerHeight = transcriptPanel.querySelector('h3')?.offsetHeight || 0;
1153-
const pinnedHeight = pinnedUserMessage.offsetHeight || 0;
1154-
const topThreshold = panelRect.top + headerHeight + pinnedHeight + 10;
1156+
1157+
// Use cached height if pinned is hidden, otherwise update cache
1158+
if (pinnedUserMessage.style.display !== 'none') {
1159+
cachedPinnedHeight = pinnedUserMessage.offsetHeight || cachedPinnedHeight;
1160+
}
1161+
// Use a minimum height estimate if we've never measured it
1162+
const pinnedHeight = cachedPinnedHeight || 40;
1163+
1164+
// Threshold for when a message is considered "scrolled past"
1165+
const pinnedAreaBottom = panelRect.top + headerHeight + pinnedHeight;
11551166

11561167
let messageToPin = null;
11571168
let nextUserMessage = null;
11581169

11591170
for (const msg of userMessages) {
11601171
const msgRect = msg.getBoundingClientRect();
1161-
if (msgRect.bottom < topThreshold) {
1172+
// A message should be pinned if its bottom is above the pinned area
1173+
if (msgRect.bottom < pinnedAreaBottom) {
11621174
messageToPin = msg;
11631175
} else {
11641176
// This is the first user message that's visible
@@ -1167,13 +1179,12 @@ async function init() {
11671179
}
11681180
}
11691181

1170-
// Hide pinned if the next user message would overlap with the pinned area
1171-
// (i.e., its top is within the pinned header zone)
1172-
if (messageToPin && nextUserMessage) {
1182+
// Hide pinned if the next user message is entering the pinned area
1183+
// Use a small buffer to prevent flashing at the boundary
1184+
if (nextUserMessage) {
11731185
const nextRect = nextUserMessage.getBoundingClientRect();
1174-
const pinnedBottomThreshold = panelRect.top + headerHeight + pinnedHeight + 5;
1175-
if (nextRect.top < pinnedBottomThreshold) {
1176-
// Next user message is overlapping - hide the pinned
1186+
if (nextRect.top < pinnedAreaBottom) {
1187+
// Next user message is in the pinned area - hide the pinned
11771188
messageToPin = null;
11781189
}
11791190
}

0 commit comments

Comments
 (0)