Skip to content

Conversation

@gadenbuie
Copy link
Collaborator

Scrolling to the bottom of the chat stream can be broken (or just generally wonky) when there are many tool requests/results in a message.

This happens generally because the scroll-to-bottom logic runs just after rendering the message content, at which point the tool request/results are still empty containers and haven't yet been rendered by lit, so the scrolling isn't quite in line with the bottom of the container, or can drift.

The fix in this PR is to emit a shiny-chat-maybe-scroll-to-bottom event when the request/result is firstUpdated(), i.e. when it is rendered in the DOM, which then calls into the same scroll to bottom logic that is used when the chat message is updated.

Example

Here's a small example app I've been using (the weather tool). Make the window height small and ask a question that leads to checking the weather in a few cities at once.

Example app
library(shiny)
library(bslib)
library(ellmer)
pkgload::load_all(here::here("pkg-r"))

get_weather_forecast <- tool(
  function(lat, lon, location_name) {
    lat <- unlist(lat)
    lon <- unlist(lon)
    location_name <- unlist(location_name)

    forecast <- weathR::point_tomorrow(lat, lon, short = FALSE)

    icon <- if (any(forecast$temp > 70)) {
      bsicons::bs_icon("sun-fill")
    } else if (any(forecast$temp < 45)) {
      bsicons::bs_icon("snow")
    } else {
      bsicons::bs_icon("cloud-sun-fill")
    }

    ContentToolResult(
      forecast,
      extra = list(
        display = list(
          title = paste("Weather Forecast for", location_name),
          icon = icon
        )
      )
    )
  },
  name = "get_weather_forecast",
  description = "Get the weather forecast for a location.",
  arguments = list(
    lat = type_number("Latitude"),
    lon = type_number("Longitude"),
    location_name = type_string("Name of the location for display to the user")
  ),
  annotations = tool_annotations(
    title = "Weather Forecast",
    icon = bsicons::bs_icon("cloud-sun")
  )
)

create_chat <- function() {
  chat <- chat_ollama(model = "granite4:tiny-h")
  chat$register_tool(get_weather_forecast)
  chat
}

ui <- page_fillable(
  card(
    chat_mod_ui("chat")
  )
)

server <- function(input, output, session) {
  chat_mod_server("chat", create_chat())
}

shinyApp(ui, server)

@gadenbuie gadenbuie requested a review from cpsievert November 19, 2025 21:27
@gadenbuie gadenbuie added this to the [R] v0.3.0 milestone Nov 19, 2025
@gadenbuie gadenbuie mentioned this pull request Nov 19, 2025
25 tasks
Copy link
Collaborator

@cpsievert cpsievert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thanks!

@gadenbuie gadenbuie merged commit 376cc57 into main Nov 20, 2025
16 checks passed
@gadenbuie gadenbuie deleted the fix/scroll-with-tool-results branch November 20, 2025 12:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants