Skip to content

Commit e37bbf4

Browse files
Improve scroll behavior and input styling
1 parent 36fb1c0 commit e37bbf4

2 files changed

Lines changed: 31 additions & 12 deletions

File tree

‎frontend/src/components/message/PromptInput.tsx‎

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ export function PromptInput({
486486

487487

488488
return (
489-
<div className="relative backdrop-blur-md bg-background opacity-95 border border-border rounded-xl p-2 md:p-3 mx-2 md:mx-4 mb-2 md:mb-5 w-[90%] md:max-w-4xl">
489+
<div className="relative backdrop-blur-md bg-background opacity-95 border border-border dark:border-white/30 rounded-xl p-2 md:p-3 md:mx-4 mb-2 md:mb-1 w-[95%] md:max-w-4xl">
490490
{hasActiveStream && (
491491
<div className="">
492492
<SessionStatusIndicator sessionID={sessionID} />
@@ -560,15 +560,13 @@ export function PromptInput({
560560
)}
561561
</div>
562562
<div className="flex items-center gap-1.5 md:gap-2 flex-shrink-0">
563-
{showScrollButton && (
564-
<button
563+
<button
565564
onClick={onScrollToBottom}
566-
className="p-1.5 md:p-2 rounded-lg bg-muted hover:bg-muted-foreground/20 text-muted-foreground hover:text-foreground transition-colors border border-foreground/30"
565+
className={`p-1.5 md:p-2 rounded-lg bg-muted hover:bg-muted-foreground/20 text-muted-foreground hover:text-foreground transition-colors border border-transparent ${showScrollButton ? 'border-foreground/30 visible' : 'invisible'}`}
567566
title="Scroll to bottom"
568567
>
569568
<ChevronDown className="w-5 h-5" />
570569
</button>
571-
)}
572570
{showStopButton && (
573571
<button
574572
onClick={handleStop}

‎frontend/src/hooks/useAutoScroll.ts‎

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,17 @@ export function useAutoScroll<T extends Message>({
3232
const userScrolledAtRef = useRef(0)
3333
const userDisengagedRef = useRef(false)
3434
const pointerStartYRef = useRef<number | null>(null)
35+
const onScrollStateChangeRef = useRef(onScrollStateChange)
36+
37+
onScrollStateChangeRef.current = onScrollStateChange
3538

3639
const scrollToBottom = useCallback(() => {
3740
if (!containerRef?.current) return
3841
userScrolledAtRef.current = 0
3942
userDisengagedRef.current = false
4043
containerRef.current.scrollTop = containerRef.current.scrollHeight
41-
onScrollStateChange?.(false)
42-
}, [containerRef, onScrollStateChange])
44+
onScrollStateChangeRef.current?.(false)
45+
}, [containerRef])
4346

4447
useEffect(() => {
4548
lastMessageCountRef.current = 0
@@ -49,14 +52,13 @@ export function useAutoScroll<T extends Message>({
4952
}, [sessionId])
5053

5154
useEffect(() => {
52-
if (!containerRef?.current) return
53-
54-
const container = containerRef.current
55+
const container = containerRef?.current
56+
if (!container) return
5557

5658
const markDisengaged = () => {
5759
userScrolledAtRef.current = Date.now()
5860
userDisengagedRef.current = true
59-
onScrollStateChange?.(true)
61+
onScrollStateChangeRef.current?.(true)
6062
}
6163

6264
const handlePointerDown = (e: PointerEvent) => {
@@ -85,13 +87,31 @@ export function useAutoScroll<T extends Message>({
8587
markDisengaged()
8688
}
8789
}
90+
91+
const handleScroll = () => {
92+
const { scrollTop, scrollHeight, clientHeight } = container
93+
const isAtBottom = scrollHeight - scrollTop - clientHeight < 50
94+
95+
if (isAtBottom) {
96+
if (userDisengagedRef.current) {
97+
userScrolledAtRef.current = 0
98+
userDisengagedRef.current = false
99+
onScrollStateChangeRef.current?.(false)
100+
}
101+
} else if (!userDisengagedRef.current) {
102+
userScrolledAtRef.current = Date.now()
103+
userDisengagedRef.current = true
104+
onScrollStateChangeRef.current?.(true)
105+
}
106+
}
88107

89108
container.addEventListener('pointerdown', handlePointerDown, { passive: true })
90109
container.addEventListener('pointermove', handlePointerMove, { passive: true })
91110
container.addEventListener('pointerup', handlePointerUp, { passive: true })
92111
container.addEventListener('pointercancel', handlePointerUp, { passive: true })
93112
container.addEventListener('wheel', handleWheel, { passive: true })
94113
container.addEventListener('keydown', handleKeyDown)
114+
container.addEventListener('scroll', handleScroll, { passive: true })
95115

96116
return () => {
97117
container.removeEventListener('pointerdown', handlePointerDown)
@@ -100,8 +120,9 @@ export function useAutoScroll<T extends Message>({
100120
container.removeEventListener('pointercancel', handlePointerUp)
101121
container.removeEventListener('wheel', handleWheel)
102122
container.removeEventListener('keydown', handleKeyDown)
123+
container.removeEventListener('scroll', handleScroll)
103124
}
104-
}, [containerRef, onScrollStateChange])
125+
}, [containerRef, sessionId, messages])
105126

106127
useEffect(() => {
107128
if (!containerRef?.current || !messages) return

0 commit comments

Comments
 (0)