Skip to content

Expose isAtEnd from KeyboardChatScrollView for jump-to-latest and follow-mode UIs #1430

@jkinggg

Description

@jkinggg

Is your feature request related to a problem? Please describe.

KeyboardChatScrollView already computes whether the scroll view is effectively at the end for keyboardLiftBehavior="whenAtEnd", but that state is currently internal.

For chat-style UIs, apps often need the same signal for:

  • showing or hiding a "scroll to bottom" / "jump to latest" button
  • enabling follow-mode while streaming new assistant content
  • tracking whether unread content is accumulating below the viewport

Today the app has to re-implement that logic outside the component. That is awkward because KeyboardChatScrollView already owns the relevant scroll metrics and keyboard-aware padding behavior, so app-side heuristics can drift from the component's internal definition of "at end".

Describe the solution you'd like

Expose an optional isAtEnd?: SharedValue<boolean> prop on KeyboardChatScrollView.

When provided, the component would update that shared value on the UI thread using the same internal scroll metrics and isScrollAtEnd(...) logic it already uses for keyboardLiftBehavior="whenAtEnd".

Example:

const isAtEnd = useSharedValue(true);

<KeyboardChatScrollView
  isAtEnd={isAtEnd}
  keyboardLiftBehavior="whenAtEnd"
/>

This keeps the public API narrow while still exposing the high-level state chat apps actually need.

Describe alternatives you've considered

  1. Expose raw scroll position instead.

I think that is a less ideal API for this use case. Most consumers do not need raw scrollY; they need the semantic "is the user pinned to the latest content?" state. Exposing raw scroll metrics also leaks more implementation detail and pushes more edge-case handling into app code.

  1. Recompute "at end" in the app.

This works imperfectly, especially once keyboard lift behavior, bottom padding, composer growth, and inverted/non-inverted behavior are involved. The component already has the authoritative inputs, so surfacing that result is more reliable.

  1. Expose a callback instead of a shared value.

A callback is usable, but a SharedValue<boolean> fits the existing Reanimated-driven API surface better and avoids bouncing this state back to JS for consumers that want to animate directly from it.

Additional context

  • This would be an additive API change.
  • The implementation can be JS-only in KeyboardChatScrollView.
  • Internally, the component already has everything needed: scroll, layout, size, and isScrollAtEnd(...).
  • This is especially helpful for AI chat and messenger-style screens that need a jump-to-latest button that stays in sync with the component's own whenAtEnd behavior.

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions