From a0cfefcd19ce0fc36d75e880d452707137ffa7ba Mon Sep 17 00:00:00 2001 From: Erwan Leboucher Date: Sat, 18 Jul 2026 16:03:22 +0200 Subject: [PATCH 1/2] fix: render typing indicator in-flow and stop scroll snapping to bottom --- src/app/features/room/RoomViewTyping.css.ts | 2 - src/app/features/room/RoomViewTyping.tsx | 144 ++++++++++---------- src/app/hooks/timeline/useTimelineSync.ts | 4 +- 3 files changed, 74 insertions(+), 76 deletions(-) diff --git a/src/app/features/room/RoomViewTyping.css.ts b/src/app/features/room/RoomViewTyping.css.ts index 5c90a178b8..d78bb19c13 100644 --- a/src/app/features/room/RoomViewTyping.css.ts +++ b/src/app/features/room/RoomViewTyping.css.ts @@ -17,8 +17,6 @@ export const RoomViewTyping = style([ width: '100%', backgroundColor: color.Surface.Container, color: color.Surface.OnContainer, - position: 'absolute', - bottom: 0, animation: `${SlideUpAnime} 100ms ease-in-out`, }, ]); diff --git a/src/app/features/room/RoomViewTyping.tsx b/src/app/features/room/RoomViewTyping.tsx index 98267fdd85..74dd6c9b62 100644 --- a/src/app/features/room/RoomViewTyping.tsx +++ b/src/app/features/room/RoomViewTyping.tsx @@ -47,79 +47,77 @@ export const RoomViewTyping = as<'div', RoomViewTypingProps>( }; return ( -
- - - - {typingNames.length === 1 && ( - <> - {typingNames[0]} - - {' is typing...'} - - - )} - {typingNames.length === 2 && ( - <> - {typingNames[0]} - - {' and '} - - {typingNames[1]} - - {' are typing...'} - - - )} - {typingNames.length === 3 && ( - <> - {typingNames[0]} - - {', '} - - {typingNames[1]} - - {' and '} - - {typingNames[2]} - - {' are typing...'} - - - )} - {typingNames.length > 3 && ( - <> - {typingNames[0]} - - {', '} - - {typingNames[1]} - - {', '} - - {typingNames[2]} - - {' and '} - - {typingNames.length - 3} others - - {' are typing...'} - - - )} - - - {chipIcon(X)} - - -
+ + + + {typingNames.length === 1 && ( + <> + {typingNames[0]} + + {' is typing...'} + + + )} + {typingNames.length === 2 && ( + <> + {typingNames[0]} + + {' and '} + + {typingNames[1]} + + {' are typing...'} + + + )} + {typingNames.length === 3 && ( + <> + {typingNames[0]} + + {', '} + + {typingNames[1]} + + {' and '} + + {typingNames[2]} + + {' are typing...'} + + + )} + {typingNames.length > 3 && ( + <> + {typingNames[0]} + + {', '} + + {typingNames[1]} + + {', '} + + {typingNames[2]} + + {' and '} + + {typingNames.length - 3} others + + {' are typing...'} + + + )} + + + {chipIcon(X)} + + ); } ); diff --git a/src/app/hooks/timeline/useTimelineSync.ts b/src/app/hooks/timeline/useTimelineSync.ts index 9aa923220f..67c02ea8d2 100644 --- a/src/app/hooks/timeline/useTimelineSync.ts +++ b/src/app/hooks/timeline/useTimelineSync.ts @@ -576,8 +576,10 @@ export function useTimelineSync({ !(isAtBottom || resetAutoScrollPending) || (!liveTimelineLinked && !resetAutoScrollPending) || eventsLength === 0 - ) + ) { + lastScrolledAtEventsLengthRef.current = eventsLength; return; + } if (eventsLength <= lastScrolledAtEventsLengthRef.current && !resetAutoScrollPending) return; From e212b9fce751adc7b9e0b19836bd9102d6a9d0ac Mon Sep 17 00:00:00 2001 From: Erwan Leboucher Date: Sat, 18 Jul 2026 16:07:14 +0200 Subject: [PATCH 2/2] chore: add changeset --- .changeset/fix-typing-indicator-scroll-snap.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/fix-typing-indicator-scroll-snap.md diff --git a/.changeset/fix-typing-indicator-scroll-snap.md b/.changeset/fix-typing-indicator-scroll-snap.md new file mode 100644 index 0000000000..4150ebc62e --- /dev/null +++ b/.changeset/fix-typing-indicator-scroll-snap.md @@ -0,0 +1,5 @@ +--- +default: patch +--- + +Show the typing indicator as its own row instead of an overlay so it no longer hides the last message, and stop the timeline from snapping to the bottom when you scroll back down after messages arrived off-screen.