Skip to content

Repository files navigation

TextUI

A dependency-free TypeScript terminal UI runtime. Screens are plain data; JSX is one way to write them.

import { createApp, registerBuiltins } from '@textui/core';
import { createNodeTerminal } from '@textui/terminal';

const app = createApp({
  terminal: createNodeTerminal(),
  root: <Dashboard />,
  onBoot: registerBuiltins,
});

await app.start();

Status: pre-1.0. The surface is still moving.

The one idea

JSX compiles to data. <Row gap={1}/> and { component: 'Row', gap: 1 } are the same value, and the runtime mounts either. A screen can be written in TypeScript, loaded from JSON, generated, edited or sent over a wire without the runtime changing - and components are resolved by name at mount time, so what renders is a registration rather than an import.

Everything else follows from that: one reactive store addressed by paths, typed registries for components, commands, themes, shells and resources, and a renderer that diffs cells rather than redrawing frames.

Packages

Package What it is
@textui/core The runtime: store, registries, renderer, hooks, component catalog
@textui/terminal Terminal adapters, capability detection, ANSI writing, input decoding
@textui/testing Headless harness: semantic queries, input, resizing, time
@textui/cli textui init / add / create / doctor, and primitives for your own CLI
components/ The source-copy registry - components you own, not import
playground/ The showcase, fourteen focused playgrounds, and a filesystem explorer

Documentation

Published at https://softov.github.io/textui/, and readable in docs/ as plain markdown.

Start here:

Document What it answers
Getting started From nothing to a running application
The vocabulary The words everything else assumes
Architecture The model: store, graph, registries, surfaces, shells
Decisions and tradeoffs What was chosen, and what it cost

Then by subsystem:

Section What it covers
Store Paths, scopes, computed, collections, providers, events
Components The catalog, how to write one, and the templates
Themes Tokens, glyphs, borders, capability downgrade, syntax
Platform Commands, keybindings, focus, layers, screens, extension points
Terminal Adapters, capabilities, managed and embedded sessions
Documents Resource kinds, providers, viewers, editors, buffers
CLI The developer CLI and the registry model
Testing The harness, and what to assert

Development

pnpm install
pnpm build          # every package
pnpm typecheck      # every workspace
pnpm test           # every suite
pnpm dev --list     # the playgrounds
pnpm dev gallery    # open one

The docs site is Jekyll, and needs no Ruby on your machine - it builds in a container:

scripts/docs-serve.sh           # live, with reload, at localhost:4000/textui/
scripts/docs-serve.sh --build   # build once, into docs/_site
scripts/docs-preview.py         # serve what was built, at localhost:8000/textui/
scripts/docs-preview.py --host 0.0.0.0   # ...and reachable from the network
node scripts/check-docs.mjs     # the nav tree, links and titles

docs-preview.py exists because the site is built with baseurl: /textui, so every link in it is absolute at /textui/.... A plain python -m http.server over docs/_site 404s on all of it; this one mounts the site under the prefix the pages actually ask for.

Node ≥ 22, pnpm 10.

The acceptance test

The three layouts this project started from - a dense bordered console, an airy borderless report, and a workbench frame - are one architecture with three registrations. playground/test/playgrounds.test.tsx mounts the same component under all of them, and under six themes, at three terminal widths, with and without Unicode and colour. If a shell ever needs a component the others cannot use, the boundary is in the wrong place.

License

MIT

About

A dependency-free TypeScript terminal UI runtime. Screens are plain data; JSX is one way to write them.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages