All skills
msmps avatar

/opentui

@0d61d6d
by Matt Simpsonmsmps/opentui-skill225 stars
9

OpenTUI skill for building terminal user interfaces with the Core, React, or Solid APIs. Use for any TUI task including components, layout, keyboard and keymap handling, animations, and testing.

Use this Skill: https://skilld.dev/gh/msmps/opentui-skill/opentui

This session only. Nothing lands on disk.

referenceslayoutREFERENCE.md

≈1.6k tokens on demand. Your agent reads this file only when SKILL.md points to it.

OpenTUI Layout System

OpenTUI uses the Yoga layout engine, providing CSS Flexbox-like capabilities for positioning and sizing components in the terminal.

Overview

Key concepts:

  • Flexbox model: Familiar CSS Flexbox properties
  • Yoga engine: Facebook's cross-platform layout engine
  • Terminal units: Dimensions are in character cells (columns x rows)
  • Percentage support: Relative sizing based on parent

Flex Container Properties

flexDirection

Controls the main axis direction:

// Row (default) - children flow horizontally
<box flexDirection="row">
  <text>1</text>
  <text>2</text>
  <text>3</text>
</box>
// Output: 1 2 3

// Column - children flow vertically
<box flexDirection="column">
  <text>1</text>
  <text>2</text>
  <text>3</text>
</box>
// Output:
// 1
// 2
// 3

// Reverse variants
<box flexDirection="row-reverse">...</box>     // 3 2 1
<box flexDirection="column-reverse">...</box>  // Bottom to top

justifyContent

Aligns children along the main axis:

<box flexDirection="row" width={40} justifyContent="flex-start">
  {/* Children at start (left for row) */}
</box>

<box flexDirection="row" width={40} justifyContent="flex-end">
  {/* Children at end (right for row) */}
</box>

<box flexDirection="row" width={40} justifyContent="center">
  {/* Children centered */}
</box>

<box flexDirection="row" width={40} justifyContent="space-between">
  {/* First at start, last at end, rest evenly distributed */}
</box>

<box flexDirection="row" width={40} justifyContent="space-around">
  {/* Equal space around each child */}
</box>

<box flexDirection="row" width={40} justifyContent="space-evenly">
  {/* Equal space between all children and edges */}
</box>

alignItems

Aligns children along the cross axis:

<box flexDirection="row" height={10} alignItems="flex-start">
  {/* Children at top */}
</box>

<box flexDirection="row" height={10} alignItems="flex-end">
  {/* Children at bottom */}
</box>

<box flexDirection="row" height={10} alignItems="center">
  {/* Children vertically centered */}
</box>

<box flexDirection="row" height={10} alignItems="stretch">
  {/* Children stretch to fill height */}
</box>

<box flexDirection="row" height={10} alignItems="baseline">
  {/* Children aligned by text baseline */}
</box>

flexWrap

Controls whether children wrap to new lines:

<box flexDirection="row" flexWrap="nowrap" width={20}>
  {/* Children overflow (default) */}
</box>

<box flexDirection="row" flexWrap="wrap" width={20}>
  {/* Children wrap to next row */}
</box>

<box flexDirection="row" flexWrap="wrap-reverse" width={20}>
  {/* Children wrap upward */}
</box>

gap

Space between children:

<box flexDirection="row" gap={2}>
  <text>A</text>
  <text>B</text>
  <text>C</text>
</box>
// Output: A  B  C (2 spaces between)

Flex Item Properties

flexGrow

How much a child should grow relative to siblings:

<box flexDirection="row" width={30}>
  <box flexGrow={1}><text>1</text></box>
  <box flexGrow={2}><text>2</text></box>
  <box flexGrow={1}><text>1</text></box>
</box>
// Widths: 7.5 | 15 | 7.5 (1:2:1 ratio)

flexShrink

How much a child should shrink when space is limited:

<box flexDirection="row" width={20}>
  <box width={15} flexShrink={1}><text>Shrinks</text></box>
  <box width={15} flexShrink={0}><text>Fixed</text></box>
</box>

flexBasis

Initial size before growing/shrinking:

<box flexDirection="row">
  <box flexBasis={20} flexGrow={1}>Starts at 20, can grow</box>
  <box flexBasis="auto">Use measured content as the basis</box>
</box>

flexBasis accepts a cell count or "auto"; it does not accept percentages.

alignSelf

Override parent's alignItems for this child:

