Namespace: Beep.Skia.Controls — Inherits: MaterialControl → SkiaComponent

Overview

The TextBox and TextArea controls provide Material Design 3.0 text input fields rendered entirely with SkiaSharp. TextBox handles single-line input (e.g., form fields, search boxes, labels) while TextArea extends it with multi-line editing, word wrap, and line count tracking. Both controls use SKCanvas for text rendering and integrate with the platform's keyboard input system via the InputManager.

Text fields follow the MD3 "Filled" and "Outlined" visual styles with animated label transitions, floating placeholder labels, error states, and helper text. The cursor is a blinking vertical line drawn by the control's render cycle. Text selection is drawn as a semi-transparent highlight rectangle.

TextBox Properties

PropertyTypeDescription
Text string The current text value. Setting this programmatically moves the cursor to the end unless CursorPosition is also set.
Placeholder string Placeholder text shown when Text is empty. Rendered in OnSurfaceVariant color at 60% opacity. In MD3 style, the placeholder acts as a label that floats above the field when focused or populated.
MaxLength int Maximum character count. Input beyond this limit is rejected. Default is 0 (unlimited). A character counter is displayed below the field when set.
IsPassword bool When true, characters are rendered as bullets (•) instead of the actual text. A visibility toggle icon is drawn at the trailing edge. Default is false.
IsReadOnly bool When true, the field cannot be edited but remains selectable for copy operations. The background is rendered in a muted state. Default is false.
FieldStyle TextFieldStyle Enum: Filled (default) or Outlined. Filled has a filled background with an underline indicator. Outlined has a transparent background with a full border.
IsFocused bool Read-only. Indicates whether the field has keyboard focus. When focused, the underline/outline is drawn in Primary color.
CursorPosition int Zero-based index of the insertion cursor within Text. Setting this moves the cursor. Read to determine where the next typed character will be inserted.
IsCursorVisible bool Read-only. Indicates whether the blinking cursor is currently shown (alternates on a timer).
HelperText string Optional helper text displayed below the field in BodySmall typography. Used for hints or validation messages.
HasError bool When true, the field renders in Error color (underline, outline, label) and the helper text color changes to Error. Default is false.
LeadingIcon SKPath Optional icon drawn at the left side of the field. Icon color follows the field state.
TrailingIcon SKPath Optional icon drawn at the right side. For IsPassword fields, a visibility toggle icon is automatically managed here.

TextArea Properties

TextArea inherits all TextBox properties and adds multi-line support:

PropertyTypeDescription
LineCount int Read-only. The number of text lines, accounting for newline characters and word wrap. Updated on every text change.
WordWrap bool When true (default), text automatically wraps at the field's width boundary. When false, horizontal scrolling is enabled.
LineHeight float Vertical spacing between wrapped lines in logical pixels. Default is 20f.
AcceptsReturn bool When true, the Enter key inserts a newline. When false, Enter triggers the default action or is ignored. Default is true.
AcceptsTab bool When true, Tab inserts a tab character instead of moving focus. Default is false.
MinLines int Minimum number of visible lines. The TextArea will not shrink below this height. Default is 1.
MaxLines int Maximum number of visible lines before vertical scrolling begins. 0 for unlimited. Default is 0.

Events

EventSignatureDescription
TextChanged EventHandler<string> Raised whenever Text changes, either by user input or programmatic assignment. The string argument is the new text value. Fires after the internal state is updated.
FocusChanged EventHandler<bool> Raised when the field gains or loses keyboard focus. The boolean is the new IsFocused value.
CursorPositionChanged EventHandler<int> Raised when the cursor position changes, either by click, arrow keys, or programmatic assignment.

Code Example

Basic TextBox (Filled Style)

var nameField = new TextBox
{
    Text = "",
    Placeholder = "Full Name",
    FieldStyle = TextFieldStyle.Filled,
    MaxLength = 100,
    X = 40,
    Y = 40,
    Width = 300,
    Height = 56
};

nameField.Initialize();
nameField.TextChanged += (s, text) =>
    Console.WriteLine($"Name updated: {text}");

drawingManager.AddComponent(nameField);
drawingManager.RequestRedraw();

Outlined Password Field with Error

var passwordField = new TextBox
{
    Placeholder = "Password",
    IsPassword = true,
    FieldStyle = TextFieldStyle.Outlined,
    MaxLength = 32,
    HelperText = "Must be at least 8 characters",
    X = 40,
    Y = 120,
    Width = 300,
    Height = 56
};

passwordField.Initialize();

passwordField.TextChanged += (s, text) =>
{
    passwordField.HasError = text.Length > 0 && text.Length < 8;
    passwordField.HelperText = passwordField.HasError
        ? "Password is too short"
        : "Must be at least 8 characters";
};

drawingManager.AddComponent(passwordField);

Multi-Line TextArea

var descriptionArea = new TextArea
{
    Text = "",
    Placeholder = "Description",
    FieldStyle = TextFieldStyle.Outlined,
    WordWrap = true,
    MinLines = 3,
    MaxLines = 8,
    AcceptsReturn = true,
    AcceptsTab = false,
    X = 40,
    Y = 200,
    Width = 400,
    Height = 120
};

descriptionArea.Initialize();
descriptionArea.TextChanged += (s, text) =>
    Console.WriteLine($"Description lines: {descriptionArea.LineCount}");

drawingManager.AddComponent(descriptionArea);

ReadOnly TextBox with Leading Icon

var iconPath = SKPath.ParseSvgPathData(
    "M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z");

var readonlyField = new TextBox
{
    Text = "This field is not editable",
    IsReadOnly = true,
    LeadingIcon = iconPath,
    FieldStyle = TextFieldStyle.Filled,
    X = 40,
    Y = 350,
    Width = 400,
    Height = 56
};

readonlyField.Initialize();
drawingManager.AddComponent(readonlyField);
drawingManager.RequestRedraw();

Tip

Text input in SkiaSharp-rendered controls relies on keyboard event forwarding. The TextBox control registers itself with the InputManager on focus to receive OnKeyDown and OnKeyPress events. Ensure your host application forwards platform keyboard events to the InputManager for text input to work.