termino

ScrollBox

A scrollable container that supports horizontal and vertical scrolling, sticky scroll behavior, viewport culling, and customizable scrollbars.

~/components/scrollbox — wheel or buttons
live
$ termino scrollbox-demo — scroll with wheel
┌──────────────────────────────────────────────┐
050service log line 50
051service log line 51
052service log line 52
053service log line 53
054service log line 54
055service log line 55
056build ok ✓
057deploy started
058pushing image…
059live on port 3000
└──────────────────────────────────────────────┘
scrollTop 50
sticky ON (bottom)
event stickyScroll: bottom

##Renderable API

tsrenderable
1import { ScrollBoxRenderable, BoxRenderable, createCliRenderer } from "@opentui/core"
2
3const renderer = await createCliRenderer()
4
5const scrollbox = new ScrollBoxRenderable(renderer, {
6id: "scrollbox",
7width: 40,
8height: 20,
9})
10
11for (let i = 0; i < 100; i++) {
12scrollbox.add(
13 new BoxRenderable(renderer, {
14 id: `item-${i}`,
15 width: "100%",
16 height: 2,
17 backgroundColor: i % 2 === 0 ? "#292e42" : "#2f3449",
18 }),
19)
20}
21
22renderer.root.add(scrollbox)

##Construct API

tsconstruct
1import { ScrollBox, Box, Text, createCliRenderer } from "@opentui/core"
2
3const renderer = await createCliRenderer()
4
5renderer.root.add(
6ScrollBox(
7 {
8 width: 40,
9 height: 20,
10 },
11 ...Array.from({ length: 100 }, (_, i) =>
12 Box(
13 { width: "100%", padding: 1, backgroundColor: i % 2 === 0 ? "#292e42" : "#2f3449" },
14 Text({ content: `Item ${i}` }),
15 ),
16 ),
17),
18)

##Sticky scroll

Keep content pinned to an edge as new content arrives. Useful for log viewers or chat interfaces:

ts
1const scrollbox = new ScrollBoxRenderable(renderer, {
2id: "logs",
3width: 60,
4height: 20,
5stickyScroll: true,
6stickyStart: "bottom", // keep scrolled to bottom
7})

Sticky positions:

  • "bottom" — stay scrolled to bottom (default for chat/logs)
  • "top" — stay scrolled to top
  • "left" — stay scrolled to left
  • "right" — stay scrolled to right

When you scroll away from the sticky position, sticky behavior pauses until you scroll back to the sticky edge.

##Bidirectional scrolling

ts
1const scrollbox = new ScrollBoxRenderable(renderer, {
2id: "canvas",
3width: 60,
4height: 30,
5scrollX: true,
6scrollY: true,
7})

By default, scrollY is true and scrollX is false.

##Viewport culling

Render only visible children for large content:

ts
1const scrollbox = new ScrollBoxRenderable(renderer, {
2id: "large-list",
3width: 40,
4height: 20,
5viewportCulling: true,
6})

Viewport culling skips render calls for offscreen children, so their renderBefore and renderAfter hooks do not run. Do not make layout or state depend on render hooks.

##Scroll methods

ts
1scrollbox.scrollBy(5) // scroll down 5 lines
2scrollbox.scrollBy({ x: 10, y: 5 }) // relative, both axes
3scrollbox.scrollBy(1, "viewport") // scroll by page
4scrollbox.scrollTo(0) // scroll to top
5scrollbox.scrollTo({ x: 0, y: 100 }) // absolute position
6scrollbox.scrollChildIntoView("row-42") // reveal a nested child

scrollChildIntoView uses DOM-style "nearest" behavior: if the child already fits, the call is a no-op; otherwise it scrolls the minimum distance to reveal it.

##Keyboard navigation

~/keymap
↑ ↓Scroll by line
← →Scroll by column (when scrollX)
Page Up / Page DownScroll by page
Home / EndScroll to start / end

##Customizing scrollbars

ts
1const scrollbox = new ScrollBoxRenderable(renderer, {
2id: "styled-scroll",
3width: 40,
4height: 20,
5scrollbarOptions: {
6 showArrows: true,
7 trackOptions: {
8 foregroundColor: "#7aa2f7",
9 backgroundColor: "#414868",
10 },
11},
12verticalScrollbarOptions: { trackOptions: { backgroundColor: "#333" } },
13horizontalScrollbarOptions: { trackOptions: { backgroundColor: "#333" } },
14})

##Properties

properties
proptypedefaultdescription
scrollXbooleanfalseEnable horizontal scrolling
scrollYbooleantrueEnable vertical scrolling
stickyScrollbooleanfalseKeep scroll pinned to an edge
stickyStart"top" | "bottom" | "left" | "right"-Which edge to stick to
viewportCullingbooleantrueOnly render visible children
rootOptionsBoxOptions-Style options for root container
wrapperOptionsBoxOptions-Style options for wrapper
viewportOptionsBoxOptions-Style options for viewport
contentOptionsBoxOptions-Style options for content container
scrollbarOptionsScrollBarOptions-Options for both scrollbars
verticalScrollbarOptionsScrollBarOptions-Options for vertical scrollbar
horizontalScrollbarOptionsScrollBarOptions-Options for horizontal scrollbar

##Internal components

ScrollBox exposes its internal components for advanced use:

ts
1scrollbox.wrapper // BoxRenderable — outer wrapper
2scrollbox.viewport // BoxRenderable — visible area
3scrollbox.content // ContentRenderable — holds children
4scrollbox.horizontalScrollBar // ScrollBarRenderable
5scrollbox.verticalScrollBar // ScrollBarRenderable