<box flexDirection="row" height={10} alignItems="center">
  <text>Centered</text>
  <text alignSelf="flex-start">Top</text>
  <text alignSelf="flex-end">Bottom</text>
</box>

Dimensions

Fixed Dimensions

<box width={40} height={10}>
  {/* Exactly 40 columns by 10 rows */}
</box>

Percentage Dimensions

Parent must have explicit size:

<box width="100%" height="100%">
  <box width="50%" height="50%">
    {/* Half of parent */}
  </box>
</box>

Min/Max Constraints

<box
  minWidth={20}
  maxWidth={60}
  minHeight={5}
  maxHeight={20}
>
  {/* Constrained sizing */}
</box>

Spacing

Padding (inside)

// All sides
<box padding={2}>Content</box>

// Individual sides
<box
  paddingTop={1}
  paddingRight={2}
  paddingBottom={1}
  paddingLeft={2}
>
  Content
</box>

Margin (outside)

// All sides
<box margin={1}>Content</box>

// Individual sides
<box
  marginTop={1}
  marginRight={2}
  marginBottom={1}
  marginLeft={2}
>
  Content
</box>

Positioning

Relative (default)

Element flows in normal document order:

<box position="relative">
  {/* Normal flow */}
</box>

Absolute

Element positioned relative to nearest positioned ancestor:

<box position="relative" width="100%" height="100%">
  <box
    position="absolute"
    left={10}
    top={5}
    width={20}
    height={5}
  >
    Positioned at (10, 5)
  </box>
</box>

Position Properties

<box
  position="absolute"
  left={10}      // From left edge
  top={5}        // From top edge
  right={10}     // From right edge
  bottom={5}     // From bottom edge
>
  Content
</box>

Display

Visibility Control

// Visible (default)
<box visible>Visible</box>

// Hidden (removed from layout)
<box visible={false}>Hidden</box>

Overflow

<box overflow="visible">
  {/* Content can extend beyond bounds (default) */}
</box>

<box overflow="hidden">
  {/* Content clipped at bounds */}
</box>

<box overflow="scroll">
  {/* Scrollable when content exceeds bounds */}
</box>

Z-Index

Control stacking order for overlapping elements:

<box position="relative">
  <box position="absolute" zIndex={1}>Behind</box>
  <box position="absolute" zIndex={2}>In front</box>
</box>

See Also

Source: SKILL.md on GitHub

No alerts17d5 checks · Risk SAFE
  • Gen Agent Trust Hub17d

    This skill contains documentation and usage patterns for the OpenTUI framework, designed for building terminal user interfaces across Core, React, and SolidJS. The analysis confirmed that the skill provides legitimate development guidance; no malicious code, persistence mechanisms, or obfuscation were detected. Findings are limited to standard platform capabilities and recommended scaffolding tools.

  • Socket17d

    No alerts

  • Snyk17d

    Risk: LOW · No issues

  • Runlayer7mo

    1/26 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 0d61d6d. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub last month.

Steadyupdated last month
Other metadata
metadata
{
  "references": "core, react, solid, components, layout, keyboard, keymap, animation, testing"
}
  • React
  • Testing
  • terminal-ui
  • tui
  • solid
  • components
  • keyboard-input
  • animations
  • layout

README badge

README badge for msmps/opentui-skill

Builds terminal user interfaces with OpenTUI using an imperative core API or React/Solid reconcilers. Covers layout, keyboard handling, animations, components, and testing for full-featured TUI applications.

Generated from the current SKILL.md.

Does this skill cover all three OpenTUI frameworks?
Yes. The skill consolidates the core imperative API, React reconciler, and Solid reconciler. Use the decision tree in the skill to pick the right framework for your task.
How do I start a new OpenTUI project?
Use `create-tui` with options before arguments: `bunx create-tui -t react my-app` (not `bunx create-tui my-app -t react`). Then read the REFERENCE.md for your chosen framework.
What runtime does OpenTUI require?
OpenTUI runs on Bun and uses Zig for native builds. See `./references/core/gotchas.md` for runtime requirements and build guidance.
Can I use `process.exit()` to shut down my TUI?
No. Always use `renderer.destroy()` instead. Calling `process.exit()` directly is a common pitfall covered in `core/gotchas.md`.
How do I apply text styling in React or Solid?
Use nested modifier elements, not props. See `components/text-display.md` for the correct pattern.

Generated from the current SKILL.md. These answers refresh after source changes.