Styling
Kraken TUI provides comprehensive styling capabilities including color resolution, text decoration, and borders. All styling is resolved in the Native Core for maximum performance.
Color System
Kraken TUI supports three color modes with automatic terminal capability detection and graceful degradation.
Hex Colors (Truecolor)
Named Colors
256-Color Palette
Default
text . setForeground ( "#FF0000" ); // Bright red
text . setBackground ( "#1E1E1E" ); // Dark gray
text . setForeground ( "#F80" ); // Short form: #FF8800
Encoding: 0x01RRGGBB (truecolor mode)Support: Modern terminals (iTerm2, Windows Terminal, Alacritty, etc.)text . setForeground ( "red" );
text . setBackground ( "blue" );
text . setForeground ( "bright-cyan" );
Encoding: 0x020000XX (ANSI index mode)Support: All terminalsAvailable names: black, red, green, yellow, blue, magenta, cyan, white, bright-black, bright-red, bright-green, bright-yellow, bright-blue, bright-magenta, bright-cyan, bright-whitetext . setForeground ( 196 ); // ANSI color 196 (red)
text . setBackground ( 233 ); // ANSI color 233 (dark gray)
Encoding: 0x020000XX (ANSI index mode)Support: Most modern terminalsRange: 0–255text . setForeground ( "default" );
text . setForeground ( 0 ); // Equivalent
Encoding: 0x00000000 (default mode)Uses terminal’s default foreground/background color.
Color Parsing
The Style Module parses colors into a uniform u32 encoding:
// From source: ts/src/style.ts
export function parseColor ( value : string | number ) : number {
if ( typeof value === "number" ) {
if ( value === 0 ) return 0 ; // Default
if ( value >= 0 && value <= 255 ) return 0x02000000 | value ; // ANSI index
return value ; // Already encoded
}
const lower = value . toLowerCase (). trim ();
if ( lower === "default" || lower === "" ) return 0 ;
// Hex color: "#FF0000" → 0x01FF0000
if ( lower . startsWith ( "#" )) {
const hex = lower . slice ( 1 );
if ( hex . length === 6 ) {
const rgb = parseInt ( hex , 16 );
if ( ! isNaN ( rgb )) return 0x01000000 | rgb ;
}
// Short form: "#F80" → "#FF8800"
if ( hex . length === 3 ) {
const r = parseInt ( hex [ 0 ], 16 ) * 17 ;
const g = parseInt ( hex [ 1 ], 16 ) * 17 ;
const b = parseInt ( hex [ 2 ], 16 ) * 17 ;
return 0x01000000 | ( r << 16 ) | ( g << 8 ) | b ;
}
}
// Named color: "red" → 0x02000001
if ( lower in NAMED_COLORS ) {
return 0x02000000 | NAMED_COLORS [ lower ];
}
return 0 ; // Default fallback
}
Graceful Degradation
The Native Core automatically detects terminal capabilities and degrades colors gracefully: Truecolor → 256-color → 16-color → Monochrome
// You write:
text . setForeground ( "#FF5733" );
// Terminal with truecolor: exact #FF5733
// Terminal with 256-color: closest ANSI color (e.g., 203)
// Terminal with 16-color: closest ANSI color (e.g., red)
// Monochrome terminal: default foreground
Text Decoration
Apply text decoration attributes to widgets:
Bold
text . setBold ( true ); // Enable bold
text . setBold ( false ); // Disable bold
Bold rendering depends on terminal font support. Some terminals render bold as brighter colors instead of heavier weight.
Italic
text . setItalic ( true ); // Enable italic
text . setItalic ( false ); // Disable italic
Italic support varies by terminal. Not all monospace fonts include italic variants.
Underline
text . setUnderline ( true ); // Enable underline
text . setUnderline ( false ); // Disable underline
Combining Decorations
const heading = new Text ({ content: "Important" });
heading . setForeground ( "#FF0000" );
heading . setBold ( true );
heading . setUnderline ( true );
// Bold, underlined, red text
Borders
Add borders around container widgets:
Border Styles
none
single
double
rounded
bold
box . setBorderStyle ( "none" );
// No border (default)
box . setBorderStyle ( "single" );
// ┌─────┐
// │ │
// └─────┘
box . setBorderStyle ( "double" );
// ╔═════╗
// ║ ║
// ╚═════╝
box . setBorderStyle ( "rounded" );
// ╭─────╮
// │ │
// ╰─────╯
box . setBorderStyle ( "bold" );
// ┏━━━━━┓
// ┃ ┃
// ┗━━━━━┛
Border Colors
box . setBorderStyle ( "single" );
box . setBorderColor ( "#00FF00" ); // Green border
Border color is separate from foreground/background. You can have a green border with red text on a black background.
Border with Content
const panel = new Box ();
panel . setBorderStyle ( "rounded" );
panel . setBorderColor ( "cyan" );
panel . setPadding ( 1 , 2 , 1 , 2 ); // Inner spacing
const title = new Text ({ content: "Panel Title" });
title . setBold ( true );
panel . append ( title );
// ╭──────────────╮
// │ │
// │ Panel Title │ ← 1 cell padding top/bottom
// │ │ 2 cells padding left/right
// ╰──────────────╯
Opacity
Control widget transparency (composited in the render buffer):
widget . setOpacity ( 1.0 ); // Fully opaque (default)
widget . setOpacity ( 0.5 ); // 50% transparent
widget . setOpacity ( 0.0 ); // Fully transparent (invisible)
Opacity affects the widget and all its descendants. Use sparingly as it increases render complexity.
Opacity Animation
Opacity is commonly animated for fade effects:
// Fade in
widget . setOpacity ( 0.0 );
widget . animate ({
property: "opacity" ,
target: 1.0 ,
duration: 300 ,
easing: "easeOut"
});
// Fade out
widget . animate ({
property: "opacity" ,
target: 0.0 ,
duration: 300 ,
easing: "easeIn"
});
Style Resolution
Explicit Styles vs Theme Defaults
Explicit widget styles always win over theme defaults. Themes provide fallback values for properties you don’t set explicitly.
import { Theme } from "kraken-tui" ;
const theme = Theme . create ();
theme . setForeground ( "white" ); // Default foreground
theme . setBackground ( "black" ); // Default background
const box = new Box ();
theme . applyTo ( box );
// box uses white on black (from theme)
box . setForeground ( "red" ); // Explicit style
// box now uses red on black (explicit wins)
See the Theming section for more details.
Styling Examples
Syntax-Highlighted Code Block
const codeBlock = new Text ({
content: 'function hello() { \n console.log("Hello"); \n }' ,
format: "code" ,
language: "javascript"
});
codeBlock . setBackground ( "#1E1E1E" );
codeBlock . setPadding ( 1 , 2 , 1 , 2 );
const container = new Box ();
container . setBorderStyle ( "single" );
container . setBorderColor ( "#444" );
container . append ( codeBlock );
const button = new Box ();
button . setBorderStyle ( "rounded" );
button . setBorderColor ( "blue" );
button . setBackground ( "#1E3A8A" ); // Dark blue
button . setPadding ( 0 , 2 , 0 , 2 );
const label = new Text ({ content: "Submit" });
label . setForeground ( "white" );
label . setBold ( true );
button . append ( label );
// ╭──────────╮
// │ Submit │ ← Blue background, white bold text
// ╰──────────╯
Status Indicator
function createStatus ( level : "info" | "warn" | "error" ) {
const status = new Text ({ content: level . toUpperCase () });
status . setBold ( true );
switch ( level ) {
case "info" :
status . setForeground ( "#00FF00" ); // Green
break ;
case "warn" :
status . setForeground ( "#FFA500" ); // Orange
break ;
case "error" :
status . setForeground ( "#FF0000" ); // Red
break ;
}
return status ;
}
const info = createStatus ( "info" ); // Green INFO
const warn = createStatus ( "warn" ); // Orange WARN
const error = createStatus ( "error" ); // Red ERROR
Rainbow Text
const rainbow = new Box ({ direction: "row" });
const colors = [ "red" , "#FFA500" , "yellow" , "green" , "blue" , "#4B0082" , "#8B00FF" ];
const letters = "RAINBOW" . split ( "" );
letters . forEach (( letter , i ) => {
const span = new Text ({ content: letter });
span . setForeground ( colors [ i ]);
span . setBold ( true );
rainbow . append ( span );
});
// RAINBOW ← Each letter different color
Color parsing happens once per property set in TypeScript, then the u32 encoding crosses FFI. Native Core uses the encoding directly — zero parsing overhead during render.
Text decorations (bold, italic, underline) are stored as bit flags in a single u8, making style checks and comparisons extremely fast.
Borders are rendered using Unicode box-drawing characters. Single-cell writes per corner/edge — minimal overhead.
Opacity requires alpha blending during render. Use sparingly for performance-critical paths. Fully opaque (1.0) and fully transparent (0.0) are optimized fast paths.
Style Best Practices
Use Named Colors for Compatibility
Named colors work in all terminals. Use hex colors for branding/design fidelity when you control the deployment environment. // Good for wide compatibility:
text . setForeground ( "green" );
// Good for precise branding:
text . setForeground ( "#00D084" ); // Exact brand green
Prefer Theme Defaults Over Per-Widget Styling
Set common styles once in a theme instead of repeating them on every widget. const theme = Theme . create ();
theme . setForeground ( "white" );
theme . setBackground ( "black" );
theme . applyTo ( rootWidget );
// All descendants inherit theme defaults
Test in Your Target Terminals
Color rendering varies by terminal emulator. Test in the terminals your users will use (especially for hex colors and decorations).
Minimize Opacity Usage
Reserve opacity for animations and overlays. Avoid setting non-1.0 opacity on large subtrees.
Next Steps
Theming Create reusable theme systems
Animation Animate colors and opacity