Comma Agents
@comma-agents/tuiComponents

ScrollableView

Variable-height scrollable container with per-row measurement, mouse-wheel scrolling, and sticky-to-bottom behavior.

ScrollableView

A lower-level scrollable container that handles layout, measurement, mouse-wheel scrolling, and scroll offset management. Each row is individually measured via Ink's layout engine, supporting variable-height content. ScrollableView has no keyboard input -- add that with ScrollableList.

import { ScrollableView } from "@comma-agents/tui";

<ScrollableView
  items={messages}
  getKey={(msg) => msg.id}
  renderItem={(msg, index) => <Text>{msg.text}</Text>}
  stickToBottom={true}
  onScrollChange={(state) => console.log(state.rowOffset)}
/>

ScrollableViewProps

PropTypeDefaultDescription
itemsreadonly ItemType[]--Items to render
getKey(item, index) => string--Unique key for each item
renderItem(item, index) => ReactNode--Render function
getRowHeight(item, index, viewportWidth) => number1Fallback height estimate before measurement
scrollToRownumber--Scroll so this row index is visible
stickToBottombooleanfalsePin to bottom on new content
onScrollChange(state: ScrollableViewState) => void--Called when scroll state changes
emptyTextstring"No items."Empty state text

ScrollableViewState

FieldTypeDescription
rowOffsetnumberCurrent top offset in terminal rows
totalRowsnumberTotal content height in rows
viewportRowsnumberMeasured viewport height in rows
atBottombooleanWhether rowOffset is at the maximum valid value

Sticky-to-Bottom

When stickToBottom is true, the view auto-pins to the bottom when new content arrives. It automatically disengages when the user scrolls up with the mouse wheel and re-engages when they scroll back to the bottom edge.

Mouse Wheel

Mouse wheel scrolls by 3 rows per tick. Only scroll events inside the viewport bounding box are handled. A Scrollbar component is rendered when totalRows > viewportRows.

On this page