Bunli
Packages

@bunli/tui

React-based Terminal UI component library for Bunli

Overview

@bunli/tui is a React-based Terminal User Interface library for Bunli CLI applications, powered by OpenTUI. It provides 40+ components for building full-screen TUI applications in the terminal.

Installation

bun add @bunli/tui @bunli/runtime

Features

  • 40+ Components - Forms, layouts, navigation, feedback, data display
  • Chart Primitives - BarChart, LineChart, Sparkline
  • Theme System - Dark/light themes with token customization
  • Keyboard Navigation - Full terminal keyboard support
  • Form Validation - Built-in validation via Standard Schema/Zod

Package Structure

ExportDescription
@bunli/tuiMain - components, hooks, theme utilities
@bunli/tui/inlineInline-mode components (List, Table, Markdown, Diff)
@bunli/tui/interactiveInteractive components with theme providers
@bunli/tui/chartsChart primitives (BarChart, LineChart, Sparkline)
@bunli/tui/utils/sync-batcherAction batching utility

Form Components

Build interactive forms with validation:

import { Form, TextField, SelectField, NumberField } from "@bunli/tui";
import { z } from "zod";

const schema = z.object({
  name: z.string().min(1),
  age: z.number().int().positive(),
  role: z.enum(["admin", "user", "guest"]),
});

function UserForm({ onSubmit }) {
  return (
    <Form title="User Registration" schema={schema} onSubmit={(values) => onSubmit(values)}>
      <TextField name="name" label="Name" />
      <NumberField name="age" label="Age" />
      <SelectField
        name="role"
        label="Role"
        options={[
          { label: "Admin", value: "admin" },
          { label: "User", value: "user" },
          { label: "Guest", value: "guest" },
        ]}
      />
    </Form>
  );
}

Available Form Fields

ComponentDescription
TextFieldSingle-line text input
NumberFieldNumeric input with validation
PasswordFieldHidden text input with reveal
TextareaFieldMulti-line text input
SelectFieldSingle selection dropdown
MultiSelectFieldMultiple selection
CheckboxFieldBoolean toggle

Layout Components

Structure your TUI application:

import { Container, Stack, Grid, Panel, Card } from "@bunli/tui";

function Dashboard() {
  return (
    <Container>
      <Stack direction="column" gap={1}>
        <Panel title="Header" />
        <Grid columns={2} gap={1}>
          <Card title="Metric 1" />
          <Card title="Metric 2" />
        </Grid>
        <Panel title="Details" footer="Footer" />
      </Stack>
    </Container>
  );
}

Layout Components

ComponentDescription
ContainerOuter container with optional border
StackFlexbox-like column/row layout
GridMulti-column grid layout
PanelTitled panel with header/footer
CardSimplified panel variant
ScrollPanelScrollable panel with sticky header/footer
DividerHorizontal/vertical divider
SectionHeaderSection title with subtitle
SidebarLayoutThree-pane layout (sidebar/content/inspector)

Interactive navigation and selection:

import { Tabs, Menu, NavList, CommandPalette } from "@bunli/tui";

// Tabbed navigation
function TabExample() {
  return (
    <Tabs
      tabs={[
        { key: "overview", label: "Overview", content: <div>...</div> },
        { key: "settings", label: "Settings", content: <div>...</div> },
      ]}
    />
  );
}

// Command palette
function CommandExample({ commands }) {
  return (
    <CommandPalette
      items={commands.map((cmd) => ({
        key: cmd.id,
        label: cmd.title,
        hint: cmd.hint,
      }))}
      onSelect={(key) => runCommand(key)}
    />
  );
}
ComponentDescription
TabsTabbed interface
MenuKeyboard-navigable menu
NavListEnhanced navigation list with sections
CommandPaletteFuzzy-searchable command list
ModalModal dialog overlay
ConfirmYes/No confirmation dialog
ChooseSingle/multiple selection list
FilterFuzzy-filtered selection
PagerScrollable content viewer
FilePickerDirectory browser

Feedback Components

