Ink Web
Guides

Terminal Components

API reference for InkTerminalBox and InkXterm components

ink-web provides two main components for rendering Ink applications in the browser: InkTerminalBox and InkXterm. These components handle the xterm.js integration and provide a terminal-like environment for your Ink components.

InkTerminalBox

A higher-level component that wraps InkXterm with styling, CSS isolation, and loading state support. This is the recommended component for most use cases.

import { InkTerminalBox, Box, Text } from "ink-web";
import "ink-web/css";
import "xterm/css/xterm.css";

export function MyTerminal() {
  return (
    <InkTerminalBox rows={10} focus>
      <Box flexDirection="column">
        <Text color="green">Hello from Ink!</Text>
      </Box>
    </InkTerminalBox>
  );
}

Props

PropTypeDefaultDescription
childrenReact.ReactElementRequiredThe Ink component tree to render
classNamestring""Additional CSS class for the container
focusbooleantrueWhether to focus the terminal on mount
termOptionsITerminalOptions{}xterm.js terminal options
rowsnumberundefinedNumber of rows to display. Sets a fixed height.
onReady() => voidundefinedCallback fired when terminal is fully initialized
loadingReact.ReactNodeundefinedLoading indicator shown while terminal initializes

Features

  • CSS Isolation: Resets inherited styles to prevent parent CSS from affecting terminal rendering
  • Loading States: Show a custom loading indicator while xterm.js initializes
  • Fixed Height: Use rows prop to set consistent height across SSR and client
  • Automatic Sizing: Automatically fits to container and handles resize events

Example with Loading State

import { InkTerminalBox, Box, Text } from "ink-web";
import { Loader2 } from "lucide-react";

export function MyTerminal() {
  return (
    <InkTerminalBox
      rows={15}
      focus
      loading={<Loader2 className="h-6 w-6 animate-spin text-gray-400" />}
      onReady={() => console.log("Terminal ready!")}
    >
      <Box flexDirection="column">
        <Text>Terminal content</Text>
      </Box>
    </InkTerminalBox>
  );
}

InkXterm

A lower-level component that directly integrates xterm.js with Ink. Use this when you need more control or don't want the additional styling from InkTerminalBox.

import { InkXterm, Box, Text } from "ink-web";
import "xterm/css/xterm.css";

export function MyTerminal() {
  return (
    <InkXterm focus>
      <Box flexDirection="column">
        <Text>Hello World</Text>
      </Box>
    </InkXterm>
  );
}

Props

PropTypeDefaultDescription
childrenReact.ReactElementRequiredThe Ink component tree to render
classNamestring""CSS class for the container div
focusbooleantrueWhether to focus the terminal on mount
termOptionsITerminalOptions{}xterm.js terminal options
onReady() => voidundefinedCallback fired when terminal is fully initialized

Initialization Behavior

InkXterm uses a robust initialization strategy:

  1. requestAnimationFrame: Waits for the browser's next paint cycle to ensure the DOM is ready
  2. Dimension Check: Verifies the container has non-zero dimensions
  3. ResizeObserver: If dimensions aren't ready, observes for when they become available

This approach ensures reliable initialization without arbitrary timeouts.

mountInkInXterm

For advanced use cases, you can use the mountInkInXterm function directly to create your own terminal integration.

import { mountInkInXterm, Box, Text } from "ink-web";

const container = document.getElementById("terminal");

const { term, unmount } = mountInkInXterm(
  <Box>
    <Text>Hello</Text>
  </Box>,
  {
    container,
    focus: true,
    termOptions: { fontSize: 14 },
    onReady: () => console.log("Ready!"),
  }
);

// Later, to cleanup:
await unmount();

Options

OptionTypeDescription
containerHTMLElementDOM element to mount the terminal in
focusbooleanWhether to focus the terminal
termOptionsITerminalOptionsxterm.js terminal options
onReady() => voidCallback when terminal is ready

Return Value

PropertyTypeDescription
termTerminalThe xterm.js Terminal instance
unmount() => Promise<void>Cleanup function

Terminal Options

Both components accept termOptions which are passed to xterm.js. Common options include:

<InkTerminalBox
  termOptions={{
    fontSize: 14,
    fontFamily: "Menlo, Monaco, 'Courier New', monospace",
    cursorBlink: true,
    theme: {
      background: "#1a1a1a",
      foreground: "#ffffff",
    },
  }}
>
  {/* ... */}
</InkTerminalBox>

See the xterm.js documentation for all available options.

Choosing Between Components

Use CaseRecommended Component
Standard terminal UIInkTerminalBox
Need loading statesInkTerminalBox
SSR/Next.js appsInkTerminalBox
Custom styling/no CSS resetInkXterm
Advanced/custom integrationmountInkInXterm