Replies: 1 comment 1 reply
-
Using the This has the nice side effect of allowing your users to scroll up in the messages without automatically scrolling back down when a new message arrives, but re-enabling the auto scroll to bottom if they do scroll it back down to the latest message. It has one unfortunate side effect of a tiny little jitter when initially scrolling up, because the component will try to scroll back down the first time the hidden div goes out of view, even when this is initiated by user action. pip install 'reflex-intersection-observer>=0.0.2' import asyncio
import reflex as rx
from reflex_intersection_observer import intersection_observer
BOTTOM_ELEMENT_ID = "bottom"
class ScrollHandlingState(rx.State):
def scroll_to_bottom(self):
return rx.call_script(f"document.getElementById('{BOTTOM_ELEMENT_ID}').scrollIntoView()")
def handle_non_intersect(self, _entry):
return self.scroll_to_bottom()
class MessageGenerator(rx.State):
messages: list[str]
should_load: bool = False
def on_load(self):
self.messages = ["Hello, world!"]
self.should_load = True
return MessageGenerator.add_messages
@rx.background
async def add_messages(self):
while self.should_load:
async with self:
self.messages.append(f"New message {len(self.messages) + 1}!")
if not self.should_load:
break
await asyncio.sleep(3)
def message_control_button():
return rx.cond(
MessageGenerator.should_load,
rx.button("Stop", on_click=MessageGenerator.set_should_load(False)),
rx.button("Start", on_click=[MessageGenerator.set_should_load(True), MessageGenerator.add_messages]),
)
def index() -> rx.Component:
return rx.vstack(
rx.heading("Messages"),
rx.hstack(
message_control_button(),
rx.icon_button(
rx.icon("arrow_down_to_line"),
on_click=ScrollHandlingState.scroll_to_bottom,
),
),
rx.scroll_area(
rx.vstack(
rx.foreach(MessageGenerator.messages, rx.text),
intersection_observer(
height="1px",
id=BOTTOM_ELEMENT_ID,
root="#scroller",
on_non_intersect=ScrollHandlingState.handle_non_intersect,
visibility="hidden",
),
),
id="scroller",
width="90vw",
height="100px",
),
rx.text("This is outside scroll area"),
align="center",
)
app = rx.App()
app.add_page(index, on_load=MessageGenerator.on_load) Screen.Recording.2024-03-13.at.12.58.34.movThe jittering could be fixed with another state var that tracks whether a new message has arrived and only calling |
Beta Was this translation helpful? Give feedback.
-
@luka
on discord asks:Beta Was this translation helpful? Give feedback.
All reactions