Skip to content

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:

csharp
Color.Default

Named Colors (256-color palette)

Standard terminal colors:

csharp
// 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.LightGray

Indexed Colors

Access any of the 256-color palette:

csharp
Color.FromIndex(42)  // Index 0-255

The 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:

csharp
// From RGB values
Color.FromRgb(255, 128, 0)  // Orange

// From hex string
Color.FromHex("#FF8000")
Color.FromHex("FF8000")     // # is optional

Applying Colors

Foreground Color

csharp
new TextNode("Colored text")
    .WithForeground(Color.Cyan)

Background Color

csharp
new TextNode("Highlighted")
    .WithBackground(Color.Yellow)
    .WithForeground(Color.Black)

Both Colors

csharp
new TextNode("Styled")
    .WithForeground(Color.White)
    .WithBackground(Color.Blue)

Color Support by Component

ComponentForegroundBackgroundOther
TextNode-
PanelNode--Border, Title
SpinnerNode--Spinner, Label
TextInputNodePlaceholder, Cursor, Selection
StreamingTextNodePrefix

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

Terminal256-colorTrue Color
Windows Terminal
iTerm2
GNOME Terminal
VS Code Terminal
macOS Terminal.appLimited
cmd.exeLimited

Color API Reference

View Color implementation
csharp
// 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);

    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
}

Released under the Apache 2.0 License.