giggles

Getting Started

A framework for building interactive terminal user interfaces with React and Ink

giggles is a framework for building interactive terminal user interfaces (TUIs) with React and Ink. It provides a declarative, composable system for handling focus navigation and keyboard input in terminal applications.

Installation

Install giggles along with its peer dependencies:

npm install giggles ink react
pnpm add giggles ink react
yarn add giggles ink react

Verify requirements:

  • Node.js 16+
  • React 18+ or 19+
  • Ink 6+

Your First TUI

Here's a simple focusable menu that demonstrates giggles' core concepts:

menu.tsx
import { Box, Text, render } from 'ink';
import { GigglesProvider, FocusGroup, useFocus, useKeybindings } from 'giggles';

function MenuItem({ label }: { label: string }) {
  const focus = useFocus();

  return (
    <Box>
      <Text color={focus.isFocused ? 'green' : 'white'}>
        {focus.isFocused ? '> ' : '  '}
        {label}
      </Text>
    </Box>
  );
}

function Menu() {
  const focus = useFocus();

  useKeybindings(focus, {
    q: () => process.exit(0),
  });

  return (
    <Box flexDirection="column">
      <Text bold>My Menu (j/k to navigate, q to quit)</Text>
      <Text> </Text>
      <FocusGroup direction="vertical">
        <MenuItem label="Start Game" />
        <MenuItem label="Settings" />
        <MenuItem label="Exit" />
      </FocusGroup>
    </Box>
  );
}

function App() {
  return (
    <GigglesProvider>
      <Menu />
    </GigglesProvider>
  );
}

render(<App />);

What's happening

  1. GigglesProvider wraps your app and provides focus + input context
  2. FocusGroup creates a navigable group (use j/k or arrow keys)
  3. useFocus() gives each item access to its focus state
  4. useKeybindings() binds keys to actions

Core Concepts

Focus System

giggles manages focus as a tree structure. Components can be focusable, and FocusGroup creates navigable lists. Focus moves through the tree based on your layout.

  • FocusGroup: Container for navigable items (horizontal or vertical)
  • useFocus(): Hook to access focus state and methods
  • useFocusState(): Observer hook for focus changes

Learn more: Focus →

Input Handling

Input events flow through the focus tree. The focused component receives input first, then it bubbles up the tree until handled.

  • useKeybindings(): Bind keys to actions for a component
  • FocusTrap: Contain input within a section (for modals, dialogs)
  • Key normalization: ctrl+c, Ctrl-C, ^c all work the same

Learn more: Input →

On this page