Display status and information:

import { Alert, Badge, ProgressBar, Spinner, Toast, EmptyState } from "@bunli/tui";

// Status display
function StatusPanel() {
  return (
    <Stack gap={1}>
      <Alert tone="success" message="Deployment complete!" />
      <ProgressBar value={75} label="Uploading..." />
      <Spinner variant="dots" title="Loading..." />
      <Badge label="Active" tone="success" />
    </Stack>
  );
}

Feedback Components

ComponentDescription
AlertInformational alert with tones
BadgeStatus badge/tag
ToastTransient notification
ProgressBarProgress indicator
SpinnerLoading spinner (12 variants)
EmptyStateEmpty state with icon
KeyValueListKey-value pair display
StatStatistic display
DataTableTabular data display

Chart Components

ASCII charts for data visualization:

import { BarChart, LineChart, Sparkline } from "@bunli/tui/charts";

// Bar chart
function Metrics() {
  return (
    <BarChart
      series={{
        name: "Revenue",
        points: [
          { label: "Jan", value: 100 },
          { label: "Feb", value: 150 },
          { label: "Mar", value: 120 },
        ],
      }}
      width={40}
    />
  );
}

// Inline sparkline
function Trend({ values }) {
  return <Sparkline values={values} width={20} />;
}

Chart Components

ComponentDescription
BarChartASCII bar chart with series
LineChartLine chart with multiple series
SparklineCompact inline sparkline

Hooks

React hooks for terminal UI:

import { useKeyboard, useTerminalDimensions, useTimeline } from "@opentui/react";
import { useTuiTheme } from "@bunli/runtime/app";
import { useFormField } from "@bunli/tui";

function KeyboardExample() {
  useKeyboard({
    "Ctrl+C": () => exit(),
    "Ctrl+S": () => save(),
    "g h": () => goHome(),
    "g g": () => goTop(),
  });

  const { width, height } = useTerminalDimensions();
  console.log(`Terminal: ${width}x${height}`);
}

function FormFieldExample() {
  const field = useFormField("name");
  return (
    <TextField label="Name" value={field.value} onChange={field.setValue} error={field.error} />
  );
}

Available Hooks

HookPackageDescription
useKeyboard@opentui/reactGlobal keyboard handler
useTerminalDimensions@opentui/reactTerminal size
useTimeline@opentui/reactAnimation timeline
useOnResize@opentui/reactResize handler
useTuiTheme@bunli/runtime/appTheme tokens
useFormField@bunli/tuiForm field binding
useScopedKeyboard@bunli/runtime/appScoped keyboard handler
useRuntime@bunli/runtime/appRuntime exit function
useRouteStore@bunli/runtime/appNavigation state
useCommandRegistry@bunli/runtime/appCommand registry
useDialogManager@bunli/runtime/appDialog controls

Theme System

Customize colors and appearance:

import { ThemeProvider, createTheme, darkThemeTokens, lightThemeTokens } from "@bunli/runtime/app";

// Dark theme (default)
const dark = createTheme({ preset: "dark" });

// Light theme
const light = createTheme({
  preset: "light",
  tokens: {
    ...lightThemeTokens,
    accent: "#0066cc",
  },
});

// Custom theme
const custom = createTheme({
  tokens: {
    bg: "#1a1a2e",
    fg: "#eaeaea",
    accent: "#00d4aa",
  },
});

function App() {
  return (
    <ThemeProvider theme={custom}>
      <YourUI />
    </ThemeProvider>
  );
}

Keyboard Shortcuts

Most interactive components support keyboard navigation:

ComponentKeys
MenuUp/k, Down/j, Enter
NavListUp/k, Down/j, Enter
TabsLeft/h, Right/l
ConfirmLeft/h, Right/l, y/n
ChooseUp/k, Down/j, Space, Enter
FilterUp, Down, Tab, Ctrl+A
Pagerj/k, d/u, /, n/N, g/G, q
DataTableUp/k, Down/j, Left/h, Right/l

See Also

On this page