0
# Ink
1
2
Ink is a React-like framework for building command-line interfaces that brings the familiar component-based development experience of React to terminal applications. It provides a comprehensive set of UI components powered by Facebook's Yoga layout engine to enable Flexbox-style layouts in the terminal, making it possible to create interactive CLI tools with real-time UI updates, focus management, and sophisticated terminal-based interfaces.
3
4
## Package Information
5
6
- **Package Name**: ink
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install ink react`
10
11
## Core Imports
12
13
```typescript
14
import { render, Box, Text, useInput, useApp } from "ink";
15
```
16
17
For type imports:
18
19
```typescript
20
import {
21
render,
22
Box,
23
Text,
24
useInput,
25
useApp,
26
type AppProps,
27
type StdinProps,
28
type StdoutProps,
29
type StderrProps
30
} from "ink";
31
```
32
33
For CommonJS:
34
35
```javascript
36
const { render, Box, Text, useInput, useApp } = require("ink");
37
```
38
39
## Basic Usage
40
41
```typescript
42
import React, { useState } from "react";
43
import { render, Box, Text, useInput, useApp } from "ink";
44
45
function Counter() {
46
const [count, setCount] = useState(0);
47
const { exit } = useApp();
48
49
useInput((input, key) => {
50
if (input === "q") {
51
exit();
52
}
53
54
if (key.upArrow) {
55
setCount(count + 1);
56
}
57
58
if (key.downArrow) {
59
setCount(count - 1);
60
}
61
});
62
63
return (
64
<Box>
65
<Text color="green">Counter: {count}</Text>
66
<Text dimColor> (Use ↑/↓ to change, 'q' to quit)</Text>
67
</Box>
68
);
69
}
70
71
// Render the app
72
render(<Counter />);
73
```
74
75
## Architecture
76
77
Ink is built around several key components:
78
79
- **React Reconciler**: Custom React renderer for terminal output instead of DOM
80
- **Yoga Layout Engine**: Facebook's Flexbox implementation for terminal layouts
81
- **Component System**: React-like components (Box, Text) with styling props
82
- **Hook System**: React hooks for input handling, focus management, and app lifecycle
83
- **Virtual DOM**: Custom DOM implementation optimized for terminal rendering
84
- **Event System**: Keyboard input parsing and event handling for interactive CLIs
85
86
## Capabilities
87
88
### Application Rendering
89
90
Core functionality for mounting and rendering React component trees to the terminal with full lifecycle management.
91
92
```typescript { .api }
93
function render(
94
node: ReactNode,
95
options?: NodeJS.WriteStream | RenderOptions
96
): Instance;
97
98
interface RenderOptions {
99
stdout?: NodeJS.WriteStream; // default: process.stdout
100
stdin?: NodeJS.ReadStream; // default: process.stdin
101
stderr?: NodeJS.WriteStream; // default: process.stderr
102
debug?: boolean; // default: false
103
exitOnCtrlC?: boolean; // default: true
104
patchConsole?: boolean; // default: true
105
}
106
107
interface Instance {
108
rerender: (node: ReactNode) => void;
109
unmount: () => void;
110
waitUntilExit: () => Promise<void>;
111
cleanup: () => void;
112
clear: () => void;
113
}
114
```
115
116
[Application Rendering](./rendering.md)
117
118
### Layout Components
119
120
Essential components for building terminal layouts using Flexbox-style positioning and styling.
121
122
```typescript { .api }
123
// Primary layout container component
124
function Box(props: BoxProps & { children?: ReactNode }): JSX.Element;
125
126
// Text display component with styling options
127
function Text(props: TextProps & { children?: ReactNode }): JSX.Element;
128
129
interface BoxProps {
130
// Flexbox layout properties
131
flexDirection?: "row" | "column" | "row-reverse" | "column-reverse";
132
flexWrap?: "nowrap" | "wrap" | "wrap-reverse";
133
flexGrow?: number;
134
flexShrink?: number;
135
justifyContent?: "flex-start" | "flex-end" | "center" | "space-between" | "space-around" | "space-evenly";
136
alignItems?: "flex-start" | "center" | "flex-end" | "stretch";
137
// [Additional layout properties...]
138
}
139
140
interface TextProps {
141
color?: string;
142
backgroundColor?: string;
143
bold?: boolean;
144
italic?: boolean;
145
underline?: boolean;
146
strikethrough?: boolean;
147
wrap?: "wrap" | "truncate-end" | "truncate-start" | "truncate-middle";
148
}
149
```
150
151
[Layout Components](./components.md)
152
153
### User Input Handling
154
155
Comprehensive input handling system for creating interactive CLI applications with keyboard navigation and focus management.
156
157
```typescript { .api }
158
// Handle keyboard input with parsed key information
159
function useInput(
160
inputHandler: (input: string, key: Key) => void,
161
options?: { isActive?: boolean }
162
): void;
163
164
// Focus management for component navigation
165
function useFocus(options?: {
166
isActive?: boolean;
167
autoFocus?: boolean;
168
id?: string;
169
}): { isFocused: boolean; focus: (id: string) => void };
170
171
interface Key {
172
upArrow: boolean;
173
downArrow: boolean;
174
leftArrow: boolean;
175
rightArrow: boolean;
176
return: boolean;
177
escape: boolean;
178
ctrl: boolean;
179
shift: boolean;
180
tab: boolean;
181
backspace: boolean;
182
delete: boolean;
183
meta: boolean;
184
}
185
```
186
187
[User Input Handling](./hooks.md)
188
189
## Common Types
190
191
```typescript { .api }
192
// DOM element reference type for measuring and manipulation
193
interface DOMElement {
194
nodeName: string;
195
attributes: Record<string, any>;
196
childNodes: DOMNode[];
197
yogaNode?: YogaNode;
198
parentNode?: DOMElement;
199
style: Styles;
200
}
201
202
// Context Props types for hooks (also available as individual exports)
203
interface AppProps {
204
readonly exit: (error?: Error) => void;
205
}
206
207
interface StdinProps {
208
readonly stdin: NodeJS.ReadStream;
209
readonly setRawMode: (value: boolean) => void;
210
readonly isRawModeSupported: boolean;
211
readonly internal_exitOnCtrlC: boolean;
212
readonly internal_eventEmitter: EventEmitter;
213
}
214
215
interface StdoutProps {
216
readonly stdout: NodeJS.WriteStream;
217
readonly write: (data: string) => void;
218
}
219
220
interface StderrProps {
221
readonly stderr: NodeJS.WriteStream;
222
readonly write: (data: string) => void;
223
}
224
225
// Comprehensive styling interface based on Yoga layout
226
interface Styles {
227
// Layout
228
position?: "absolute" | "relative";
229
display?: "flex" | "none";
230
overflow?: "visible" | "hidden";
231
232
// Flexbox
233
flexDirection?: "row" | "column" | "row-reverse" | "column-reverse";
234
flexWrap?: "nowrap" | "wrap" | "wrap-reverse";
235
flexGrow?: number;
236
flexShrink?: number;
237
flexBasis?: number | string;
238
justifyContent?: "flex-start" | "flex-end" | "center" | "space-between" | "space-around" | "space-evenly";
239
alignItems?: "flex-start" | "center" | "flex-end" | "stretch";
240
alignSelf?: "flex-start" | "center" | "flex-end" | "auto";
241
242
// Dimensions
243
width?: number | string;
244
height?: number | string;
245
minWidth?: number | string;
246
minHeight?: number | string;
247
248
// Spacing
249
margin?: number;
250
marginX?: number;
251
marginY?: number;
252
marginTop?: number;
253
marginBottom?: number;
254
marginLeft?: number;
255
marginRight?: number;
256
padding?: number;
257
paddingX?: number;
258
paddingY?: number;
259
paddingTop?: number;
260
paddingBottom?: number;
261
paddingLeft?: number;
262
paddingRight?: number;
263
gap?: number;
264
columnGap?: number;
265
rowGap?: number;
266
267
// Borders
268
borderStyle?: string;
269
borderTop?: boolean;
270
borderBottom?: boolean;
271
borderLeft?: boolean;
272
borderRight?: boolean;
273
borderColor?: string;
274
borderTopColor?: string;
275
borderBottomColor?: string;
276
borderLeftColor?: string;
277
borderRightColor?: string;
278
279
// Text
280
textWrap?: "wrap" | "truncate-end" | "truncate-start" | "truncate-middle" | "end" | "middle";
281
}
282
```