An enhanced, customizable select input component for Ink that supports both vertical and horizontal orientations, hotkeys, and flexible rendering. Ideal for building rich, interactive CLI apps with React.
- Orientation: Choose between vertical or horizontal layouts.
- Custom Indicators & Items: Easily swap out the default indicator and item rendering.
- Hotkey Support: Assign single-character hotkeys for quick selection.
- Disabled Items: Gracefully skip unselectable items during navigation.
- Keyboard Navigation: Arrow keys and Vim-like keys (
h/j/k/l) supported. - Hooks for Highlight & Selection: Run custom logic on highlight and selection changes.
- Limit Displayed Items: Restrict how many options to show at once.
| Dependency | Required Version |
|---|---|
| Node.js | >= 20 |
| React | >= 19 |
| Ink | >= 6 |
For Ink 5 / React 18 support, use
ink-enhanced-select-input@0.2.0.
npm install ink-enhanced-select-input ink reactor
yarn add ink-enhanced-select-input ink reactimport React from 'react' import { render, Text } from 'ink' import { EnhancedSelectInput } from 'ink-enhanced-select-input' const items = [ { label: 'Option 1', value: 'one', hotkey: '1' }, { label: 'Option 2', value: 'two', hotkey: '2' }, { label: 'Option 3', value: 'three', disabled: true }, { label: 'Option 4', value: 'four', hotkey: '4' }, ] function Demo() { return ( <EnhancedSelectInput items={items} onSelect={(item) => console.log(`Selected: ${item.value}`)} onHighlight={(item) => console.log(`Highlighted: ${item.value}`)} /> ) } render(<Demo />)<EnhancedSelectInput items={items} orientation="horizontal" onSelect={(item) => console.log(item.value)} /><EnhancedSelectInput items={[ { label: 'Save', value: 'save', indicator: <Text color="green">✔</Text> }, { label: 'Delete', value: 'delete', indicator: <Text color="red">✘</Text> }, { label: 'Cancel', value: 'cancel', hotkey: 'c' }, ]} onSelect={(item) => console.log(item.value)} />function MyIndicator({ isSelected }) { return ( <Text color={isSelected ? 'magenta' : undefined}> {isSelected ? '👉' : ' '} </Text> ) } function MyItem({ isSelected, isDisabled, label }) { return ( <Text color={isDisabled ? 'gray' : isSelected ? 'yellow' : 'white'} dimColor={isDisabled} > {label} </Text> ) } ;<EnhancedSelectInput items={items} indicatorComponent={MyIndicator} itemComponent={MyItem} />| Prop | Type | Default | Description |
|---|---|---|---|
items | Array<Item<V>> | required | List of selectable items |
isFocused | boolean | true | Whether the component responds to input |
initialIndex | number | 0 | Index of the initially highlighted item |
limit | number | — | Max number of visible items |
indicatorComponent | FC<IndicatorProps> | DefaultIndicatorComponent | Custom selection indicator |
itemComponent | FC<ItemProps> | DefaultItemComponent | Custom item renderer |
onSelect | (item: Item<V>) => void | — | Called on selection (Enter or hotkey) |
onHighlight | (item: Item<V>) => void | — | Called when the highlighted item changes |
orientation | 'vertical' | 'horizontal' | 'vertical' | Layout direction |
type Item<V> = { key?: string label: string value: V hotkey?: string indicator?: React.ReactNode disabled?: boolean }| Orientation | Previous | Next | Select |
|---|---|---|---|
| Vertical | ↑ / k | ↓ / j | Enter |
| Horizontal | ← / h | → / l | Enter |
Hotkeys (when assigned) select the item immediately.
Disabled items are automatically skipped during navigation.
git clone https://github.com/gfargo/ink-enhanced-select-input.git cd ink-enhanced-select-input yarn install| Command | Description |
|---|---|
yarn build | Compile TypeScript to dist/ |
yarn start | Build and run the interactive storybook demo |
yarn test | Build and run tests |
yarn lint | Check formatting and lint |
yarn lint:fix | Auto-fix formatting and lint issues |
Contributions are welcome. Feel free to open issues, submit pull requests, or provide feedback.