@@ -11,8 +11,11 @@ import {
1111 PopoverItem ,
1212 PopoverScrollArea ,
1313 PopoverTrigger ,
14+ scrollFadeAttributes ,
15+ scrollFadeClass ,
1416 Tooltip ,
1517 Trash ,
18+ useScrollEdges ,
1619} from '@sim/emcn'
1720import { ArrowUp , CircleAlert , Download , MoreVertical , Paperclip , Square , X } from '@sim/emcn/icons'
1821import { createLogger } from '@sim/logger'
@@ -300,6 +303,7 @@ export function Chat() {
300303 const [ moreMenuOpen , setMoreMenuOpen ] = useState ( false )
301304
302305 const inputRef = useRef < HTMLInputElement > ( null )
306+ const attachmentsRef = useRef < HTMLDivElement > ( null )
303307 const timeoutRef = useRef < NodeJS . Timeout | null > ( null )
304308 const streamReaderRef = useRef < ReadableStreamDefaultReader < Uint8Array > | null > ( null )
305309 const preventZoomRef = usePreventZoom ( )
@@ -318,6 +322,9 @@ export function Chat() {
318322 handleDragLeave,
319323 handleDrop,
320324 } = useChatFileUpload ( )
325+ const attachmentEdges = useScrollEdges ( attachmentsRef , {
326+ enabled : isChatOpen && chatFiles . length > 0 ,
327+ } )
321328
322329 /**
323330 * Resolves the unified start block for chat execution, if available.
@@ -1084,10 +1091,19 @@ export function Chat() {
10841091 >
10851092 { /* File thumbnails */ }
10861093 { chatFiles . length > 0 && (
1087- < div className = 'mt-1 flex flex-wrap gap-1.5' >
1088- { chatFiles . map ( ( file ) => (
1089- < ChatFilePreview key = { file . id } file = { file } onRemove = { removeFile } />
1090- ) ) }
1094+ < div
1095+ ref = { attachmentsRef }
1096+ className = { cn (
1097+ 'mt-1 pointer-coarse:max-h-[102px] pointer-coarse:overflow-y-auto pointer-coarse:overscroll-contain' ,
1098+ scrollFadeClass
1099+ ) }
1100+ { ...scrollFadeAttributes ( attachmentEdges ) }
1101+ >
1102+ < div className = 'flex flex-wrap gap-1.5' >
1103+ { chatFiles . map ( ( file ) => (
1104+ < ChatFilePreview key = { file . id } file = { file } onRemove = { removeFile } />
1105+ ) ) }
1106+ </ div >
10911107 </ div >
10921108 ) }
10931109
0 commit comments