Select

A vertical list for choosing from multiple options. Focus the select to enable keyboard input.

Basic usage

Renderable API

import { SelectRenderable, SelectRenderableEvents, createCliRenderer } from "@opentui/core"

const renderer = await createCliRenderer()

const menu = new SelectRenderable(renderer, {
  id: "menu",
  width: 30,
  height: 8,
  options: [
    { name: "New File", description: "Create a new file" },
    { name: "Open File", description: "Open an existing file" },
    { name: "Save", description: "Save current file" },
    { name: "Exit", description: "Exit the application" },
  ],
})

menu.on(SelectRenderableEvents.ITEM_SELECTED, (index, option) => {
  console.log("Selected:", option.name)
})

menu.focus()
renderer.root.add(menu)

Construct API

import { Select, createCliRenderer } from "@opentui/core"

const renderer = await createCliRenderer()

const menu = Select({
  width: 30,
  height: 8,
  options: [
    { name: "Option 1", description: "First option" },
    { name: "Option 2", description: "Second option" },
    { name: "Option 3", description: "Third option" },
  ],
})

menu.focus()
renderer.root.add(menu)

Keyboard navigation

When focused, the select responds to these keys:

Key Action
Up / k Move selection up
Down / j Move selection down
Shift+Up / Shift+Down Fast scroll (5 items)
Enter Select current item

Events

Item selected

Fires when the user presses Enter on an option:

import { SelectRenderableEvents } from "@opentui/core"

menu.on(SelectRenderableEvents.ITEM_SELECTED, (index: number, option: SelectOption) => {
  console.log(`Selected index ${index}: ${option.name}`)
})

Selection changed

Fires when the highlighted item changes:

menu.on(SelectRenderableEvents.SELECTION_CHANGED, (index: number, option: SelectOption) => {
  console.log(`Highlighted: ${option.name}`)
  // Update a preview pane, for example
})

Option structure

interface SelectOption {
  name: string // Display text
  description: string // Displays below the name when showDescription is true
  value?: any // Optional value
}

Styling

const styledMenu = new SelectRenderable(renderer, {
  id: "styled-menu",
  width: 40,
  height: 10,
  options: [...],
  backgroundColor: "#1a1a1a",
  selectedBackgroundColor: "#333366",
  selectedTextColor: "#FFFFFF",
  textColor: "#AAAAAA",
  descriptionColor: "#666666",
})

Properties

Property Type Default Description
width number - Component width
height number - Component height
options SelectOption[] [] Available options
selectedIndex number 0 Initially selected index
backgroundColor string | RGBA transparent Background color
textColor string | RGBA #FFFFFF Normal text color
focusedBackgroundColor string | RGBA #1a1a1a Background when focused
focusedTextColor string | RGBA #FFFFFF Text color when focused
selectedBackgroundColor string | RGBA #334455 Selected item background
selectedTextColor string | RGBA #FFFF00 Selected item text color
descriptionColor string | RGBA #888888 Description text color
selectedDescriptionColor string | RGBA #CCCCCC Selected item description color
showDescription boolean true Show option descriptions
showScrollIndicator boolean false Show scroll position indicator
showSelectionIndicator boolean true Show the selection marker and gutter
wrapSelection boolean false Wrap selection at list boundaries
itemSpacing number 0 Spacing between items
fastScrollStep number 5 Items to skip with Shift+Up/Down

Example: file menu

import { Box, Select, createCliRenderer } from "@opentui/core"

const renderer = await createCliRenderer()

const fileMenu = Select({
  width: 25,
  height: 12,
  options: [
    { name: "New", description: "Create new file (Ctrl+N)" },
    { name: "Open...", description: "Open file (Ctrl+O)" },
    { name: "Save", description: "Save file (Ctrl+S)" },
    { name: "Save As...", description: "Save with new name" },
    { name: "---", description: "" }, // Separator (visual only)
    { name: "Exit", description: "Quit application (Ctrl+Q)" },
  ],
})

const menuPanel = Box(
  {
    borderStyle: "single",
    borderColor: "#666",
  },
  fileMenu,
)

fileMenu.focus()
renderer.root.add(menuPanel)

Programmatic control

// Get current selection index
const currentIndex = menu.getSelectedIndex()

// Get currently selected option
const option = menu.getSelectedOption()

// Set selection programmatically
menu.setSelectedIndex(2)

// Navigate programmatically
menu.moveUp() // Move up one item
menu.moveDown() // Move down one item
menu.moveUp(3) // Move up multiple items
menu.selectCurrent() // Trigger selection of current item

// Update options dynamically
menu.options = [
  { name: "New Option 1", description: "First" },
  { name: "New Option 2", description: "Second" },
]

// Toggle display options
menu.showDescription = false
menu.showScrollIndicator = true
menu.showSelectionIndicator = false
menu.wrapSelection = true