A modern, feature-rich terminal UI framework for Dart. Build interactive command-line interfaces with ease using a component-based architecture.
Konsole provides a simple yet powerful way to create terminal applications with rich UI components like boxes, buttons, spinners, and more.
## Features- 🎨 Rich component library - Buttons, boxes, spinners, text labels, and more
- 📊 Flexible layout system - Use rows and columns for intuitive layouts
- 🎯 Focus management - Tab navigation between interactive elements
- 🌈 ANSI color support - Full terminal color customization
- ⌨️ Input handling - Process keyboard input from your users
- 🔄 Update loop - Automatic rendering with animation support
Add Konsole to your pubspec.yaml
:
dependencies:
konsole: ^1.0.0
Then run:
dart pub get
Konsole is built around a few simple concepts:
- Components: UI elements like Button, Text, Box
- Layouts: Row and Column components for organizing elements
- Application: The main Konsole class that manages components and rendering
- Input Handling: Each component can respond to user input
Component | Description |
---|---|
Text |
Simple text display with color support |
Button |
Interactive button with callback support |
Box |
Container with border and optional title |
Spinner |
Animated loading indicator with multiple styles |
More to come.
Component | Description |
---|---|
Row |
Horizontal layout container |
Column |
Vertical layout container |
import 'package:konsole/konsole.dart';
void main() {
final app = Konsole();
app.add(Text.success("Hello Konsole!"));
app.run();
}
See example/components/texts.dart
for a full showcase of all text styles and extension methods:
import 'package:konsole/konsole.dart';
void main() {
final examples = [
Text('Default Text'),
Text.success('Success Text'),
Text.error('Error Text'),
Text.warning('Warning Text'),
Text.info('Info Text'),
Text.muted('Muted Text'),
Text.highlight('Highlight Text'),
Text.title('Title Text'),
Text.subtitle('Subtitle Text'),
Text.accent('Accent Text'),
Text('Bold Text').bold(),
Text('Italic Text').italic(),
Text('Underline Text').underline(),
Text('Custom Color').withColor(KonsoleColors.magenta),
Text('Custom BG').withBackgroundColor(KonsoleColors.bgCyan),
Text('Right Aligned', alignment: TextAlignment.right, maxWidth: 30),
Text('Center Aligned', alignment: TextAlignment.center, maxWidth: 30),
Text(
'Wrapped text example that is long enough to demonstrate word wrapping.',
maxWidth: 20,
wordWrap: true,
),
Text('With Prefix', prefix: '>> '),
Text('With Suffix', suffix: ' <<'),
];
final app = Konsole();
app.add(Column(examples));
app.run();
}
See example/apps/konsole_example.dart
for a full-featured interactive demo with counter, spinners, and more.
import 'package:konsole/konsole.dart';
class Counter extends KonsoleComponent {
int value;
String fgColor;
String? bgColor;
int totalWidth;
Counter({
this.value = 0,
this.fgColor = KonsoleColors.white,
this.bgColor,
this.totalWidth = 20,
super.marginHorizontal,
super.marginVertical,
}) : super(width: totalWidth, height: 1) {
focusable = true;
}
@override
String render() {
String text = 'Counter: $value';
text =
text.length > totalWidth
? text.substring(0, totalWidth)
: text.padRight(totalWidth);
return Ansi.color(text, fg: fgColor, bgColor: bgColor);
}
@override
void handleInput(String input) {
if (focused) {
if (input == '\x1B[A') value++;
if (input == '\x1B[B') value--;
}
}
}
void main() {
final app = Konsole();
final counter = Counter(fgColor: KonsoleColors.red, totalWidth: 35);
final counterBox = Column([
counter,
Column([
Button(
'Up',
fgColor: KonsoleColors.magenta,
onPressed: () => counter.value++,
customWidth: 10,
),
Button(
'Down',
fgColor: KonsoleColors.yellow,
onPressed: () => counter.value--,
customWidth: 10,
),
]),
]);
app.add(
Row([
counterBox,
Column([
Spinner.line(fgColor: KonsoleColors.cyan),
Spinner.dot(fgColor: KonsoleColors.yellow),
Spinner.box(fgColor: KonsoleColors.magenta),
Spinner(fgColor: KonsoleColors.blue),
]),
]),
);
app.run();
}
Display styled text with color and formatting support:
Text.success("Success!");
Text.error("Error!");
Text.warning("Warning!");
Text.info("Info");
Text.muted("Muted");
Text.highlight("Highlight");
Text.title("Title");
Text.subtitle("Subtitle");
Text.accent("Accent");
// Use extension methods for chaining styles
Text("Bold").bold();
Text("Italic").italic();
Text("Underline").underline();
Text("Custom Color").withColor(KonsoleColors.magenta);
Text("Custom BG").withBackgroundColor(KonsoleColors.bgCyan);
Text("Right Aligned", alignment: TextAlignment.right, maxWidth: 30);
Text("Center Aligned", alignment: TextAlignment.center, maxWidth: 30);
Text("Wrapped text example that is long enough to demonstrate word wrapping.", maxWidth: 20, wordWrap: true);
Text("With Prefix", prefix: '>> ');
Text("With Suffix", suffix: ' <<');
Interactive button that can respond to user input:
Button(
"Click Me",
fgColor: KonsoleColors.white,
bgColor: KonsoleColors.bgBlue,
onPressed: () => print("Button clicked!"),
)
Container with border and optional title:
Box(
Text("Content inside box"),
title: "Box Title",
fgColor: KonsoleColors.cyan,
)
Animated loading indicators with multiple styles:
// Default spinner '⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'
Spinner(fgColor: KonsoleColors.blue)
// Dot-style spinner '.', '..', '...', '....'
Spinner.dot(fgColor: KonsoleColors.yellow)
// Line-style spinner
Spinner.line(fgColor: KonsoleColors.cyan)
// Box-style spinner '□', '■', '▣', '▢'
Spinner.box(fgColor: KonsoleColors.magenta)
Interactive numeric counter:
See example/apps/counter.dart
for a full implementation.
Tab
: Move focus between interactive componentsEnter
: Activate focused buttonsUp/Down Arrow
: Interact with counter componentsq
: Quit the application
Konsole provides built-in ANSI color constants:
// Foreground colors
KonsoleColors.black
KonsoleColors.red
KonsoleColors.green
KonsoleColors.yellow
KonsoleColors.blue
KonsoleColors.magenta
KonsoleColors.cyan
KonsoleColors.white
// Background colors
KonsoleColors.bgBlack
KonsoleColors.bgRed
KonsoleColors.bgGreen
KonsoleColors.bgYellow
KonsoleColors.bgBlue
KonsoleColors.bgMagenta
KonsoleColors.bgCyan
KonsoleColors.bgWhite
Extend the KonsoleComponent
class to create your own components:
class MyCustomComponent extends KonsoleComponent {
MyCustomComponent({super.marginHorizontal, super.marginVertical}) : super(width: 10, height: 1);
@override
String render() {
return "My custom component";
}
@override
void handleInput(String input) {
// Handle input here
}
@override
void update(double dt) {
// Update state here
}
}
Konsole uses a simple but powerful layout system with two main layout components:
- Row: Horizontal layout that arranges components from left to right
- Column: Vertical layout that arranges components from top to bottom
Both layout components support margins:
// Horizontal layout with margin
Row([component1, component2], marginHorizontal: 2, marginVertical: 1)
// Vertical layout with margin
Column([component1, component2], marginHorizontal: 2, marginVertical: 1)
Each component can also have its own margins:
Text("Hello", marginHorizontal: 2, marginVertical: 1)
This project is licensed under the MIT License - see the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request