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

Overview

The Button control is a Material Design 3.0 push button rendered entirely with SkiaSharp. It supports text labels, optional icons, and five visual style variants matching the MD3 specification. Buttons respond to hover, press, and focus states with animated state layers and elevation changes, all drawn without using any WinForms or WPF primitives.

Every Button is a MaterialControl, meaning it inherits the full Material Design 3.0 theming system including elevation shadows, state-layer overlays, ripple animations on press, and automatic color resolution from the active theme tokens.

Material State Layers

Hover, focus, and pressed states render translucent overlays using theme-aware opacity values.

Ripple Animation

Touch and click interactions trigger a circular ripple emanating from the contact point.

Icon Support

Render a leading or trailing icon glyph alongside the button text using an SKBitmap or path.

Elevation Changes

Elevated and Filled tonal variants animate shadow depth on hover and press.

Properties

In addition to inherited properties from MaterialControl and SkiaComponent (X, Y, Width, Height, Enabled, Visible), the Button control exposes the following:

PropertyTypeDescription
Text string The label displayed on the button. Supports UTF-8 text rendered via SKPaint. Default is "".
Icon SKBitmap Optional icon image rendered before the text. When set, the text shifts to accommodate the icon with internal padding. Set to null for text-only buttons.
IconPath SKPath Alternative to Icon — a vector path for the icon drawn with the current theme's OnSurface color. Scales to IconSize.
IconSize float Desired size of the icon in logical pixels. Default is 18f. The icon is centered vertically within the button.
ButtonStyle ButtonStyle Enum controlling the visual variant. See Variants below. Default is Filled.
IsPressed bool Read-only. Indicates whether the button is currently in a pressed (mouse-down or touch-down) state. Used internally for state-layer rendering.
IsHovered bool Read-only. Indicates whether the mouse cursor is over the button's bounding rectangle. Activates the hover state layer.
IsFocused bool Read-only. Indicates keyboard focus. When true, a focus ring is drawn around the button perimeter.
CornerRadius float Radius of the rounded rectangle corners. Default is 20f (fully rounded pill shape). Set to 4f for a more squared appearance.
Elevation int Material Design elevation level (0–5). Controls the shadow depth rendered beneath the button. Elevated and Filled styles use elevation changes for hover/press feedback. Default is 0.
MinimumWidth float Minimum width constraint. The button will not shrink below this value regardless of text length. Default is 64f.
PaddingHorizontal float Internal horizontal padding between the text/icon and the button edges. Default is 24f per MD3 specification.

Events

EventSignatureDescription
Click EventHandler Raised when the button is released after a press within its bounds. This is the primary interaction event. Does not fire if the pointer leaves the button before release.
PressedChanged EventHandler<bool> Raised when the IsPressed state changes. The boolean argument is true on press and false on release. Useful for press-and-hold interactions.
HoverChanged EventHandler<bool> Raised when the mouse enters or leaves the button bounds. The boolean argument reflects IsHovered.

Variants

Material Design 3.0 defines five button styles. Set the ButtonStyle property to choose:

StyleDescriptionUse When
ButtonStyle.Filled Solid fill using the Primary theme color with white text. Has a subtle elevation shadow. The default style. Primary actions, call-to-action, submit.
ButtonStyle.Outlined Transparent background with a 1px border in Outline color. Text is Primary color. Secondary actions, less emphasis than filled.
ButtonStyle.Text No background, no border. Only the label text is visible in Primary color. Minimal visual weight. Tertiary actions, inline links, icon-only toolbars.
ButtonStyle.Elevated White/light background with a visible shadow. Elevation increases on hover and press. Cards, dialogs, surfaces where the button needs to stand out from a colored background.
ButtonStyle.Tonal Filled with the SecondaryContainer color and OnSecondaryContainer text. No shadow. Medium-emphasis actions that should feel related to the surface.

Each style automatically applies the correct theme tokens. You do not need to manually set colors; the button resolves colors from the active MaterialTheme based on its style and state.

Code Example

Creating a Filled Button

var submitButton = new Button
{
    Text = "Submit",
    ButtonStyle = ButtonStyle.Filled,
    X = 100,
    Y = 50,
    Width = 120,
    Height = 40,
    CornerRadius = 20f,
    Elevation = 1
};

submitButton.Initialize();
submitButton.Click += (s, e) => Console.WriteLine("Button clicked!");

drawingManager.AddComponent(submitButton);
drawingManager.RequestRedraw();

Outlined Button with Icon

var iconPath = SKPath.ParseSvgPathData(
    "M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z");

var addButton = new Button
{
    Text = "Add Item",
    IconPath = iconPath,
    IconSize = 18f,
    ButtonStyle = ButtonStyle.Outlined,
    X = 250,
    Y = 50,
    Width = 140,
    Height = 40
};

addButton.Initialize();
drawingManager.AddComponent(addButton);

Setting Up All Five Variants

var styles = new[]
{
    (ButtonStyle.Filled,   100f, "Filled"),
    (ButtonStyle.Outlined, 160f, "Outlined"),
    (ButtonStyle.Text,     220f, "Text"),
    (ButtonStyle.Elevated, 280f, "Elevated"),
    (ButtonStyle.Tonal,    340f, "Tonal")
};

foreach (var (style, y, label) in styles)
{
    var btn = new Button
    {
        Text = label,
        ButtonStyle = style,
        X = 100,
        Y = y,
        Width = 140,
        Height = 40
    };
    btn.Initialize();
    drawingManager.AddComponent(btn);
}

drawingManager.RequestRedraw();

Handling Press State for Press-and-Hold

var holdButton = new Button
{
    Text = "Hold Me",
    ButtonStyle = ButtonStyle.Tonal,
    X = 100,
    Y = 420,
    Width = 140,
    Height = 40
};

holdButton.Initialize();
holdButton.PressedChanged += (s, pressed) =>
{
    if (pressed)
        Console.WriteLine("Press started - begin long-press timer");
    else
        Console.WriteLine("Press released - cancel timer");
};

drawingManager.AddComponent(holdButton);

Tip

Use ButtonStyle.Text icon-only buttons for toolbar actions. Set Text = "" and only provide an IconPath or Icon bitmap. The button will render as a compact 40×40 icon button with a circular ripple.