# React API Reference
## Rendering
### createRoot(renderer)
Creates a React root for rendering.
```tsx
import { createCliRenderer } from "@opentui/core"
import { createRoot } from "@opentui/react"
const renderer = await createCliRenderer({
exitOnCtrlC: false, // Handle Ctrl+C yourself
})
const root = createRoot(renderer)
root.render()
```
## Hooks
### useRenderer()
Access the OpenTUI renderer instance.
```tsx
import { useRenderer } from "@opentui/react"
import { useEffect } from "react"
function App() {
const renderer = useRenderer()
useEffect(() => {
// Access renderer properties
console.log(`Terminal: ${renderer.width}x${renderer.height}`)
// Show debug console
renderer.console.show()
}, [renderer])
return Hello
}
```
### useKeyboard(handler, options?)
Handle keyboard events.
```tsx
import { useKeyboard, useRenderer } from "@opentui/react"
function App() {
const renderer = useRenderer()
useKeyboard((key) => {
if (key.name === "escape") {
renderer.destroy() // Never use process.exit() directly!
}
if (key.ctrl && key.name === "s") {
saveDocument()
}
})
return Press ESC to exit
}
// With release events
function GameControls() {
const [pressed, setPressed] = useState(new Set())
useKeyboard(
(event) => {
setPressed(keys => {
const newKeys = new Set(keys)
if (event.eventType === "release") {
newKeys.delete(event.name)
} else {
newKeys.add(event.name)
}
return newKeys
})
},
{ release: true } // Include release events
)
return Pressed: {Array.from(pressed).join(", ")}
}
```
**Options:**
- `release?: boolean` - Include key release events (default: false)
**KeyEvent properties:**
- `name: string` - Key name ("a", "escape", "f1", etc.)
- `sequence: string` - Raw escape sequence
- `ctrl: boolean` - Ctrl modifier
- `shift: boolean` - Shift modifier
- `meta: boolean` - Alt modifier
- `option: boolean` - Option modifier (macOS)
- `eventType: "press" | "release" | "repeat"`
- `repeated: boolean` - Key is being held
### useOnResize(callback)
Handle terminal resize events.
```tsx
import { useOnResize } from "@opentui/react"
function App() {
useOnResize((width, height) => {
console.log(`Resized to ${width}x${height}`)
})
return Resize the terminal
}
```
### useTerminalDimensions()
Get reactive terminal dimensions.
```tsx
import { useTerminalDimensions } from "@opentui/react"
function ResponsiveLayout() {
const { width, height } = useTerminalDimensions()
return (
80 ? "row" : "column"}>
Width: {width}
Height: {height}
)
}
```
### useTimeline(options?)
Create animations with the timeline system.
```tsx
import { useTimeline } from "@opentui/react"
import { useEffect, useState } from "react"
function AnimatedBox() {
const [width, setWidth] = useState(0)
const timeline = useTimeline({
duration: 2000,
loop: false,
})
useEffect(() => {
timeline.add(
{ width: 0 },
{
width: 50,
duration: 2000,
ease: "easeOutQuad",
onUpdate: (anim) => {
setWidth(Math.round(anim.targets[0].width))
},
}
)
}, [timeline])
return
}
```
**Options:**
- `duration?: number` - Default duration (ms)
- `loop?: boolean` - Loop the timeline
- `autoplay?: boolean` - Auto-start (default: true)
- `onComplete?: () => void` - Completion callback
- `onPause?: () => void` - Pause callback
**Timeline methods:**
- `add(target, properties, startTime?)` - Add animation
- `play()` - Start playback
- `pause()` - Pause playback
- `restart()` - Restart from beginning
## Components
### Text Component
```tsx
{/* Use nested modifier tags for styling */}
Red
Bold
Italic
Underline
Link
```
> **Note**: Do NOT use `bold`, `italic`, `underline` as props on ``. Use nested modifier tags like ``, ``, `` instead.
### Box Component
```tsx
{}}
onMouseUp={(e) => {}}
onMouseMove={(e) => {}}
>
{children}
```
### Scrollbox Component
```tsx
{/* Scrollable content */}
{items.map((item, i) => (
{item}
))}
```
### Input Component
```tsx
setValue(newValue)}
placeholder="Enter text..."
focused // Start focused
width={30}
backgroundColor="#1a1a1a"
textColor="#FFFFFF"
cursorColor="#00FF00"
focusedBackgroundColor="#2a2a2a"
/>
```
### Textarea Component
```tsx