ugtui
v1.0.1
Published
A beautiful terminal UI framework for Node.js - Create interactive CLI applications with ease
Maintainers
Readme
ugtui
A beautiful terminal UI framework for Node.js that makes building rich, interactive command-line applications easy and enjoyable.
Features
- 🎨 Beautiful UI Components - Pre-built components for common UI patterns
- 📐 Flexible Layout System - Flexbox-like layout engine
- 🎯 Event Handling - Keyboard event support
- 💅 Styling & Theming - Rich styling options with built-in themes
- ⚡ High Performance - Efficient rendering with minimal overhead
- 🔧 TypeScript Support - Full type definitions included
- 📦 Easy to Use - Simple API with intuitive design
- 🔌 Zero Dependencies - Uses only Node.js built-ins
Installation
Install from npm (Recommended)
npm install ugtuiInstall from local folder
cd /path/to/your-project
npm install /path/to/ugtuiDevelopment setup
# Clone or navigate to ugtui directory
cd /path/to/ugtui
# Install dependencies
npm install
# Build
npm run build
# Run examples
npm run exampleQuick Start
Your First App
Create a file app.js:
const { App, Box, Text, Button } = require('ugtui');
const app = new App();
const title = new Text({
content: 'Hello, ugtui!',
style: { fg: 'green', styles: ['bold'] },
padding: 1
});
const button = new Button({
label: 'Click Me!',
padding: 1,
onPress: () => console.log('Button clicked!')
});
const box = new Box({
border: true,
borderStyle: 'rounded',
title: ' My App ',
style: { fg: 'blue' }
});
box.addChild(title);
box.addChild(button);
app.mount(box);
app.start();Run it in an interactive terminal:
node app.jsGetting Started Guide
1. Understanding Components
ugtui is built around components - reusable building blocks that you compose to create your UI.
const { Box, Text, Button, FlexLayout } = require('ugtui');
// Create components
const title = new Text({ content: 'Title' });
const button = new Button({ label: 'Click' });
const box = new Box({ border: true });
// Add children
box.addChild(title);
box.addChild(button);2. Layout with FlexLayout
Organize components using the flexible layout system:
const layout = new FlexLayout({
direction: 'column', // 'row' or 'column'
justify: 'center', // 'flex-start', 'flex-end', 'center', 'space-between'
align: 'center', // 'flex-start', 'flex-end', 'center', 'stretch'
gap: 1, // Spacing between children
padding: 1 // Internal padding
});
layout.addChild(component1);
layout.addChild(component2);3. Styling Components
Apply colors and styles to make your UI beautiful:
const styledText = new Text({
content: 'Styled Text',
style: {
fg: 'blue', // foreground color
bg: 'white', // background color (optional)
styles: ['bold', 'underline'] // text effects
}
});4. Interactive Components
Handle user input with interactive components:
// Button with click handler
const button = new Button({
label: 'Submit',
onPress: () => {
console.log('Button pressed!');
}
});
// Input with change handler
const input = new Input({
placeholder: 'Type something...',
onChange: (value) => console.log('Typing:', value),
onSubmit: (value) => console.log('Submitted:', value)
});
// List with selection handler
const list = new List({
items: ['Option 1', 'Option 2', 'Option 3'],
onSelect: (index, item) => {
console.log('Selected:', item);
}
});5. Putting It All Together
const { App, Box, Text, Button, FlexLayout } = require('ugtui');
const app = new App();
// Create UI
const title = new Text({
content: 'Welcome!',
style: { fg: 'green', styles: ['bold'] },
padding: 1
});
const button = new Button({
label: 'Get Started',
onPress: () => {
title.updateProps({ content: 'Hello, User!' });
}
});
// Layout
const content = new FlexLayout({
direction: 'column',
gap: 1,
padding: 1
});
content.addChild(title);
content.addChild(button);
// Container
const box = new Box({
border: true,
borderStyle: 'rounded',
title: ' My App '
});
box.addChild(content);
// Start app
app.mount(box);
app.start();Components
Box
Container with optional borders and titles.
const box = new Box({
border: true,
borderStyle: 'rounded', // 'single', 'double', 'rounded'
title: 'Container',
padding: 2,
style: { fg: 'blue' }
});Text
Displays text with alignment and wrapping.
const text = new Text({
content: 'Hello, World!',
align: 'center', // 'left', 'center', 'right'
wrap: true,
style: { fg: 'green', styles: ['bold'] }
});Button
Interactive button with press handling.
const button = new Button({
label: 'Click Me',
padding: 1,
disabled: false,
activeColor: 'blue',
hoverColor: 'white',
onPress: () => console.log('Clicked!'),
style: { fg: 'blue', styles: ['bold'] }
});Input
Text input field with validation and password support.
const input = new Input({
placeholder: 'Enter text...',
password: false,
maxLength: 50,
disabled: false,
onChange: (value) => console.log('Value:', value),
onSubmit: (value) => console.log('Submitted:', value)
});
// Get current value
const currentValue = input.getValue();
// Set value programmatically
input.setValue('New value');List
Scrollable list of selectable items.
const list = new List({
items: ['Item 1', 'Item 2', 'Item 3'],
maxHeight: 10,
showScrollbar: true,
onSelect: (index, item) => console.log('Selected:', item)
});
// Get selected index
const index = list.getSelectedIndex();
// Set selected index
list.setSelectedIndex(1);
// Get selected item
const item = list.getSelectedItem();FlexLayout
Flexible container layout similar to CSS Flexbox.
const layout = new FlexLayout({
direction: 'row', // 'row' or 'column'
justify: 'center', // 'flex-start', 'flex-end', 'center', 'space-between', 'space-around'
align: 'center', // 'flex-start', 'flex-end', 'center', 'stretch'
gap: 2,
padding: 1
});
layout.addChild(component1);
layout.addChild(component2);Styling
Colors
Available colors:
Basic:
black,red,green,yellow,blue,magenta,cyan,white
Bright:
brightBlack,brightRed,brightGreen,brightYellow,brightBlue,brightMagenta,brightCyan,brightWhite
Text Styles
Available styles:
bold- Bold textdim- Dimmed textitalic- Italic textunderline- Underlined textblink- Blinking textreverse- Reversed foreground/backgroundhidden- Hidden text
Style Example
{
fg: 'blue', // foreground color
bg: 'white', // background color (optional)
styles: ['bold', 'underline'] // array of styles
}Theme Colors
Default theme colors:
{
primary: 'blue',
secondary: 'magenta',
success: 'green',
danger: 'red',
warning: 'yellow',
muted: 'white',
background: 'black',
surface: 'brightBlack',
text: 'white',
textSecondary: 'brightWhite'
}Keyboard Navigation
Tab- Navigate between componentsArrow Keys- Navigate within lists and formsEnter- Select item or submit formHome/End- Jump to start/end of listBackspace- Delete characterDelete- Delete forward characterq- Exit applicationCtrl+C- Exit application
API Reference
App
Main application class.
const app = new App({
fps: 60, // Frame rate
debug: false // Enable debug mode
});
// Mount root component
app.mount(component);
// Start application
app.start();
// Stop application
app.stop();
// Global key press listener
app.onKeyPress((event) => {
console.log('Key:', event.key);
console.log('Ctrl:', event.ctrl);
console.log('Alt:', event.alt);
console.log('Shift:', event.shift);
});
// Get terminal instance
const terminal = app.getTerminal();Component Methods
All components inherit from the base Component class:
// Add child component
component.addChild(child);
// Remove child component
component.removeChild(child);
// Get all children
const children = component.getChildren();
// Set position
component.setPosition({ x: 0, y: 0 });
// Get position
const pos = component.getPosition();
// Set size
component.setSize({ width: 20, height: 10 });
// Get size
const size = component.getSize();
// Give focus
component.focus();
// Remove focus
component.blur();
// Check if focused
const isFocused = component.isFocused();
// Update properties
component.updateProps({
style: { fg: 'green' },
padding: 2
});
// Get properties
const props = component.getProps();Examples
Simple Counter
const { App, Box, Text, Button, FlexLayout } = require('ugtui');
const app = new App();
let count = 0;
const counterText = new Text({
content: `Count: ${count}`,
style: { fg: 'green', styles: ['bold'] },
padding: 1
});
const incrementButton = new Button({
label: 'Increment',
onPress: () => {
count++;
counterText.updateProps({ content: `Count: ${count}` });
}
});
const decrementButton = new Button({
label: 'Decrement',
onPress: () => {
count--;
counterText.updateProps({ content: `Count: ${count}` });
}
});
const buttons = new FlexLayout({
direction: 'row',
gap: 2,
justify: 'center'
});
buttons.addChild(incrementButton);
buttons.addChild(decrementButton);
const content = new FlexLayout({
direction: 'column',
gap: 1,
align: 'center'
});
content.addChild(counterText);
content.addChild(buttons);
const box = new Box({
border: true,
borderStyle: 'rounded',
title: ' Counter '
});
box.addChild(content);
app.mount(box);
app.start();Todo List
const { App, Box, Text, Input, List, FlexLayout } = require('ugtui');
const app = new App();
const todos: string[] = [];
const input = new Input({
placeholder: 'Add a todo...',
onSubmit: (value) => {
if (value.trim()) {
todos.push(value);
list.updateProps({ items: [...todos] });
input.setValue('');
}
}
});
const list = new List({
items: todos,
maxHeight: 10,
onSelect: (index, item) => {
todos.splice(index, 1);
list.updateProps({ items: [...todos] });
console.log('Removed:', item);
}
});
const content = new FlexLayout({
direction: 'column',
gap: 1,
padding: 1
});
content.addChild(input);
content.addChild(list);
const box = new Box({
border: true,
borderStyle: 'rounded',
title: ' Todo List '
});
box.addChild(content);
app.mount(box);
app.start();Form with Validation
const { App, Box, Text, Input, Button, FlexLayout } = require('ugtui');
const app = new App();
const nameInput = new Input({
placeholder: 'Name',
padding: 1
});
const emailInput = new Input({
placeholder: 'Email',
padding: 1
});
const submitButton = new Button({
label: 'Submit',
onPress: () => {
const name = nameInput.getValue();
const email = emailInput.getValue();
console.log(`Submitted: ${name} (${email})`);
}
});
const form = new FlexLayout({
direction: 'column',
gap: 1,
padding: 2
});
form.addChild(nameInput);
form.addChild(emailInput);
form.addChild(submitButton);
const box = new Box({
border: true,
borderStyle: 'double',
title: ' Registration Form '
});
box.addChild(form);
app.mount(box);
app.start();Important Notes
Terminal Requirements
ugtui requires an interactive terminal (TTY). It works in:
✅ Terminal.app ✅ iTerm2 ✅ VS Code integrated terminal ✅ SSH sessions ✅ tmux, screen
It doesn't work in:
❌ Non-interactive environments ❌ Some CI/CD pipelines ❌ Piped output scenarios
TypeScript Usage
For TypeScript projects:
import { App, Box, Text } from 'ugtui';
const app = new App();
const box = new Box({ border: true });
// Full type safety!Troubleshooting
"ugtui requires an interactive terminal"
This error means you're not running in a TTY environment. Make sure to:
- Run in an interactive terminal (not through pipes)
- Don't redirect output
- Use Terminal.app, iTerm2, or similar
Nothing displays
Make sure you've called app.mount() before app.start():
const app = new App();
app.mount(component); // ← Must be before start
app.start();Components overlap
Use FlexLayout with proper gap and padding:
const layout = new FlexLayout({
direction: 'column',
gap: 1, // Spacing between children
padding: 1 // Internal padding
});Building
# Build TypeScript
npm run build
# Watch mode
npm run dev
# Run examples
npm run exampleVersion History
1.0.0 (2024-03-04)
Initial release:
- Terminal handling with raw mode
- 6 UI components (Box, Text, Button, Input, List, FlexLayout)
- Styling system with 16 colors and 7 styles
- Flexbox-like layout engine
- Keyboard navigation
- Full TypeScript support
- Zero external dependencies
Contributing
Contributions are welcome! Please feel free to:
- Report bugs
- Suggest features
- Submit pull requests
- Improve documentation
License
MIT License - see LICENSE file for details.
Credits
Created by Unmesh.
Links
- Installation:
npm install ugtui - Repository: https://github.com/unmesh100/ugtui
- Issues: https://github.com/unmesh100/ugtui/issues
Happy building with ugtui! 🚀
