### Install OpenTUI Keymap
Source: https://opentui.com/docs/keymap/overview
Install the OpenTUI Keymap package using Bun.
```bash
bun install @opentui/keymap
```
--------------------------------
### Welcome Screen Example
Source: https://opentui.com/docs/components/ascii-font
A comprehensive example demonstrating how to use Box, ASCIIFont, and Text components to create a welcome screen. Imports from @opentui/core.
```typescript
import { Box, ASCIIFont, Text, createCliRenderer } from "@opentui/core"
const renderer = await createCliRenderer()
const welcomeScreen = Box(
{
width: "100%",
height: "100%",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
},
ASCIIFont({
text: "OPENTUI",
font: "huge",
color: "#00FFFF",
}),
Text({
content: "Terminal UI Framework",
fg: "#888888",
}),
Text({
content: "Press any key to continue...",
fg: "#444444",
}),
)
renderer.root.add(welcomeScreen)
```
--------------------------------
### Install OpenTUI Solid Bindings
Source: https://opentui.com/docs/bindings/solid
Install the necessary packages for Solid.js integration.
```bash
bun install solid-js @opentui/solid
```
--------------------------------
### Install QR Code Package
Source: https://opentui.com/docs/components/qr-code
Install the QR code package separately using Bun.
```bash
bun install @opentui/qrcode
```
--------------------------------
### Basic React TUI Application Setup
Source: https://opentui.com/docs/bindings/react
Demonstrates the fundamental setup for a React TUI application, including creating a renderer and rendering a simple 'Hello, world!' component.
```jsx
import { createCliRenderer } from "@opentui/core"
import { createRoot } from "@opentui/react"
function App() {
return Hello, world!
}
const renderer = await createCliRenderer()
createRoot(renderer).render()
```
--------------------------------
### Device Selection and Playback Start
Source: https://opentui.com/docs/core-concepts/audio
Illustrates how to list available playback devices, select a specific device, and then start the audio engine. If no playback device is available, an error is logged.
```typescript
const audio = Audio.create({ autoStart: false })
const devices = audio.listPlaybackDevices() ?? []
const device = devices.find((item) => item.isDefault) ?? devices[0]
if (device) {
audio.selectPlaybackDevice(device.index)
}
if (!audio.start()) {
console.error("No playback device available")
}
```
--------------------------------
### Start React DevTools
Source: https://opentui.com/docs/bindings/react
Command to start the React DevTools standalone application.
```bash
npx react-devtools@7
```
--------------------------------
### Manual Installation of OpenTUI React Packages
Source: https://opentui.com/docs/bindings/react
Install the necessary OpenTUI React and core packages along with React itself.
```bash
bun install @opentui/react @opentui/core react
```
--------------------------------
### Basic React Keymap Setup
Source: https://opentui.com/docs/keymap/react
Demonstrates the fundamental setup of OpenTUI keymap bindings within a React application. It shows how to initialize the keymap, provide it via KeymapProvider, and register command bindings using the useBindings hook.
```jsx
/** @jsxImportSource @opentui/react */
import { createCliRenderer } from "@opentui/core"
import { createDefaultOpenTuiKeymap } from "@opentui/keymap/opentui"
import { KeymapProvider, useBindings } from "@opentui/keymap/react"
import { createRoot } from "@opentui/react"
const renderer = await createCliRenderer()
const keymap = createDefaultOpenTuiKeymap(renderer)
function App() {
useBindings(
() => ({
commands: [
{
name: "quit",
run() {
renderer.destroy()
},
},
],
bindings: [{ key: "q", cmd: "quit" }],
}),
[],
)
return Press q to quit
}
createRoot(renderer).render(
,
)
```
--------------------------------
### Install React DevTools
Source: https://opentui.com/docs/bindings/react
Instructions for installing the React DevTools core package for debugging OpenTUI React applications.
```bash
bun add --dev react-devtools-core@7
```
--------------------------------
### Install OpenTUI with Bun
Source: https://opentui.com/docs/getting-started
Initialize a new project and add the OpenTUI core package. This is currently Bun exclusive.
```bash
mkdir my-tui && cd my-tui
bun init -y
bun add @opentui/core
```
--------------------------------
### Login Form Example
Source: https://opentui.com/docs/bindings/react
A complete example of a login form using OpenTUI React, including input fields, keyboard navigation, and status display.
```javascript
import { createCliRenderer } from "@opentui/core"
import { createRoot, useKeyboard } from "@opentui/react"
import { useCallback, useState } from "react"
function App() {
const [username, setUsername] = useState("")
const [password, setPassword] = useState("")
const [focused, setFocused] = useState<"username" | "password">("username")
const [status, setStatus] = useState("idle")
useKeyboard((key) => {
if (key.name === "tab") {
setFocused((prev) => (prev === "username" ? "password" : "username")),
}
})
const handleSubmit = useCallback(() => {
if (username === "admin" && password === "secret") {
setStatus("success")
} else {
setStatus("error")
}
}, [username, password])
return (
Login Form
{status.toUpperCase()}
)
}
const renderer = await createCliRenderer()
createRoot(renderer).render()
```
--------------------------------
### Install Native Packages for Multi-Platform Builds
Source: https://opentui.com/docs/reference/standalone-executables
Before compiling for multi-platform releases, install optional native packages for all target OS and CPU combinations using this command. Replace `` with the specific version of @opentui/core.
```bash
bun install --os="*" --cpu="*" @opentui/core@
```
--------------------------------
### Create a Basic Solid App
Source: https://opentui.com/docs/bindings/solid
A minimal example of creating a Solid.js application with OpenTUI's `render` function and a basic `` component.
```typescript
import { render } from "@opentui/solid"
const App = () => Hello, World!
render(App)
```
--------------------------------
### File Menu Example
Source: https://opentui.com/docs/components/select
An example of creating a file menu using the Select component, including separators and descriptions for actions. It's wrapped in a Box for visual structure.
```typescript
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)
```
--------------------------------
### Login Form Example
Source: https://opentui.com/docs/components/input
A comprehensive example demonstrating a login form with username and password inputs. It utilizes a `LabeledInput` component for structure and styling, and initializes the form by focusing the username field.
```typescript
import { Box, Text, Input, delegate, createCliRenderer } from "@opentui/core"
const renderer = await createCliRenderer()
function LabeledInput(props: { id: string; label: string; placeholder: string }) {
return delegate(
{ focus: `${props.id}-input` },
Box(
{ flexDirection: "row", marginBottom: 1 },
Text({ content: props.label.padEnd(12), fg: "#888888" }),
Input({
id: `${props.id}-input`,
placeholder: props.placeholder,
width: 20,
backgroundColor: "#222",
focusedBackgroundColor: "#333",
textColor: "#FFF",
cursorColor: "#0F0",
}),
),
)
}
const usernameInput = LabeledInput({
id: "username",
label: "Username:",
placeholder: "Enter username",
})
const passwordInput = LabeledInput({
id: "password",
label: "Password:",
placeholder: "Enter password",
})
const form = Box(
{
width: 40,
borderStyle: "rounded",
title: "Login",
padding: 1,
},
usernameInput,
passwordInput,
)
// Focus the username input
usernameInput.focus()
renderer.root.add(form)
```
--------------------------------
### Delegate Mappings Example
Source: https://opentui.com/docs/core-concepts/constructs
Provides a concrete example of the mapping object used with `delegate()`, showing how method/property names are associated with descendant IDs for routing.
```typescript
delegate(
{
focus: "inner-input", // .focus() -> find descendant "inner-input" and call focus()
blur: "inner-input", // .blur() -> same
add: "content-area", // .add() -> add children to "content-area" instead
value: "inner-input", // .value get/set -> proxy to "inner-input"
},
vnode,
)
```
--------------------------------
### Start Continuous Rendering
Source: https://opentui.com/docs/core-concepts/renderer
Starts the render loop to run continuously at the target FPS. Use this for dynamic UIs that require constant updates.
```typescript
renderer.start() // Start continuous rendering
renderer.stop() // Stop the render loop
```
--------------------------------
### Card Component Example
Source: https://opentui.com/docs/components/box
A functional example demonstrating how to create a reusable Card component using Box and Text, with custom styling and content.
```typescript
import { Box, Text, t, bold, fg } from "@opentui/core"
function Card(props: { title: string; description: string }) {
return Box(
{
width: 40,
borderStyle: "rounded",
borderColor: "#666",
padding: 1,
margin: 1,
},
Text({
content: t`${bold(fg("#00FFFF")(props.title))}`,
}),
Text({
content: props.description,
fg: "#AAAAAA",
}),
)
}
renderer.root.add(
Box(
{ flexDirection: "row", flexWrap: "wrap" },
Card({ title: "Feature 1", description: "Description of feature 1" }),
Card({ title: "Feature 2", description: "Description of feature 2" }),
Card({ title: "Feature 3", description: "Description of feature 3" }),
),
)
```
--------------------------------
### String Binding Examples
Source: https://opentui.com/docs/keymap/core
Demonstrates various string formats for defining key bindings, including single strokes, sequences, and modifier chords.
```text
"x"
"ctrl+x"
"return"
```
```text
"dd"
"s"
"{count}j"
```
--------------------------------
### Acquiring a shared resource
Source: https://opentui.com/docs/keymap/core
Use acquireResource(symbol, setup) to share ref-counted setup and teardown logic across multiple addon registrations. This is useful for managing shared resources efficiently.
```typescript
keymap.acquireResource('myResource', async () => {
// Setup logic
return () => {
// Teardown logic
};
});
```
--------------------------------
### Install Bun Runtime Support
Source: https://opentui.com/docs/plugins/core
Import this once in your app entry to install Bun runtime support for `@opentui/core` and default core runtime entrypoints. Add first-party package runtime modules explicitly when a plugin imports them.
```typescript
import "@opentui/core/runtime-plugin-support"
```
--------------------------------
### Basic HTML Keymap Setup
Source: https://opentui.com/docs/keymap/hosts
Sets up a default keymap for an HTML host, registering a 'toggle-help' command bound to the '?' key. This is suitable for web applications requiring keyboard navigation or actions.
```typescript
import { createDefaultHtmlKeymap } from "@opentui/keymap/html"
const root = document.getElementById("app")!
const keymap = createDefaultHtmlKeymap(root)
keymap.registerLayer({
commands: [
{
name: "toggle-help",
run() {
document.body.classList.toggle("help-open")
},
},
],
bindings: [{ key: "?", cmd: "toggle-help" }])
```
--------------------------------
### Install C++ Runtime Libraries on Alpine
Source: https://opentui.com/docs/reference/standalone-executables
For Bun's Linux musl standalone runtime, install the standard C++ runtime libraries on Alpine Linux using this command.
```bash
apk add --no-cache libstdc++ libgcc
```
--------------------------------
### Object Binding Examples
Source: https://opentui.com/docs/keymap/core
Shows how to define bindings using an object format for direct normalization and for release events.
```javascript
{ name: "return", ctrl: true }
```
```javascript
{ key: "a", event: "release", ...}
```
--------------------------------
### Create TUI Project with React Template
Source: https://opentui.com/docs/bindings/react
Quickly start a new React TUI project using the 'create-tui' command with the 'react' template.
```bash
bun create tui --template react
```
--------------------------------
### Basic CLI Keymap Setup
Source: https://opentui.com/docs/keymap/hosts
Sets up a default keymap for the CLI, registering a 'quit' command bound to the 'q' key. This is useful for basic CLI applications needing keyboard shortcuts.
```typescript
import { createCliRenderer } from "@opentui/core"
import { createDefaultOpenTuiKeymap } from "@opentui/keymap/opentui"
const renderer = await createCliRenderer()
const keymap = createDefaultOpenTuiKeymap(renderer)
keymap.registerLayer({
commands: [
{
name: "quit",
run() {
renderer.destroy()
},
},
],
bindings: [{ key: "q", cmd: "quit" }])
```
--------------------------------
### Declarative API Layout Example
Source: https://opentui.com/docs/core-concepts/layout
Shows how to construct a layout using the declarative OpenTUI API with nested Box and Text components. This example creates a container with left and right panels.
```typescript
import { Box, Text } from "@opentui/core"
renderer.root.add(
Box(
{
flexDirection: "row",
width: "100%",
height: 10,
},
Box(
{
flexGrow: 1,
backgroundColor: "#333",
padding: 1,
},
Text({ content: "Left Panel" }),
),
Box(
{
width: 20,
backgroundColor: "#555",
padding: 1,
},
Text({ content: "Right Panel" }),
),
),
)
```
--------------------------------
### Load External Plugins with Runtime Support
Source: https://opentui.com/docs/plugins/react
This snippet demonstrates loading external plugins from disk at runtime using Bun. It installs runtime support and then registers the loaded plugin.
```typescript
import "@opentui/react/runtime-plugin-support"
const mod = await import(pathToFileURL(pluginPath).href)
registry.register(mod.loadExternalPlugin())
```
--------------------------------
### Basic Flexbox Container Setup
Source: https://opentui.com/docs/core-concepts/layout
Sets up a root container with row direction, space-between justification, and center alignment for child elements. Requires creating a CLI renderer and BoxRenderable instances.
```typescript
import { BoxRenderable, createCliRenderer } from "@opentui/core"
const renderer = await createCliRenderer()
const container = new BoxRenderable(renderer, {
id: "container",
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
width: "100%",
height: 10,
})
const leftPanel = new BoxRenderable(renderer, {
id: "left",
flexGrow: 1,
height: 10,
backgroundColor: "#444",
})
const rightPanel = new BoxRenderable(renderer, {
id: "right",
width: 20,
height: 10,
backgroundColor: "#666",
})
container.add(leftPanel)
container.add(rightPanel)
renderer.root.add(container)
```
--------------------------------
### Basic Line Number Setup
Source: https://opentui.com/docs/components/line-number
Demonstrates how to initialize and add a LineNumberRenderable to a CodeRenderable within a ScrollBoxRenderable.
```typescript
import {
CodeRenderable,
LineNumberRenderable,
ScrollBoxRenderable,
SyntaxStyle,
RGBA,
createCliRenderer,
} from "@opentui/core"
const renderer = await createCliRenderer()
const syntaxStyle = SyntaxStyle.fromStyles({
default: { fg: RGBA.fromHex("#E6EDF3") },
})
const code = new CodeRenderable(renderer, {
id: "code",
content: "const x = 1\nconst y = 2\n",
filetype: "typescript",
syntaxStyle,
width: "100%",
})
const lineNumbers = new LineNumberRenderable(renderer, {
id: "code-lines",
target: code,
minWidth: 3,
paddingRight: 1,
fg: "#6b7280",
bg: "#161b22",
})
const scrollbox = new ScrollBoxRenderable(renderer, {
id: "scrollbox",
width: 70,
height: 18,
})
scrollbox.add(lineNumbers)
renderer.root.add(scrollbox)
```
--------------------------------
### Select Component API
Source: https://opentui.com/docs/components/select
This documentation outlines the API for the Select component, including its properties, events, and usage examples.
```APIDOC
## Select Component
A vertical list for choosing from multiple options. Focus the select to enable keyboard input.
### Basic Usage
#### Renderable API
```javascript
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
```javascript
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 the following 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.
```javascript
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.
```javascript
menu.on(SelectRenderableEvents.SELECTION_CHANGED, (index: number, option: SelectOption) => {
console.log(`Highlighted: ${option.name}`)
// Update a preview pane, for example
})
```
### Option Structure
```typescript
interface SelectOption {
name: string // Display text
description: string // Displays below the name when showDescription is true
value?: any // Optional value
}
```
### Styling
```javascript
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 |
| `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
```javascript
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)
```
```
--------------------------------
### Basic Audio Playback
Source: https://opentui.com/docs/core-concepts/audio
Demonstrates loading a sound file and playing it with basic options. Ensure the audio engine is created and started before playing sounds. Errors during playback are caught and logged.
```typescript
import { Audio } from "@opentui/core"
const audio = Audio.create({ autoStart: false })
audio.on("error", (error, context) => {
console.error(`${context.action}: ${error.message}`)
})
const sound = await audio.loadSoundFile("click.wav")
if (sound != null && audio.start()) {
audio.play(sound, { volume: 0.8, pan: 0, loop: false })
}
audio.dispose()
```
--------------------------------
### Acquire Shared Resource
Source: https://opentui.com/docs/keymap/custom-addons
Use acquireResource to share setup and teardown logic across multiple addon registrations on the same keymap.
```typescript
acquireResource(symbol, setup);
```
--------------------------------
### Basic Core Slot Registry and Plugin Registration
Source: https://opentui.com/docs/plugins/core
Demonstrates the basic usage of `createCoreSlotRegistry` and `registerCorePlugin`. This example sets up a registry for `BaseRenderable` nodes and registers a plugin that provides a 'statusbar' slot renderer. The `unregister` function can be called to remove the plugin.
```typescript
import {
BoxRenderable,
createCliRenderer,
createCoreSlotRegistry,
registerCorePlugin,
SlotRenderable,
TextRenderable,
} from "@opentui/core"
type Slots = "statusbar"
type SlotData = { label: string }
const context = { appName: "core-app", version: "1.0.0" }
const renderer = await createCliRenderer()
const registry = createCoreSlotRegistry(renderer, context)
const unregister = registerCorePlugin(registry, {
id: "clock-plugin",
order: 0,
slots: {
statusbar(_ctx, data) {
return new TextRenderable(renderer, {
id: "clock-status",
content: `clock: ${data.label}`,
})
},
},
})
const slot = new SlotRenderable(renderer, {
id: "statusbar-slot",
registry,
name: "statusbar",
data: { label: "ok" },
mode: "append",
width: "100%",
height: 3,
flexDirection: "row",
fallback: () =>
new TextRenderable(renderer, {
id: "statusbar-fallback",
content: "fallback",
}),
})
renderer.root.add(slot)
// later
slot.mode = "replace"
slot.data = { label: "updated" }
slot.refresh()
slot.destroy()
```
--------------------------------
### Available Core Constructs
Source: https://opentui.com/docs/core-concepts/constructs
Shows examples of various core constructs like Box, Text, Input, and others, illustrating their instantiation with different properties. These create VNodes, not actual Renderables.
```typescript
import {
ASCIIFont,
Box,
Code,
FrameBuffer,
Input,
ScrollBox,
Select,
SyntaxStyle,
TabSelect,
Text,
RGBA,
} from "@opentui/core"
// These create VNodes, not actual Renderables
const syntaxStyle = SyntaxStyle.fromStyles({
default: { fg: RGBA.fromHex("#FFFFFF") },
})
const box = Box({ border: true })
const text = Text({ content: "Hello" })
const input = Input({ placeholder: "Type here..." })
const code = Code({ content: "const x = 1", filetype: "typescript", syntaxStyle })
const scrollBox = ScrollBox({ width: 40, height: 10 })
const frameBuffer = FrameBuffer({ width: 20, height: 10 })
const ascii = ASCIIFont({ text: "OPEN", font: "tiny" })
```
--------------------------------
### Create and Add a TextRenderable
Source: https://opentui.com/docs/core-concepts/renderables
Instantiate a TextRenderable with a renderer and options, then add it to the renderer's root. This is a basic example of creating a renderable element.
```typescript
import { createCliRenderer, TextRenderable, BoxRenderable } from "@opentui/core"
const renderer = await createCliRenderer()
const greeting = new TextRenderable(renderer, {
id: "greeting",
content: "Hello, OpenTUI!",
fg: "#00FF00",
})
renderer.root.add(greeting)
```
--------------------------------
### Basic Diff Rendering with Syntax Highlighting
Source: https://opentui.com/docs/components/diff
Demonstrates how to create and add a DiffRenderable component to the renderer. It includes setup for syntax styling and specifies the diff content, view type, filetype, and line number display.
```typescript
import { DiffRenderable, SyntaxStyle, RGBA, createCliRenderer } from "@opentui/core"
const renderer = await createCliRenderer()
const syntaxStyle = SyntaxStyle.fromStyles({
default: { fg: RGBA.fromHex("#E6EDF3") },
string: { fg: RGBA.fromHex("#A5D6FF") },
keyword: { fg: RGBA.fromHex("#FF7B72"), bold: true },
})
const diff = new DiffRenderable(renderer, {
id: "diff",
width: "100%",
height: 16,
diff: `diff --git a/app.ts b/app.ts\nindex 1111111..2222222 100644\n--- a/app.ts\n+++ b/app.ts\n@@ -1,3 +1,3 @@\n-const a = 1\n+const a = 2\n`,
view: "split",
filetype: "typescript",
syntaxStyle,
showLineNumbers: true,
})
renderer.root.add(diff)
```
--------------------------------
### Solid Counter Example
Source: https://opentui.com/docs/bindings/solid
A basic counter component using Solid.js with OpenTUI. It utilizes `createSignal` for state management and `useKeyboard` for user input. The renderer can be destroyed by pressing ESC.
```typescript
import { render, useKeyboard, useRenderer } from "@opentui/solid"
import { createSignal } from "solid-js"
const App = () => {
const [count, setCount] = createSignal(0)
const renderer = useRenderer()
useKeyboard((key) => {
if (key.name === "up") setCount((c) => c + 1)
if (key.name === "down") setCount((c) => c - 1)
if (key.name === "escape") renderer.destroy()
})
return (
Count: {count()}
Up/Down to change, ESC to close
)
}
render(App)
```
--------------------------------
### Get Current Input Value
Source: https://opentui.com/docs/components/input
Retrieves the current text value of the input field. This property can be accessed at any time to get the latest content.
```typescript
const currentValue = input.value
```
--------------------------------
### Status Bar Example with Text and Box Components
Source: https://opentui.com/docs/components/text
Combines Text and Box components to create a status bar at the bottom of the screen, displaying file information and cursor position using rich text formatting.
```typescript
import { Text, Box, t, bold, fg } from "@opentui/core"
const statusBar = Box(
{
position: "absolute",
bottom: 0,
width: "100%",
height: 1,
backgroundColor: "#333333",
flexDirection: "row",
justifyContent: "space-between",
paddingLeft: 1,
paddingRight: 1,
},
Text({
content: t`${bold("myfile.ts")} - ${fg("#888888")("TypeScript")}`,
}),
Text({
content: t`Ln ${fg("#00FF00")("42")}, Col ${fg("#00FF00")("15")}`,
}),
)
renderer.root.add(statusBar)
```
--------------------------------
### Run OpenTUI 'Hello World' App
Source: https://opentui.com/docs/getting-started
Executes the TypeScript file using Bun to display the TUI.
```bash
bun index.ts
```
--------------------------------
### Basic Solid Keymap Integration
Source: https://opentui.com/docs/keymap/solid
Demonstrates setting up OpenTUI keymap bindings in a Solid application. It initializes the keymap, provides it via `KeymapProvider`, and registers commands and bindings using `useBindings`.
```typescript
import { createCliRenderer } from "@opentui/core"
import { createDefaultOpenTuiKeymap } from "@opentui/keymap/opentui"
import { KeymapProvider, useBindings } from "@opentui/keymap/solid"
import { render } from "@opentui/solid"
const renderer = await createCliRenderer()
const keymap = createDefaultOpenTuiKeymap(renderer)
function App() {
useBindings(() => ({
commands: [
{
name: "quit",
run() {
renderer.destroy()
},
},
],
bindings: [{ key: "q", cmd: "quit" }],
}))
return Press q to quit
}
await render(
() => (
),
renderer,
)
```
--------------------------------
### Basic Solid Slot Registry and Usage
Source: https://opentui.com/docs/plugins/solid
Demonstrates creating a Solid slot registry, registering a plugin with a statusbar slot, and rendering the slot with fallback content.
```typescript
import { createCliRenderer } from "@opentui/core"
import { createSolidSlotRegistry, Slot, render } from "@opentui/solid"
type Slots = {
statusbar: { user: string }
}
const context = { appName: "solid-app", version: "1.0.0" }
const renderer = await createCliRenderer()
const registry = createSolidSlotRegistry(renderer, context)
const unregister = registry.register({
id: "clock-plugin",
slots: {
statusbar(ctx, props) {
return {`${ctx.appName}:${props.user}`}
},
},
})
const AppSlot = Slot
const App = () => (
fallback-statusbar
)
render(() => , renderer)
```
--------------------------------
### Get Reactive Terminal Dimensions - OpenTUI Solid
Source: https://opentui.com/docs/bindings/solid
Use useTerminalDimensions to get reactive terminal dimensions as a Solid signal. Access the width and height properties from the returned signal.
```typescript
import { useTerminalDimensions } from "@opentui/solid"
const App = () => {
const dimensions = useTerminalDimensions()
return (
Terminal: {dimensions().width}x{dimensions().height}
)
}
```
--------------------------------
### Tabbed Interface Example
Source: https://opentui.com/docs/components/tab-select
Demonstrates creating a tabbed interface where selecting a tab changes the content displayed in an adjacent area. This example integrates TabSelect with Box and Text components.
```typescript
import { Box, Text, TabSelect, createCliRenderer } from "@opentui/core"
const renderer = await createCliRenderer()
// Create content panels
const panels = {
home: Box({ padding: 1 }, Text({ content: "Home content here" })),
files: Box({ padding: 1 }, Text({ content: "File browser here" })),
settings: Box({ padding: 1 }, Text({ content: "Settings form here" })),
}
// Create the tabbed container
const container = Box({
width: 60,
height: 20,
borderStyle: "rounded",
})
const tabs = TabSelect({
width: 60,
tabWidth: 20,
options: [
{ name: "Home", description: "Dashboard" },
{ name: "Files", description: "Browse files" },
{ name: "Settings", description: "Preferences" },
],
})
// Content area
let currentPanel = panels.home
const contentArea = Box({
flexGrow: 1,
padding: 1,
})
contentArea.add(currentPanel)
// Handle tab changes
tabs.on("itemSelected", (index, option) => {
// Remove current panel
if (currentPanel) {
contentArea.remove(currentPanel.id)
}
// Add new panel based on selection
switch (option.name) {
case "Home":
currentPanel = panels.home
break
case "Files":
currentPanel = panels.files
break
case "Settings":
currentPanel = panels.settings
break
}
contentArea.add(currentPanel)
})
container.add(tabs)
container.add(contentArea)
tabs.focus()
renderer.root.add(container)
```
--------------------------------
### Create and Use a Test Renderer
Source: https://opentui.com/docs/core-concepts/testing
Demonstrates how to create a test renderer, add components, render them once, capture the character frame output, and then destroy the renderer.
```typescript
import { createTestRenderer } from "@opentui/core/testing"
import { Text } from "@opentui/core"
const { renderer, renderOnce, captureCharFrame } = await createTestRenderer({ width: 40, height: 10 })
renderer.root.add(Text({ content: "Hello" }))
await renderOnce()
console.log(captureCharFrame())
renderer.destroy()
```
--------------------------------
### Create and Use Test Keymap
Source: https://opentui.com/docs/keymap/custom-addons
Set up a test keymap environment, register a custom addon, define commands and bindings, simulate key presses, and check for errors.
```typescript
import { createTestKeymap } from "@opentui/keymap/testing"
import { registerMyAddon } from "./my-addon"
const { keymap, host, diagnostics, cleanup } = createTestKeymap({ defaultKeys: true })
registerMyAddon(keymap)
keymap.registerLayer({
commands: [{ name: "save", run() {} }],
bindings: [{ key: "x", cmd: "save" }],
})
host.press("x")
diagnostics.takeErrors()
cleanup()
```
--------------------------------
### Basic React Slot Registry and Usage
Source: https://opentui.com/docs/plugins/react
Demonstrates creating a React slot registry with defined slots and context, registering a plugin that renders UI into a statusbar slot, and using the Slot component in an App.
```typescript
import { createCliRenderer } from "@opentui/core"
import { createReactSlotRegistry, createRoot, Slot } from "@opentui/react"
type Slots = {
statusbar: { user: string }
}
const context = { appName: "react-app", version: "1.0.0" }
const renderer = await createCliRenderer()
const registry = createReactSlotRegistry(renderer, context)
const unregister = registry.register({
id: "clock-plugin",
slots: {
statusbar(ctx, props) {
return {`${ctx.appName}:${props.user}`}
},
},
})
const AppSlot = Slot
function App() {
return (
fallback-statusbar
)
}
createRoot(renderer).render()
```
--------------------------------
### Install Bun Runtime Support for External Plugins
Source: https://opentui.com/docs/plugins/react
Add this import once in your app entry to install Bun runtime support for external TS/TSX plugin modules. This ensures they resolve against the host runtime instances.
```typescript
import "@opentui/react/runtime-plugin-support"
```
--------------------------------
### Invert Entire Buffer Example
Source: https://opentui.com/docs/reference/color-matrix
Demonstrates how to invert all colors in the FrameBuffer using `colorMatrixUniform` with the predefined `INVERT_MATRIX`.
```typescript
import { INVERT_MATRIX, TargetChannel } from "@opentui/core"
frameBuffer.colorMatrixUniform(INVERT_MATRIX, 1.0, TargetChannel.Both)
```
--------------------------------
### Resolve Slot Entries and Renderers
Source: https://opentui.com/docs/plugins/slots
Use `resolveEntries` to get plugin IDs and their renderers, or `resolve` for just the renderer callbacks.
```javascript
const entries = registry.resolveEntries("statusbar")
// Array<{ id: string, renderer: (ctx, props) => TNode }>
const slotRenderers = registry.resolve("statusbar")
// Array<(ctx, props) => TNode>
```
--------------------------------
### Create a 'Hello World' OpenTUI App
Source: https://opentui.com/docs/getting-started
Renders 'Hello, OpenTUI!' in green text to the terminal. Press Ctrl+C to exit.
```typescript
import { createCliRenderer, Text } from "@opentui/core"
const renderer = await createCliRenderer({
exitOnCtrlC: true,
})
renderer.root.add(
Text({
content: "Hello, OpenTUI!",
fg: "#00FF00",
}),
)
```
--------------------------------
### Sequence Pattern Runtime Predicate
Source: https://opentui.com/docs/keymap/core
Example of a `match` function within a sequence pattern that returns a captured value or undefined.
```javascript
match: runtimeEventPredicate
```
--------------------------------
### Vertical Slider
Source: https://opentui.com/docs/components/slider
Renders a vertical slider. This example demonstrates setting the orientation to 'vertical' and adjusting dimensions for a vertical layout.
```typescript
const slider = new SliderRenderable(renderer, {
orientation: "vertical",
width: 2,
height: 10,
min: 0,
max: 1,
value: 0.5,
})
```
--------------------------------
### Configure Bun Preload Script
Source: https://opentui.com/docs/bindings/solid
Add the OpenTUI Solid preload script to your `bunfig.toml` for runtime integration.
```toml
preload = ["@opentui/solid/preload"]
```
--------------------------------
### Automatic Render Mode
Source: https://opentui.com/docs/core-concepts/renderer
The default render mode where the renderer re-renders only when the component tree changes. No explicit start call is needed.
```typescript
const renderer = await createCliRenderer()
renderer.root.add(Text({ content: "Static content" })) // Triggers render
```
--------------------------------
### Constructing Keymap Engine with Custom Host
Source: https://opentui.com/docs/keymap/hosts
Implement the `KeymapHost` interface yourself and construct the engine directly when neither built-in host fits your runtime. Ensure custom hosts provide conservative metadata.
```typescript
import { Keymap, type KeymapHost } from "@opentui/keymap"
const keymap = new Keymap(host as KeymapHost