Colors
Termina provides a flexible color system supporting terminal defaults, 256-color palettes, and true color (24-bit RGB).
Color Modes
Default
Uses the terminal's default foreground or background color:
Color.DefaultNamed Colors (256-color palette)
Standard terminal colors:
// Basic colors
Color.Black
Color.Red
Color.Green
Color.Yellow
Color.Blue
Color.Magenta
Color.Cyan
Color.White
// Bright variants
Color.BrightBlack
Color.BrightRed
Color.BrightGreen
Color.BrightYellow
Color.BrightBlue
Color.BrightMagenta
Color.BrightCyan
Color.BrightWhite
// Grayscale
Color.Gray
Color.DarkGray
Color.LightGrayIndexed Colors
Access any of the 256-color palette:
Color.FromIndex(42) // Index 0-255The 256-color palette includes:
- 0-7: Standard colors
- 8-15: Bright colors
- 16-231: 6×6×6 color cube
- 232-255: Grayscale ramp
RGB Colors (True Color)
24-bit color for modern terminals:
// From RGB values
Color.FromRgb(255, 128, 0) // Orange
// From hex string
Color.FromHex("#FF8000")
Color.FromHex("FF8000") // # is optionalApplying Colors
Foreground Color
new TextNode("Colored text")
.WithForeground(Color.Cyan)Background Color
new TextNode("Highlighted")
.WithBackground(Color.Yellow)
.WithForeground(Color.Black)Both Colors
new TextNode("Styled")
.WithForeground(Color.White)
.WithBackground(Color.Blue)Color Interpolation
Color.Lerp linearly interpolates between two RGB colors:
var midpoint = Color.Lerp(Color.FromRgb(255, 0, 0), Color.FromRgb(0, 0, 255), 0.5f);
// Result: purple (127, 0, 127)If either color is not in RGB mode, Lerp returns the first color unchanged.
Gradients
The Gradient record defines a series of color stops and interpolates between them. Use gradients with GraphNode and ProgressBarNode for smooth color transitions.
// Evenly spaced stops
var gradient = Gradient.Create(Color.Red, Color.Yellow, Color.Green);
// Custom stop positions
var custom = Gradient.Create(
(0.0f, Color.FromRgb(255, 0, 0)),
(0.3f, Color.FromRgb(255, 200, 0)),
(1.0f, Color.FromRgb(0, 255, 0)));
// Sample at any position (0–1)
Color color = gradient.Sample(0.5f);At least two colors are required. Positions outside the 0–1 range are clamped.
Color Support by Component
| Component | Foreground | Background | Other |
|---|---|---|---|
| TextNode | ✓ | ✓ | - |
| PanelNode | - | - | Border, Title |
| SpinnerNode | - | - | Spinner, Label |
| TextInputNode | ✓ | ✓ | Placeholder, Cursor, Selection |
| StreamingTextNode | ✓ | ✓ | Prefix |
| GraphNode | - | - | Gradient, Single color |
| ProgressBarNode | - | - | Gradient, Single color, Empty color |
Terminal Compatibility
WARNING
Not all terminals support all color modes:
- Default - Works everywhere
- Indexed (0-15) - Works in almost all terminals
- Indexed (16-255) - Requires 256-color support
- RGB - Requires true color support (most modern terminals)
When RGB colors are used in a terminal that doesn't support them, results may vary.
Common Terminal Support
| Terminal | 256-color | True Color |
|---|---|---|
| Windows Terminal | ✓ | ✓ |
| iTerm2 | ✓ | ✓ |
| GNOME Terminal | ✓ | ✓ |
| VS Code Terminal | ✓ | ✓ |
| macOS Terminal.app | ✓ | Limited |
| cmd.exe | Limited | ✗ |
Color API Reference
View Color implementation
// Copyright (c) Petabridge, LLC. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Termina.Terminal;
/// <summary>
/// Represents a color for terminal rendering.
/// Supports default, 256-color, and true color (24-bit RGB) modes.
/// </summary>
public readonly struct Color : IEquatable<Color>
{
/// <summary>
/// The color mode.
/// </summary>
public ColorMode Mode { get; }
/// <summary>
/// For 256-color mode, the palette index (0-255).
/// </summary>
public byte Index { get; }
/// <summary>
/// Red component for RGB mode (0-255).
/// </summary>
public byte R { get; }
/// <summary>
/// Green component for RGB mode (0-255).
/// </summary>
public byte G { get; }
/// <summary>
/// Blue component for RGB mode (0-255).
/// </summary>
public byte B { get; }
private Color(ColorMode mode, byte index = 0, byte r = 0, byte g = 0, byte b = 0)
{
Mode = mode;
Index = index;
R = r;
G = g;
B = b;
}
/// <summary>
/// Default terminal color (no explicit color set).
/// </summary>
public static Color Default => new(ColorMode.Default);
/// <summary>
/// Create a color from a 256-color palette index.
/// </summary>
public static Color FromIndex(byte index) => new(ColorMode.Indexed, index);
/// <summary>
/// Create a color from RGB values.
/// </summary>
public static Color FromRgb(byte r, byte g, byte b) => new(ColorMode.Rgb, 0, r, g, b);
/// <summary>
/// Create a color from a hex string (e.g., "#FF0000" or "FF0000").
/// </summary>
public static Color FromHex(string hex)
{
hex = hex.TrimStart('#');
if (hex.Length != 6)
throw new ArgumentException("Hex color must be 6 characters", nameof(hex));
var r = Convert.ToByte(hex[0..2], 16);
var g = Convert.ToByte(hex[2..4], 16);
var b = Convert.ToByte(hex[4..6], 16);
return FromRgb(r, g, b);
}
// Standard colors (using 256-color palette indices)
public static Color Black => FromIndex(0);
public static Color Red => FromIndex(1);
public static Color Green => FromIndex(2);
public static Color Yellow => FromIndex(3);
public static Color Blue => FromIndex(4);
public static Color Magenta => FromIndex(5);
public static Color Cyan => FromIndex(6);
public static Color White => FromIndex(7);
// Bright variants
public static Color BrightBlack => FromIndex(8);
public static Color BrightRed => FromIndex(9);
public static Color BrightGreen => FromIndex(10);
public static Color BrightYellow => FromIndex(11);
public static Color BrightBlue => FromIndex(12);
public static Color BrightMagenta => FromIndex(13);
public static Color BrightCyan => FromIndex(14);
public static Color BrightWhite => FromIndex(15);
// Extended grayscale (from 256-color palette)
public static Color Gray => FromIndex(244); // Medium gray
public static Color DarkGray => FromIndex(240); // Darker gray
public static Color LightGray => FromIndex(248); // Lighter gray
/// <summary>
/// Get the ANSI escape sequence for this color as a foreground color.
/// </summary>
public string ToForegroundAnsi() => Mode switch
{
ColorMode.Default => AnsiCodes.ForegroundDefault,
ColorMode.Indexed => AnsiCodes.Foreground256(Index),
ColorMode.Rgb => AnsiCodes.ForegroundRgb(R, G, B),
_ => AnsiCodes.ForegroundDefault
};
/// <summary>
/// Get the ANSI escape sequence for this color as a background color.
/// </summary>
public string ToBackgroundAnsi() => Mode switch
{
ColorMode.Default => AnsiCodes.BackgroundDefault,
ColorMode.Indexed => AnsiCodes.Background256(Index),
ColorMode.Rgb => AnsiCodes.BackgroundRgb(R, G, B),
_ => AnsiCodes.BackgroundDefault
};
public bool Equals(Color other) =>
Mode == other.Mode && Index == other.Index && R == other.R && G == other.G && B == other.B;
public override bool Equals(object? obj) => obj is Color other && Equals(other);
public override int GetHashCode() => HashCode.Combine(Mode, Index, R, G, B);
public static bool operator ==(Color left, Color right) => left.Equals(right);
public static bool operator !=(Color left, Color right) => !left.Equals(right);
/// <summary>
/// Linearly interpolate between two RGB colors.
/// If either color is not RGB mode, returns <paramref name="a"/> unchanged.
/// </summary>
public static Color Lerp(Color a, Color b, float t)
{
if (a.Mode != ColorMode.Rgb || b.Mode != ColorMode.Rgb)
return a;
t = Math.Clamp(t, 0f, 1f);
var r = (byte)(a.R + (b.R - a.R) * t);
var g = (byte)(a.G + (b.G - a.G) * t);
var bl = (byte)(a.B + (b.B - a.B) * t);
return FromRgb(r, g, bl);
}
public override string ToString() => Mode switch
{
ColorMode.Default => "Default",
ColorMode.Indexed => $"Index({Index})",
ColorMode.Rgb => $"RGB({R},{G},{B})",
_ => "Unknown"
};
}
/// <summary>
/// The mode of color specification.
/// </summary>
public enum ColorMode
{
/// <summary>
/// Use terminal's default color.
/// </summary>
Default,
/// <summary>
/// Use 256-color palette index.
/// </summary>
Indexed,
/// <summary>
/// Use 24-bit RGB color.
/// </summary>
Rgb
}