Additional time before st.chat_message() method results in unexpected full-scroll from top

Summary

If there is additional processing time between the st.chat_input() method call and the st.chat_message() method call, there’s an unexpected full-scrolling effect during the screen refresh.

Steps to reproduce

This is taken from the conversational app example, with a minor change. I add a brief pause (0.05s) just before echoing the assistant’s echo response.

Code snippet:

import streamlit as st
import time

st.title("Echo Bot")

# Initialize chat history
if "messages" not in st.session_state:
    st.session_state.messages = []

# Display chat messages from history on app rerun
for message in st.session_state.messages:
    with st.chat_message(message["role"]):
        st.markdown(message["content"])

# React to user input
if prompt := st.chat_input("What is up?"):
    # Display user message in chat message container
    st.chat_message("user").markdown(prompt)
    # Add user message to chat history
    st.session_state.messages.append({"role": "user", "content": prompt})
    # simulate some type of processing time needed
    time.sleep(0.05)
    response = f"Echo: {prompt}"
    # Display assistant response in chat message container
    with st.chat_message("assistant"):
        st.markdown(response)
    # Add assistant response to chat history
    st.session_state.messages.append({"role": "assistant", "content": response})

If you run this as an app, and then send multiple inputs, at some point you’ll see the screen refresh, start at the top, and scroll all the way down. I use the following input, and it takes 3 submissions for the effect to occur. It doesn’t happen every submission. I also notice that the active focus shifts off the input box at the same time.

if prompt := st.chat_input("Seek knowledge..."): # Display user message in chat message container st.chat_message("user").markdown(prompt) # Add user message to chat history st.session_state.messages.append({"role": "user", "content": prompt}

Expected behavior:

I expect the chat_message container to scroll from its current place, down to accommodate the new input & response. And the active focus should stay on the input box.

This is the observed behavior when there is not a pause added.

Actual behavior:

Instead, after some number of input submissions (e.g., 3 or 4), you’ll see the screen refresh, start at the top, and scroll all the way down. The active focus also shifts off the input box.

Debug info

  • Streamlit version: 1.26.0
  • Python version: 3.10.10
  • Using pip
  • OS version: Debian 11
  • Browser version: I’ve experienced this on 116.0.5845.190 (Official Build) (64-bit) and Microsoft Edge 115.0.1901.200 (Official build) (64-bit)

Hey @amw5g,

Thanks for sharing this! I’m having trouble reproducing this behavior. Here’s a screen recording of what I see when I run that code snippet.

Freaky, @Caroline ! I just tried it again, and am still seeing the same effect. But clearly you’re not. The only difference I can think of is that my text is larger- both on input and on output. A coincidence? Maybe.

I’ve recorded a screen capture. You’ll see the effect with the 4th submission, and the 11th. In both cases you’ll see a brief scroll from the top and the focus leaves the input box.

Really appreciate you taking the time to test & reply. Even if we’re not seeing the same effect.