Skip to content

ListView ​

Unified virtualized list component. Renders only visible items plus overscan for smooth scrolling. Supports passive (parent-controlled scroll) and navigable (built-in keyboard/mouse) modes.

Import ​

tsx
import { ListView } from "silvery"

Usage ​

tsx
// Passive — parent controls scroll position
<ListView
  items={logs}
  height={20}
  renderItem={(item, index) => <Text>{item.message}</Text>}
/>

// Navigable — built-in j/k, arrows, PgUp/PgDn, Home/End, G, mouse wheel
<ListView
  items={items}
  height={20}
  navigable
  renderItem={(item, i, meta) => (
    <Text inverse={meta.isCursor}>{item.name}</Text>
  )}
  onSelect={(index) => openItem(items[index])}
/>

Props ​

Core ​

PropTypeDefaultDescription
itemsT[]requiredArray of items to render
heightnumberrequiredViewport height in rows
renderItem(item: T, index: number, meta: ListItemMeta) => ReactNoderequiredRender function for each item
estimateHeightnumber | (index: number) => number1Estimated height per item in rows
getKey(item: T, index: number) => string | numberindexKey extractor
widthnumber—Viewport width (uses parent width if omitted)

Scrolling ​

PropTypeDefaultDescription
scrollTonumber—Index to scroll to (ignored when navigable)
overscannumber5Extra items rendered beyond viewport
maxRenderednumber100Maximum items rendered at once
scrollPaddingnumber2Padding from edge before scrolling (in items)
overflowIndicatorbooleanfalseShow overflow indicators
gapnumber0Gap between items in rows
renderSeparator() => ReactNode—Custom separator between items
listFooterReactNode—Content after all items in scroll container
virtualized(item: T, index: number) => boolean—Predicate for already-virtualized prefix items
PropTypeDefaultDescription
navigableboolean—Enable built-in keyboard and mouse navigation
cursorIndexnumber—Controlled cursor position
onCursorIndexChange(index: number) => void—Called when cursor moves
onSelect(index: number) => void—Called when Enter is pressed
activebooleantrueWhether keyboard input is captured

Infinite Scroll ​

PropTypeDefaultDescription
onEndReached() => void—Called when near the end of the list
onEndReachedThresholdnumber5Items from end to trigger onEndReached

ListItemMeta ​

ts
interface ListItemMeta {
  /** Whether this item is at the cursor position (navigable mode only) */
  isCursor: boolean
}

Ref Handle (ListViewHandle) ​

MethodTypeDescription
scrollToItem(index)(index: number) => voidImperatively scroll to an item

Keyboard Shortcuts (navigable mode) ​

KeyAction
j / DownMove cursor down
k / UpMove cursor up
G / EndJump to last item
HomeJump to first item
PgDn / Ctrl+DPage down (half viewport)
PgUp / Ctrl+UPage up (half viewport)
EnterSelect item at cursor

Examples ​

Variable Height Items ​

tsx
<ListView
  items={messages}
  height={20}
  estimateHeight={(index) => messages[index].lines}
  renderItem={(msg) => <Text>{msg.content}</Text>}
  scrollTo={messages.length - 1}
/>

With Custom Separators ​

tsx
<ListView
  items={sections}
  height={15}
  navigable
  renderItem={(item, i, meta) => <Text inverse={meta.isCursor}>{item.title}</Text>}
  renderSeparator={() => <Text color="$border">{"─".repeat(40)}</Text>}
/>

Infinite Scroll ​

tsx
<ListView
  items={feed}
  height={20}
  navigable
  renderItem={(item) => <Text>{item.title}</Text>}
  onEndReached={loadMore}
  onEndReachedThreshold={10}
/>