Quickstart: React Mode
Build a TUI app with React components, hooks, and Yoga layout using @visulima/tui/react
Quickstart: React Mode
Build a TUI app with React components, hooks, and Yoga layout.
npm install @visulima/tui reactMinimal Example
import { render, Box, Text, useInput } from "@visulima/tui/react";
import React, { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
useInput((_input, key) => {
if (key.upArrow) setCount((c) => c + 1);
if (key.downArrow) setCount((c) => c - 1);
});
return (
<Box flexDirection="column" padding={1}>
<Text bold color="cyan">
Counter
</Text>
<Text>Count: {count}</Text>
<Text dim>↑↓ to change · Ctrl+C to exit</Text>
</Box>
);
}
render(<Counter />);Run it:
node --import @oxc-node/core/register app.tsxRender Path
render(<App />)mounts your tree into Yoga layout nodes- React commits set a dirty flag
- A frame loop checks the dirty flag at
maxFps(default 60) - Dirty frames run layout + paint into
Uint32Array - Rust diff emits only changed terminal cells as ANSI
Layout: Box
Box is the main layout primitive.
<Box flexDirection="row" gap={2} padding={1}>
<Box flexDirection="column" flexGrow={1} borderStyle="round">
<Text>Left panel</Text>
</Box>
<Box flexDirection="column" width={30} borderStyle="single">
<Text>Right panel</Text>
</Box>
</Box>Common props: flexDirection, flexGrow, flexShrink, width, height, padding, margin, gap, alignItems, justifyContent, borderStyle.
Text Styling
<Text color="cyan" bold>Bold cyan text</Text>
<Text color="#ff6600">Hex color</Text>
<Text backgroundColor="blue" color="white">Highlighted</Text>
<Text italic dim>Dim italic</Text>Color accepts named values, #rrggbb, rgb(r,g,b), and ANSI 256-color indices (0-255).
Keyboard Input
useInput((input, key) => {
if (key.upArrow) moveUp();
if (key.downArrow) moveDown();
if (key.return) submit();
if (key.escape) cancel();
if (key.ctrl && input === "c") exit();
});See Hooks: useInput for the full key map.
App Lifecycle
import { useApp, useInput, Text } from "@visulima/tui/react";
function App() {
const { exit } = useApp();
useInput((_input, key) => {
if (key.escape) exit();
});
return <Text>Press Esc to quit</Text>;
}useApp() returns both exit() and quit().
render() Options and Return Value
const { rerender, unmount, waitUntilExit } = render(<App />, {
maxFps: 30, // default 60
});
rerender(<App theme="dark" />);
unmount();
await waitUntilExit();renderToString for Tests
import { renderToString, Box, Text } from "@visulima/tui/react";
import React from "react";
const output = renderToString(
<Box>
<Text color="green">hello</Text>
</Box>,
);
// output: 'hello'