Button
Material Design 3.0 push button with text, icon, and multiple style variants
Namespace: Beep.Skia.Controls — Inherits: MaterialControl → SkiaComponent
Table of Contents
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:
| Property | Type | Description |
|---|---|---|
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
| Event | Signature | Description |
|---|---|---|
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:
| Style | Description | Use 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.