Ink Web

Text Input

A terminal text input component with keyboard handling, placeholder support, and customizable prompt.

Terminal

Installation

npx shadcn@latest add https://raw.githubusercontent.com/cjroth/ink-web/main/packages/ink-ui/registry/text-input.json
npx shadcn@latest add https://raw.githubusercontent.com/cjroth/ink-web/main/packages/ink-ui/registry/text-input.json
pnpm dlx shadcn@latest add https://raw.githubusercontent.com/cjroth/ink-web/main/packages/ink-ui/registry/text-input.json
bunx shadcn@latest add https://raw.githubusercontent.com/cjroth/ink-web/main/packages/ink-ui/registry/text-input.json

Usage

app/page.tsx
"use client";

import dynamic from "next/dynamic";

const Terminal = dynamic(() => import("./terminal"), {
  ssr: false,
});

export default function Home() {
  return <Terminal />;
}
app/terminal.tsx
"use client";

import { Box, Text } from "ink";
import { InkXterm } from "ink-web";
import { TextInput } from '@/components/ui/text-input'
import "ink-web/css";
import "xterm/css/xterm.css";
import { useState } from "react";

export default function Terminal() {
  const [history, setHistory] = useState<string[]>([]);

  return (
    <InkXterm focus>
      <Box flexDirection="column">
        {history.map((item, i) => (
          <Text key={i}>{item}</Text>
        ))}
        <TextInput
          onSubmit={(value) => setHistory((prev) => [...prev, value])}
          placeholder="Type here..."
        />
      </Box>
    </InkXterm>
  )
}

useTextInput Hook

The useTextInput hook manages input state and history for you:

import { useTextInput } from '@/components/ui/text-input'

const { value, setValue, history, clear, clearHistory } = useTextInput({
  onSubmit: (value) => console.log('Submitted:', value)
})

Hook Return Values

PropertyTypeDescription
valuestringCurrent input value
setValue(value: string) => voidSet the input value
historystring[]Array of submitted values
clear() => voidClear current input
clearHistory() => voidClear history array

TextInput Props

PropTypeDefaultDescription
valuestring-Controlled input value
onChange(value: string) => void-Called when input value changes
onSubmit(value: string) => void-Called when Enter is pressed
placeholderstring""Placeholder text when empty
promptstring"> "Prompt string before input
promptColorstring"cyan"Color of the prompt
cursorColorstring-Color of the cursor
focusbooleantrueWhether input is focused

Examples

Basic Input

<TextInput onSubmit={(value) => console.log(value)} />

With Placeholder

<TextInput
  placeholder="Enter your name..."
  onSubmit={(value) => console.log(value)}
/>

Custom Prompt

<TextInput
  prompt="$ "
  promptColor="green"
  onSubmit={(value) => console.log(value)}
/>

Controlled Input

const [value, setValue] = useState('')

<TextInput
  value={value}
  onChange={setValue}
  onSubmit={(value) => {
    console.log(value)
    setValue('')
  }}
/>

With History

const [history, setHistory] = useState<string[]>([])

<Box flexDirection="column">
  {history.map((item, i) => (
    <Text key={i}>{item}</Text>
  ))}
  <TextInput
    onSubmit={(value) => setHistory((prev) => [...prev, value])}
  />
</Box>