A customizable, high-precision vertical scroll bar component for Ink CLI applications.
Two Rendering Modes:
Border Mode: Seamlessly integrates with container borders (replaces one side).
Inset Mode: Renders inside the content area, perfect for floating scroll bars.
- Supports
autoHide: Completely hide the scroll bar when content fits the viewport. - If
autoHideisfalse(default) and content fits, only the track is shown.
- Supports
Rich Styling:
- Supports all standard Ink border styles (
single,double,round,bold, etc.). - Special inset styles (
block,line,thick,dots). - Customizable colors and dimming.
- Supports all standard Ink border styles (
Flexible Integration:
- Standalone
ScrollBarcomponent for custom layouts. ScrollBarBoxwrapper for instant bordered containers with scroll bars.
- Standalone
Auto-hide: Option to hide the scroll bar when content fits the viewport (inset mode).
npm install @byteland/ink-scroll-barThe easiest way to use ink-scroll-bar is with the ScrollBarBox component. It wraps your content in a bordered box and handles the scroll bar positioning for you.
importReact,{useState}from"react";import{Text}from"ink";import{ScrollBarBox}from"ink-scroll-bar";constMyComponent=()=>{const[offset,setOffset]=useState(0);consttotalItems=50;constviewportHeight=10;return(<ScrollBarBoxheight={viewportHeight+2}// +2 for borderswidth={40}borderStyle="single"scrollBarPosition="right"contentHeight={totalItems}viewportHeight={viewportHeight}scrollOffset={offset}>{/* Your scrollable content here */}<Text>Item 1...</Text></ScrollBarBox>);};For more control over layout, use the standalone ScrollBar component.
In border mode, the scroll bar renders corner characters to connect with adjacent borders.
import{Box}from"ink";import{ScrollBar}from"ink-scroll-bar";<BoxflexDirection="row">{/* Content Box with right border removed */}<BoxborderStyle="single"borderRight={false}><Content/></Box>{/* ScrollBar completes the border */}<ScrollBarplacement="right"style="single"contentHeight={100}viewportHeight={20}scrollOffset={offset}/></Box>;Inset mode renders without corners, suitable for placing inside a container.
<BoxborderStyle="round"padding={1}><BoxflexDirection="row"><Content/><ScrollBarplacement="inset"style="block"// 'block', 'line', 'thick', 'dots'color="cyan"contentHeight={100}viewportHeight={20}scrollOffset={offset}autoHide// Hide if content fits/></Box></Box>| Prop | Type | Default | Description |
|---|---|---|---|
contentHeight | number | Required | 📏 Total height of the scrollable content. |
viewportHeight | number | Required | 👁️ Height of the visible area. |
scrollOffset | number | Required | ⬇️ Current scroll position (0 to max). |
placement | 'left' | 'right' | 'inset' | 'right' | 📍 Rendering mode/position. |
style | ScrollBarStyle | 'single'/'block' | 🎨 Visual style (see below). |
color | string | undefined | 🌈 Color of the scroll bar characters. |
dimColor | boolean | false | 🌑 Whether to dim the scroll bar. |
autoHide | boolean | false | 👻 Hide when content fits (Inset mode only). If false, shows track when content fits. |
thumbChar | string | - | 👍 Custom thumb character. |
trackChar | string | - | 🛤️ Custom track character (Inset mode only). |
Inherits all Ink Box Props, plus:
| Prop | Type | Default | Description |
|---|---|---|---|
contentHeight | number | Required | 📏 Total height of the content. |
viewportHeight | number | Required | 👁️ Height of the viewport. |
scrollOffset | number | Required | ⬇️ Current scroll position. |
scrollBarPosition | 'left' | 'right' | 'right' | 📍 Which border to replace with scroll bar. |
scrollBarAutoHide | boolean | false | 👻 Hide thumb if content fits. |
thumbChar | string | - | 👍 Custom thumb character. |
Border Mode Styles (matches Ink borders):
single,double,round,bold,singleDouble,doubleSingle,classic,arrow
Inset Mode Styles:
block: █ thumb, ░ trackline: │ thumb, (blank) trackthick: ┃ thumb, ╏ trackdots: ● thumb, · track
MIT