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.