Glyph Glyph

React renderer
for terminal UIs

React renderer for the terminal. Components, flexbox, focus management, keyboard input, diff-based rendering. If you've built a React app, you already know how this works.

// app.tsx
import { render, Box, Text } from "@semos-labs/glyph";

function App() {
  return (
    <Box border="round" padding={1}>
      <Text bold>Hello, Glyph!</Text>
    </Box>
  );
}

render(<App />);

Quick Start

Create a new project

$ bun create @semos-labs/glyph my-app $ cd my-app && bun dev

Add to existing project

$ bun add @semos-labs/glyph react

Features

⊞

Flexbox Layout

CSS-like flexbox via Yoga. Rows, columns, wrapping, alignment, gaps, padding — it all works.

◧

Rich Components

Box, Text, Input, Button, Checkbox, Radio, Select, ScrollView, List, Menu, Progress, Spinner, Image, Toasts, Dialogs, and more.

⎆

Focus System

Tab navigation, focus scopes, focus trapping for modals, JumpNav quick-jump hints.

⌨

Keyboard Input

useInput hook, declarative <Keybind> component, vim-style bindings, priority keybinds.

▦

Smart Rendering

Double-buffered with character-level diffing. Only changed cells get written to the terminal.

◉

True Colors

Named colors, hex, RGB, 256-palette. Auto-contrast text on colored backgrounds.

▢

Borders & Styling

Single, double, rounded, and ASCII border styles. Bold, dim, italic, underline text.

◇

TypeScript First

Every prop, style, and hook is typed. No guessing.

Components

<Box>

Flexbox container — the fundamental building block

<Text>

Styled text with ANSI escape code support

<Input>

Text input with masks, multiline, and validation

<Button>

Focusable button with press handling

<Select>

Dropdown with type-to-filter search

<List>

Keyboard-navigable selection list

<ScrollView>

Scrollable container with virtualization

<Image>

Inline images via Kitty/iTerm2 protocol

<Menu>

Styled menu with labels and disabled items

<Portal>

Fullscreen overlay for modals

<JumpNav>

Vimium-style quick navigation hints

<DialogHost>

Imperative alert() and confirm() dialogs