Terminal User Interface framework for Java that ports the Charmbracelet ecosystem (Bubble Tea, Bubbles, Lipgloss, Harmonica) from Go, enabling developers to build interactive CLI applications using The Elm Architecture pattern.
Lipgloss is TUI4J's comprehensive styling system for terminal text, providing colors, text attributes, borders, padding, margins, alignment, and layout capabilities. It uses a fluent, immutable API for building styled text.
The Style class is the main entry point for creating styled text.
package com.williamcallahan.tui4j.compat.lipgloss;
class Style {
// Creation
static Style newStyle();
Style(Renderer renderer);
// Color methods
Style foreground(TerminalColor color);
Style foreground(String color);
Style background(TerminalColor color);
Style background(String color);
// Text attribute methods (all require boolean parameter)
Style bold(boolean enabled);
Style italic(boolean enabled);
Style underline(boolean enabled);
Style blink(boolean enabled);
Style faint(boolean enabled);
Style reverse(boolean enabled);
// Sizing methods
Style width(int width);
Style height(int height);
Style maxWidth(int maxWidth);
Style maxHeight(int maxHeight);
Style inline();
// Padding methods
Style padding(int padding);
Style padding(int vertical, int horizontal);
Style padding(int top, int right, int bottom, int left);
Style padTop(int padding);
Style padRight(int padding);
Style padBottom(int padding);
Style padLeft(int padding);
// Margin methods
Style margin(int margin);
Style margin(int vertical, int horizontal);
Style margin(int top, int right, int bottom, int left);
Style marginTop(int margin);
Style marginRight(int margin);
Style marginBottom(int margin);
Style marginLeft(int margin);
// Border methods
Style border(Border border);
Style border(Border border, boolean top, boolean right, boolean bottom, boolean left);
Style borderTop();
Style borderTop(boolean enabled);
Style borderRight();
Style borderRight(boolean enabled);
Style borderBottom();
Style borderBottom(boolean enabled);
Style borderLeft();
Style borderLeft(boolean enabled);
Style borderForeground(TerminalColor color);
Style borderForeground(String color);
Style borderBackground(TerminalColor color);
Style borderBackground(String color);
Style borderTopForeground(TerminalColor color);
Style borderRightForeground(TerminalColor color);
Style borderBottomForeground(TerminalColor color);
Style borderLeftForeground(TerminalColor color);
Style borderTopBackground(TerminalColor color);
Style borderRightBackground(TerminalColor color);
Style borderBottomBackground(TerminalColor color);
Style borderLeftBackground(TerminalColor color);
// Margin styling
Style marginBackground(TerminalColor color);
// Alignment methods
Style alignHorizontal(Position position);
Style alignVertical(Position position);
// Utility methods
Style unsetMaxWidth();
Style unsetMaxHeight();
Style transform(Function<String, String> fn);
Style copy();
// Getters
int getWidth();
int getHeight();
int getMaxWidth();
int getMaxHeight();
int leftPadding();
int rightPadding();
int topPadding();
int bottomPadding();
// Content and rendering
Style setString(String... lines);
String render();
String render(String content);
}Basic Usage:
// Create a styled string
Style style = Style.newStyle()
.foreground("#FF5733")
.background("#000000")
.bold(true)
.padding(1, 2);
String output = style.render("Hello, World!");Chaining Methods:
Style titleStyle = Style.newStyle()
.foreground("#FFFFFF")
.background("#0066CC")
.bold(true)
.padding(1, 3)
.margin(1, 0)
.width(40)
.alignHorizontal(Position.Center)
.border(StandardBorder.RoundedBorder)
.borderForeground("#0066CC");
String title = titleStyle.render("Application Title");The Color class provides factory methods for creating colors.
package com.williamcallahan.tui4j.compat.lipgloss.color;
class Color {
// RGB colors
static TerminalColor color(String hex);
static TerminalColor color(int r, int g, int b);
// ANSI colors
static ANSIColor ansi(int code);
// 256-color ANSI
static ANSI256Color ansi256(int code);
// Adaptive colors
static AdaptiveColor adaptive(TerminalColor light, TerminalColor dark);
}Usage:
// Hex color
TerminalColor red = Color.color("#FF0000");
// RGB values
TerminalColor blue = Color.color(0, 0, 255);
// ANSI color (0-15)
TerminalColor brightRed = Color.ansi(9);
// ANSI 256-color (0-255)
TerminalColor custom = Color.ansi256(203);
// Adaptive color (switches based on terminal background)
TerminalColor adaptive = Color.adaptive(
Color.color("#000000"), // Light background
Color.color("#FFFFFF") // Dark background
);Base interface for all color types.
package com.williamcallahan.tui4j.compat.lipgloss.color;
interface TerminalColor {
String sequence(boolean background);
}True color (24-bit RGB).
package com.williamcallahan.tui4j.compat.lipgloss.color;
class RGBColor implements TerminalColor {
RGBColor(int r, int g, int b);
RGBColor(String hex);
}Standard 16-color ANSI.
package com.williamcallahan.tui4j.compat.lipgloss.color;
class ANSIColor implements TerminalColor {
ANSIColor(int code); // 0-15
}Standard ANSI Colors:
256-color ANSI palette.
package com.williamcallahan.tui4j.compat.lipgloss.color;
class ANSI256Color implements TerminalColor {
ANSI256Color(int code); // 0-255
}Color that adapts to terminal background.
package com.williamcallahan.tui4j.compat.lipgloss.color;
class AdaptiveColor implements TerminalColor {
AdaptiveColor(TerminalColor light, TerminalColor dark);
}Represents absence of color.
package com.williamcallahan.tui4j.compat.lipgloss.color;
class NoColor implements TerminalColor {
NoColor();
}Terminal color capability levels.
package com.williamcallahan.tui4j.compat.lipgloss.color;
enum ColorProfile {
NoColor, // No color support
ANSI, // 16 colors
ANSI256, // 256 colors
TrueColor // 24-bit RGB
}package com.williamcallahan.tui4j.compat.lipgloss.color;
record RGB(int r, int g, int b) { }
record HSL(double h, double s, double l) { }Defines border characters for drawing boxes.
package com.williamcallahan.tui4j.compat.lipgloss.border;
record Border(
String top,
String bottom,
String left,
String right,
String topLeft,
String topRight,
String bottomLeft,
String bottomRight,
String middleLeft,
String middleRight,
String middle,
String middleTop,
String middleBottom
) { }Pre-defined border styles.
package com.williamcallahan.tui4j.compat.lipgloss.border;
class StandardBorder {
// Static final Border constants
static final Border NoBorder;
static final Border NormalBorder;
static final Border RoundedBorder;
static final Border BlockBorder;
static final Border OuterHalfBlockBorder;
static final Border InnerHalfBlockBorder;
static final Border ThickBorder;
static final Border DoubleBorder;
static final Border HiddenBorder;
static final Border MarkdownBorder;
static final Border ASCIIBorder;
}Usage:
// Normal box drawing characters
Style boxStyle = Style.newStyle()
.border(StandardBorder.NormalBorder)
.padding(1);
// Rounded corners
Style roundedStyle = Style.newStyle()
.border(StandardBorder.RoundedBorder)
.borderForeground("#00FF00");
// Thick borders
Style thickStyle = Style.newStyle()
.border(StandardBorder.ThickBorder);
// Double-line borders
Style doubleStyle = Style.newStyle()
.border(StandardBorder.DoubleBorder);
// Hidden border (for spacing without visible border)
Style spacedStyle = Style.newStyle()
.border(StandardBorder.HiddenBorder)
.padding(1);Custom Borders:
Border customBorder = new Border(
"-", // top
"-", // bottom
"|", // left
"|", // right
"+", // topLeft
"+", // topRight
"+", // bottomLeft
"+", // bottomRight
"+", // middleLeft
"+", // middleRight
"+", // middle
"+", // middleTop
"+" // middleBottom
);
Style style = Style.newStyle().border(customBorder);Partial Borders:
// Border only on top and bottom
Style style = Style.newStyle()
.border(StandardBorder.NormalBorder, true, false, true, false);
// Border only on left
Style leftBorderStyle = Style.newStyle()
.borderLeft(true)
.borderForeground("#FF0000");Alignment positions.
package com.williamcallahan.tui4j.compat.lipgloss;
enum Position {
Left, Center, Right, // Horizontal
Top, Bottom // Vertical
}Horizontal Alignment:
// Left-aligned (default)
Style leftStyle = Style.newStyle()
.width(40)
.alignHorizontal(Position.Left);
// Center-aligned
Style centerStyle = Style.newStyle()
.width(40)
.alignHorizontal(Position.Center);
// Right-aligned
Style rightStyle = Style.newStyle()
.width(40)
.alignHorizontal(Position.Right);Vertical Alignment:
// Top-aligned (default)
Style topStyle = Style.newStyle()
.height(10)
.alignVertical(Position.Top);
// Center-aligned
Style middleStyle = Style.newStyle()
.height(10)
.alignVertical(Position.Center);
// Bottom-aligned
Style bottomStyle = Style.newStyle()
.height(10)
.alignVertical(Position.Bottom);package com.williamcallahan.tui4j.compat.lipgloss;
record Dimensions(int width, int height) { }package com.williamcallahan.tui4j.compat.lipgloss;
record Size(int width, int height) { }Join multiple strings horizontally.
package com.williamcallahan.tui4j.compat.lipgloss.join;
class HorizontalJoinDecorator {
static String join(Position position, String... strs);
}Usage:
String left = Style.newStyle()
.width(20)
.background("#FF0000")
.render("Left");
String right = Style.newStyle()
.width(20)
.background("#00FF00")
.render("Right");
// Join at top
String joined = HorizontalJoinDecorator.join(Position.Top, left, right);
// Join centered
String centered = HorizontalJoinDecorator.join(Position.Center, left, right);Join multiple strings vertically.
package com.williamcallahan.tui4j.compat.lipgloss.join;
class VerticalJoinDecorator {
static String join(Position position, String... strs);
}Usage:
String header = Style.newStyle()
.width(40)
.background("#0066CC")
.render("Header");
String body = Style.newStyle()
.width(40)
.background("#FFFFFF")
.foreground("#000000")
.render("Body");
String footer = Style.newStyle()
.width(40)
.background("#666666")
.render("Footer");
// Join vertically, left-aligned
String layout = VerticalJoinDecorator.join(Position.Left, header, body, footer);Render lists with bullets or numbers.
package com.williamcallahan.tui4j.compat.lipgloss.list;
class List {
List();
List items(String... items);
List enumerator(Enumerator enumerator);
List enumeratorStyle(Style style);
List itemStyle(Style style);
String render();
}Usage:
// Bulleted list
List bulletList = new List()
.items("First item", "Second item", "Third item")
.enumeratorStyle(Style.newStyle().foreground("#00FF00"))
.itemStyle(Style.newStyle().foreground("#FFFFFF"));
String output = bulletList.render();
// Numbered list
List numberedList = new List()
.items("Step 1", "Step 2", "Step 3")
.enumerator(Enumerator.Arabic);
String numbered = numberedList.render();Render tables with borders and styling.
package com.williamcallahan.tui4j.compat.lipgloss.table;
class Table {
Table();
Table headers(String... headers);
Table row(String... cells);
Table rows(String[]... rows);
Table border(Border border);
Table borderStyle(Style style);
Table styleFunc(BiFunction<Integer, Integer, Style> func);
Table width(int width);
String render();
}Usage:
Table table = new Table()
.headers("Name", "Age", "City")
.row("Alice", "30", "New York")
.row("Bob", "25", "San Francisco")
.row("Charlie", "35", "Seattle")
.border(StandardBorder.NormalBorder)
.borderStyle(Style.newStyle().foreground("#00FF00"));
String output = table.render();
// Styled cells
Table styledTable = new Table()
.headers("Col1", "Col2")
.row("A", "B")
.row("C", "D")
.styleFunc((row, col) -> {
if (row == 0) {
// Header row
return Style.newStyle().bold(true).foreground("#FFFF00");
}
if (col % 2 == 0) {
return Style.newStyle().background("#333333");
}
return Style.newStyle();
});Table Data Interface and Filter:
package com.williamcallahan.tui4j.compat.lipgloss.table;
interface Data {
String at(int row, int cell);
int rows();
int columns();
}
final class Filter implements Data {
Filter(Data data);
Filter filter(IntPredicate predicate);
String at(int row, int cell);
int rows();
int columns();
}Usage:
// Create a data source
Data myData = new Data() {
String[][] data = {
{"Alice", "30", "New York"},
{"Bob", "25", "San Francisco"},
{"Charlie", "35", "Seattle"},
{"Diana", "28", "Boston"}
};
public String at(int row, int cell) {
return data[row][cell];
}
public int rows() { return data.length; }
public int columns() { return data[0].length; }
};
// Filter rows (e.g., only people over 28)
Filter filtered = new Filter(myData).filter(row -> {
int age = Integer.parseInt(myData.at(row, 1));
return age > 28;
});
// Use filtered data in table
Table table = new Table()
.headers("Name", "Age", "City")
.data(filtered);Render tree structures.
package com.williamcallahan.tui4j.compat.lipgloss.tree;
class Tree {
Tree();
Tree root(Node root);
Tree enumeratorStyle(Style style);
Tree itemStyle(Style style);
String render();
}
interface Node {
String value();
List<Node> children();
}
record Leaf(String value) implements Node {
@Override
default List<Node> children() {
return List.of();
}
}Usage:
// Simple tree
class TreeNode implements Node {
private final String value;
private final List<Node> children;
TreeNode(String value, Node... children) {
this.value = value;
this.children = List.of(children);
}
@Override
public String value() { return value; }
@Override
public List<Node> children() { return children; }
}
Node root = new TreeNode("Root",
new TreeNode("Child 1",
new Leaf("Grandchild 1.1"),
new Leaf("Grandchild 1.2")
),
new TreeNode("Child 2",
new Leaf("Grandchild 2.1")
)
);
Tree tree = new Tree()
.root(root)
.enumeratorStyle(Style.newStyle().foreground("#00FF00"))
.itemStyle(Style.newStyle().foreground("#FFFFFF"));
String output = tree.render();Tree Helper Interfaces and Classes:
package com.williamcallahan.tui4j.compat.lipgloss.tree;
// TreeEnumerator - Generates node prefixes
interface TreeEnumerator {
String enumerate(int index);
}
// TreeIndenter - Generates indentation
interface TreeIndenter {
String indent(int level);
}
// TreeStyle - Style configuration for tree rendering
class TreeStyle {
TreeStyle();
TreeStyle withEnumerator(TreeEnumerator enumerator);
TreeStyle withIndenter(TreeIndenter indenter);
TreeStyle withEnumeratorStyle(Style style);
TreeStyle withItemStyle(Style style);
}
// StyleFunction - Dynamic styling based on tree state
interface StyleFunction {
Style apply(String value, boolean isLeaf, int depth);
}
// Filter - Filter nodes based on criteria
interface Filter {
boolean test(Node node);
}
// Children - Provide children for a node
interface Children {
List<Node> children(Node node);
}
// NodeChildren - Helper for managing node children
class NodeChildren {
static NodeChildren of(Node... nodes);
static NodeChildren of(List<Node> nodes);
List<Node> nodes();
}
// Renderer - Advanced tree rendering
class Renderer {
Renderer();
String render(Node root);
String render(Node root, TreeStyle style);
}Advanced Tree Usage:
// Custom enumerator
TreeEnumerator romanEnumerator = index -> {
String[] romans = {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X"};
return index < romans.length ? romans[index] + ". " : (index + 1) + ". ";
};
// Custom indenter
TreeIndenter customIndenter = level -> " ".repeat(level) + "├─ ";
// Create styled tree
TreeStyle customStyle = new TreeStyle()
.withEnumerator(romanEnumerator)
.withIndenter(customIndenter)
.withEnumeratorStyle(Style.newStyle().foreground("#FFFF00").bold(true))
.withItemStyle(Style.newStyle().foreground("#FFFFFF"));
Tree tree = new Tree()
.root(root)
.style(customStyle);
// Dynamic styling with StyleFunction
StyleFunction depthStyling = (value, isLeaf, depth) -> {
String[] colors = {"#FF0000", "#00FF00", "#0000FF", "#FFFF00"};
return Style.newStyle().foreground(colors[depth % colors.length]);
};
// Filtered tree (show only specific nodes)
Filter onlyFilesFilter = node -> {
return node instanceof FileNode && ((FileNode) node).isFile();
};The Renderer provides rendering context for styles.
package com.williamcallahan.tui4j.compat.lipgloss;
class Renderer {
// Factory
static Renderer defaultRenderer();
// Constructor
Renderer(Output output);
// Style creation
Style newStyle();
// Terminal information
boolean hasDarkBackground();
ColorProfile colorProfile();
// Configuration
void setColorProfile(ColorProfile profile);
void setHasDarkBackground(boolean dark);
}Usage:
// Use default renderer
Renderer renderer = Renderer.defaultRenderer();
Style style = renderer.newStyle()
.foreground("#FF0000");
// Create custom renderer
Output output = new Output(/* configuration */);
Renderer customRenderer = new Renderer(output);
// Check terminal capabilities
if (renderer.hasDarkBackground()) {
style = style.foreground("#FFFFFF");
} else {
style = style.foreground("#000000");
}
// Force color profile
renderer.setColorProfile(ColorProfile.ANSI256);The Join class provides utilities for joining styled strings horizontally or vertically.
package com.williamcallahan.tui4j.compat.lipgloss;
final class Join {
static String joinHorizontal(Position position, String... strings);
static String joinVertical(Position position, String... strings);
}Usage:
// Join strings horizontally (side-by-side)
String left = Style.newStyle().width(20).render("Left panel");
String right = Style.newStyle().width(20).render("Right panel");
String horizontal = Join.joinHorizontal(Position.Top, left, right);
// Join strings vertically (stacked)
String header = Style.newStyle().width(40).render("Header");
String body = Style.newStyle().width(40).render("Body");
String footer = Style.newStyle().width(40).render("Footer");
String vertical = Join.joinVertical(Position.Left, header, body, footer);The Alignment class provides text alignment utilities for positioning content.
package com.williamcallahan.tui4j.compat.lipgloss;
final class Alignment {
static String alignTextHorizontal(String input, Position position, int width);
static String alignTextHorizontal(String input, Position position, int width, AttributedStyle attributedStyle);
static String alignTextVertical(String input, Position position, int height);
}Usage:
// Center text horizontally
String centered = Alignment.alignTextHorizontal("Hello", Position.Center, 40);
// Right-align text
String rightAligned = Alignment.alignTextHorizontal("Right", Position.Right, 40);
// Center text vertically
String verticallyCentered = Alignment.alignTextVertical("Middle", Position.Center, 10);The Borders class provides factory methods for creating border styles.
package com.williamcallahan.tui4j.compat.lipgloss;
final class Borders {
// Factory methods that return Border instances
// These delegate to StandardBorder static final constants
static Border noBorder();
static Border normalBorder();
static Border roundedBorder();
static Border blockBorder();
static Border outerHalfBlockBorder();
static Border innerHalfBlockBorder();
static Border thickBorder();
static Border doubleBorder();
static Border hiddenBorder();
static Border markdownBorder();
static Border asciiBorder();
}Usage:
// Recommended: Use StandardBorder constants directly
Style normalStyle = Style.newStyle().border(StandardBorder.NormalBorder);
Style roundedStyle = Style.newStyle().border(StandardBorder.RoundedBorder);
Style thickStyle = Style.newStyle().border(StandardBorder.ThickBorder);
Style markdownStyle = Style.newStyle().border(StandardBorder.MarkdownBorder);
Style asciiStyle = Style.newStyle().border(StandardBorder.ASCIIBorder);
// Alternative: Use Borders utility class (delegates to StandardBorder)
Style normalStyle2 = Style.newStyle().border(Borders.normalBorder());The Runes class provides utilities for styling specific characters within a string.
package com.williamcallahan.tui4j.compat.lipgloss;
class Runes {
static String styleRunes(String input, int[] indices, Style matched, Style unmatched);
}Usage:
// Highlight specific characters in a string
Style highlighted = Style.newStyle().foreground("#FFFF00").bold(true);
Style normal = Style.newStyle().foreground("#FFFFFF");
int[] indices = {0, 5, 10}; // Highlight characters at these positions
String styled = Runes.styleRunes("Hello World Example", indices, highlighted, normal);The Whitespace class provides utilities for rendering styled whitespace.
package com.williamcallahan.tui4j.compat.lipgloss;
final class Whitespace {
Whitespace(Style style);
String render(int width);
// Options
interface WhitespaceOption {
void apply(Whitespace whitespace);
}
static WhitespaceOption WithWhitespaceForeground(TerminalColor color);
static WhitespaceOption WithWhitespaceBackground(TerminalColor color);
static WhitespaceOption WithWhitespaceChars(String chars);
static Whitespace newWhiteSpace(Renderer renderer, WhitespaceOption... options);
}Usage:
// Create styled whitespace
Renderer renderer = Renderer.defaultRenderer();
Whitespace ws = Whitespace.newWhiteSpace(
renderer,
Whitespace.WithWhitespaceBackground(Color.color("#333333")),
Whitespace.WithWhitespaceChars(".")
);
String spacer = ws.render(40); // 40 characters of styled whitespace
// Simple whitespace with style
Style bgStyle = Style.newStyle().background("#222222");
Whitespace simple = new Whitespace(bgStyle);
String space = simple.render(20);The TextLines class provides utilities for analyzing multi-line text.
package com.williamcallahan.tui4j.compat.lipgloss;
class TextLines {
static TextLines fromText(String text);
int widestLineLength();
String[] lines();
}Usage:
// Analyze text dimensions
String multilineText = "Line 1\nLine 2 is longer\nLine 3";
TextLines textLines = TextLines.fromText(multilineText);
int maxWidth = textLines.widestLineLength();
String[] lines = textLines.lines();
// Use for dynamic width calculation
Style dynamicStyle = Style.newStyle().width(maxWidth + 4);The ListEnumerator interface provides enumerators for list rendering in trees and lists.
package com.williamcallahan.tui4j.compat.lipgloss;
interface ListEnumerator extends TreeEnumerator {
int abcLen = 26;
static TreeEnumerator alphabet();
static TreeEnumerator arabic();
static TreeEnumerator roman();
static TreeEnumerator bullet();
static TreeEnumerator asterisk();
static TreeEnumerator dash();
}Usage:
// Use with Tree component
Tree tree = new Tree()
.enumerator(ListEnumerator.arabic()); // 1., 2., 3., ...
Tree bulletTree = new Tree()
.enumerator(ListEnumerator.bullet()); // •, •, •, ...
Tree alphaTree = new Tree()
.enumerator(ListEnumerator.alphabet()); // a., b., c., ...The Output class provides terminal output configuration and color profile detection.
package com.williamcallahan.tui4j.compat.lipgloss;
class Output {
Output();
static Output defaultOutput();
ColorProfile envColorProfile();
boolean hasDarkBackground();
TerminalColor backgroundColor();
}Usage:
// Get default terminal output
Output output = Output.defaultOutput();
// Check color capabilities
ColorProfile profile = output.envColorProfile();
boolean darkMode = output.hasDarkBackground();
TerminalColor bgColor = output.backgroundColor();
// Use for adaptive styling
Style adaptiveStyle;
if (output.hasDarkBackground()) {
adaptiveStyle = Style.newStyle().foreground("#FFFFFF");
} else {
adaptiveStyle = Style.newStyle().foreground("#000000");
}The ANSIColors class provides the 256-color ANSI palette as hex values.
package com.williamcallahan.tui4j.compat.lipgloss.color;
final class ANSIColors {
static final String[] ANSI_HEX; // 256-element hex color palette
}Usage:
// Access ANSI color palette
String color42 = ANSIColors.ANSI_HEX[42]; // Get hex value for ANSI color 42
TerminalColor termColor = Color.color(color42);
// Use in styles
Style ansiStyle = Style.newStyle().foreground(ANSIColors.ANSI_HEX[196]); // Bright redStyle createStyle(boolean isActive) {
Style style = Style.newStyle()
.padding(1, 2)
.border(StandardBorder.RoundedBorder);
if (isActive) {
style = style
.foreground("#00FF00")
.bold(true)
.borderForeground("#00FF00");
} else {
style = style
.foreground("#666666")
.borderForeground("#666666");
}
return style;
}// Base style
Style baseStyle = Style.newStyle()
.padding(1)
.border(StandardBorder.NormalBorder);
// Derive variants
Style successStyle = baseStyle
.foreground("#00FF00")
.borderForeground("#00FF00");
Style errorStyle = baseStyle
.foreground("#FF0000")
.borderForeground("#FF0000");
Style warningStyle = baseStyle
.foreground("#FFFF00")
.borderForeground("#FFFF00");Style createResponsiveStyle(int terminalWidth) {
int contentWidth = Math.max(40, Math.min(80, terminalWidth - 4));
return Style.newStyle()
.width(contentWidth)
.padding(1, 2)
.alignHorizontal(Position.Center);
}class Theme {
Style primaryStyle = Style.newStyle()
.foreground("#FFFFFF")
.background("#0066CC")
.bold(true);
Style secondaryStyle = Style.newStyle()
.foreground("#FFFFFF")
.background("#666666");
Style errorStyle = Style.newStyle()
.foreground("#FFFFFF")
.background("#FF0000")
.bold(true);
Style successStyle = Style.newStyle()
.foreground("#FFFFFF")
.background("#00AA00")
.bold(true);
}// Header-Body-Footer layout
Style headerStyle = Style.newStyle()
.width(80)
.padding(1, 2)
.background("#0066CC")
.foreground("#FFFFFF")
.bold(true);
Style bodyStyle = Style.newStyle()
.width(80)
.height(20)
.padding(1, 2)
.border(StandardBorder.NormalBorder)
.alignVertical(Position.Top);
Style footerStyle = Style.newStyle()
.width(80)
.padding(0, 2)
.foreground("#666666");
String header = headerStyle.render("Application Title");
String body = bodyStyle.render("Content goes here...");
String footer = footerStyle.render("Press 'q' to quit");
String layout = VerticalJoinDecorator.join(
Position.Left,
header,
body,
footer
);Style leftColumnStyle = Style.newStyle()
.width(40)
.height(20)
.padding(1)
.border(StandardBorder.NormalBorder)
.borderForeground("#00FF00");
Style rightColumnStyle = Style.newStyle()
.width(40)
.height(20)
.padding(1)
.border(StandardBorder.NormalBorder)
.borderForeground("#FF00FF");
String leftColumn = leftColumnStyle.render("Left content");
String rightColumn = rightColumnStyle.render("Right content");
String layout = HorizontalJoinDecorator.join(
Position.Top,
leftColumn,
rightColumn
);Install with Tessl CLI
npx tessl i tessl/maven-com-williamcallahan--tui4j@0.3.0