跳转到内容

Terminal

此内容尚不支持你的语言。

A theme-aware terminal emulator component powered by xterm.js. Colors automatically adapt to light/dark themes using DaisyUI color tokens.

This component requires @xterm/xterm and @xterm/addon-fit as peer dependencies:

Terminal window
npm install @xterm/xterm @xterm/addon-fit
import { Terminal } from 'asterui/terminal'

Readline Mode

Built-in line editing with arrow keys and command history.

import { Terminal } from 'asterui/terminal'

function App() {
  const terminalRef = useRef<TerminalRef>(null)
  
  return (
      <Terminal
        ref={terminalRef}
        readline
        prompt={'\x1b[32m$ \x1b[0m'}
        onReady={(term) => {
          term.writeln('Welcome to AsterUI Terminal!')
          term.writeln('Type something and press Enter.')
          term.writeln('Use arrow keys for line editing and history.')
        }}
        style={{ height: '100%' }}
      />
    )
}

export default App

Command Handler

Use onLine callback to handle commands in readline mode.

import { Terminal, type TerminalRef } from 'asterui/terminal'
import { useRef } from 'react'

function App() {
  const terminalRef = useRef<TerminalRef>(null)
  
  const handleLine = (line: string) => {
    const term = terminalRef.current
    if (!term) return
  
    const cmd = line.trim().toLowerCase()
    if (cmd === 'help') {
      term.writeln('Available commands: help, date, clear, hello')
    } else if (cmd === 'date') {
      term.writeln(new Date().toString())
    } else if (cmd === 'clear') {
      term.clear()
    } else if (cmd === 'hello') {
      term.writeln('\x1b[36mHello, World!\x1b[0m')
    } else if (cmd) {
      term.writeln(`\x1b[31mUnknown command: ${cmd}\x1b[0m`)
    }
  }
  
  return (
      <Terminal
        ref={terminalRef}
        readline
        prompt={'\x1b[33m>\x1b[0m '}
        onLine={handleLine}
        onReady={(term) => {
          term.writeln('Simple command shell. Type "help" for commands.')
        }}
        style={{ height: '100%' }}
      />
    )
}

export default App

Ref Methods

Control the terminal programmatically via ref.

import { Terminal, type TerminalRef } from 'asterui/terminal'
import { useRef } from 'react'

function App() {
  const terminalRef = useRef<TerminalRef>(null)
  
  const handleWrite = () => {
    terminalRef.current?.writeln('Hello from button!')
  }
  
  const handleClear = () => {
    terminalRef.current?.clear()
  }
  
  return (
      <div className="flex flex-col gap-2 h-full">
        <div className="flex gap-2">
          <button className="d-btn d-btn-sm d-btn-primary" onClick={handleWrite}>
            Write Line
          </button>
          <button className="d-btn d-btn-sm d-btn-secondary" onClick={handleClear}>
            Clear
          </button>
        </div>
        <div className="flex-1">
          <Terminal ref={terminalRef} style={{ height: '100%' }} />
        </div>
      </div>
    )
}

export default App

Custom Options

Pass xterm.js options for customization.

import { Terminal } from 'asterui/terminal'

function App() {
  return (
      <Terminal
        options={{
          fontSize: 16,
          fontFamily: '"Fira Code", monospace',
          cursorBlink: false,
          cursorStyle: 'block',
        }}
        onReady={(term) => {
          term.writeln('Custom terminal with Fira Code font')
          term.writeln('fontSize: 16, cursorStyle: block')
        }}
        style={{ height: '100%' }}
      />
    )
}

export default App

ANSI Colors

Terminal supports ANSI escape codes for colored output.

import { Terminal } from 'asterui/terminal'

function App() {
  return (
      <Terminal
        onReady={(term) => {
          term.writeln('\x1b[1mBold text\x1b[0m')
          term.writeln('\x1b[31mRed text\x1b[0m')
          term.writeln('\x1b[32mGreen text\x1b[0m')
          term.writeln('\x1b[33mYellow text\x1b[0m')
          term.writeln('\x1b[34mBlue text\x1b[0m')
          term.writeln('\x1b[35mMagenta text\x1b[0m')
          term.writeln('\x1b[36mCyan text\x1b[0m')
          term.writeln('')
          term.writeln('\x1b[42m\x1b[30m Green background \x1b[0m')
          term.writeln('\x1b[44m\x1b[37m Blue background \x1b[0m')
        }}
        style={{ height: '100%' }}
      />
    )
}

export default App
PropertyDescriptionTypeDefault
readlineEnable readline mode with line editing and historybooleanfalse
promptPrompt string for readline mode (supports ANSI colors)string'$ '
onLineCallback when user submits a line in readline mode(line: string) => void-
onDataCallback for raw input (not used in readline mode)(data: string) => void-
onReadyCallback when terminal is initialized(terminal: XTerm) => void-
optionsxterm.js options (theme is auto-applied)ITerminalOptions-
classNameAdditional CSS classesstring-
styleContainer styleReact.CSSProperties-
data-testidTest ID for testingstring-

Access via useRef<TerminalRef>():

PropertyDescriptionType
terminalThe underlying xterm.js Terminal instanceXTerm | null
writeWrite data to the terminal(data: string) => void
writelnWrite a line to the terminal (with newline)(data: string) => void
clearClear the terminal() => void
focusFocus the terminal() => void
fitFit the terminal to its container() => void
historyCommand history array (readline mode)string[]
clearHistoryClear command history() => void

When readline is enabled, the terminal provides:

  • Left/Right arrows: Move cursor within the current line
  • Up/Down arrows: Navigate command history
  • Backspace: Delete character before cursor
  • Ctrl+C: Cancel current input
  • Enter: Submit line (triggers onLine callback)

The Terminal component automatically uses DaisyUI theme colors:

  • Background/Foreground: Uses base-100 and base-content
  • Cursor: Uses primary color
  • ANSI Colors: Maps to error, success, warning, info, secondary, accent

When the theme changes (light/dark), the terminal colors update automatically.

import { Terminal, type TerminalRef } from 'asterui/terminal'
import { useRef, useEffect } from 'react'
function WebSocketTerminal({ url }: { url: string }) {
const terminalRef = useRef<TerminalRef>(null)
const wsRef = useRef<WebSocket | null>(null)
useEffect(() => {
const ws = new WebSocket(url)
wsRef.current = ws
ws.onmessage = (event) => {
terminalRef.current?.write(event.data)
}
return () => ws.close()
}, [url])
return (
<Terminal
ref={terminalRef}
onData={(data) => wsRef.current?.send(data)}
style={{ height: 400 }}
/>
)
}
  • Terminal is keyboard accessible and focusable
  • Supports screen reader announcements for terminal output
  • High contrast themes work automatically via DaisyUI theme integration