@@ -76,6 +76,22 @@ interface TranscriptProps {
76
76
welcomeContent ?: React . ReactNode
77
77
}
78
78
79
+ function useDebouncedBoolean ( value : boolean , delay : number ) : boolean {
80
+ const [ debouncedValue , setDebouncedValue ] = useState ( value )
81
+
82
+ useEffect ( ( ) => {
83
+ const handler = setTimeout ( ( ) => {
84
+ setDebouncedValue ( value )
85
+ } , delay )
86
+
87
+ return ( ) => {
88
+ clearTimeout ( handler )
89
+ }
90
+ } , [ value , delay ] )
91
+
92
+ return debouncedValue
93
+ }
94
+
79
95
export const Transcript : FC < TranscriptProps > = props => {
80
96
const {
81
97
activeChatContext,
@@ -105,6 +121,10 @@ export const Transcript: FC<TranscriptProps> = props => {
105
121
const [ scrollableContainer , setScrollableContainer ] = useState < HTMLDivElement | null > ( null )
106
122
const [ isAtBottom , setIsAtBottom ] = useState ( false )
107
123
124
+ // Debounce the isAtBottom state to prevent flickering of the "Skip to end" button
125
+ // when the mention menu appears and causes micro-scrolls
126
+ const isAtBottomDebounced = useDebouncedBoolean ( isAtBottom , 150 )
127
+
108
128
useEffect ( ( ) => {
109
129
const handleCopyEvent = ( event : ClipboardEvent ) => {
110
130
const selectedText = window . getSelection ( ) ?. toString ( ) || ''
@@ -266,7 +286,7 @@ export const Transcript: FC<TranscriptProps> = props => {
266
286
267
287
{ scrollableContainer && < ScrollbarMarkers scrollContainer = { scrollableContainer } /> }
268
288
269
- { ! isAtBottom && < ScrollDown onClick = { scrollTotheBottom } /> }
289
+ { ! isAtBottomDebounced && < ScrollDown onClick = { scrollTotheBottom } /> }
270
290
271
291
< div className = "tw-bg-[var(--vscode-input-background)]" >
272
292
{ inputInteractionAtTheBottom &&
0 commit comments