Namespace: Beep.Skia.Controls — Inherits: Notification → MaterialControl → SkiaComponent • Dialog → MaterialControl → SkiaComponent

Overview

The Notification, StatusBar, and Dialog controls provide Material Design 3.0 messaging and overlay feedback entirely rendered with SkiaSharp. Notification (toast/snackbar) displays transient messages at a configurable screen position with automatic dismissal. StatusBar is a persistent bottom strip for status information, progress, and quick actions. Dialog renders a modal overlay with a title, body content, and action buttons, blocking interaction with the canvas beneath until dismissed.

All overlay components are managed by the OverlayManager, which handles z-ordering, focus trapping (for dialogs), and dismiss-on-escape behavior. Notifications and dialogs use enter/exit animations following MD3 motion guidelines.

Auto-Dismiss Timers

Notifications support configurable duration with a progress bar indicating time remaining before dismissal.

Modal Overlay

Dialogs render a semi-transparent scrim over the entire canvas, blocking pointer events to components behind.

Action Buttons

Snackbars and dialogs support inline action buttons for undo, confirm, cancel, and dismiss operations.

Status Icons

Each notification type renders a distinct icon (checkmark, warning triangle, error circle, info circle) using theme-aware colors.

Notification Properties

PropertyTypeDescription
Message string The notification body text. Supports multi-line for longer messages. Rendered using BodyMedium typography.
Type NotificationType Enum: Info, Success, Warning, Error. Controls the icon, accent color, and background tint. See Notification Types below.
Duration float Display duration in milliseconds. After this time elapses, the notification plays its exit animation and is removed. Default is 4000 (4 seconds). Set to 0 for persistent notifications that require manual dismissal.
Position NotificationPosition Enum: Top, Bottom (default), TopLeft, TopRight, BottomLeft, BottomRight, Center. Controls where the notification appears within the canvas/client area.
IsDismissible bool When true, a close (X) button is rendered at the trailing edge. Clicking it dismisses the notification immediately. Default is true.
ShowProgress bool When true, a thin progress bar is rendered at the bottom of the notification indicating time remaining. Default is false.
ActionText string Optional text for an action button (e.g., "Undo", "Retry"). The button is rendered at the trailing edge using LabelLarge typography in Primary color.
CornerRadius float Corner rounding of the notification surface. Default is 4f per MD3 snackbar spec.
Elevation int Material elevation shadow. Default is 6.
MinWidth float Minimum width of the notification. Default is 344f. Notifications auto-size to content up to MaxWidth.
MaxWidth float Maximum width before text wraps. Default is 568f.

StatusBar & StatusBarItem

The StatusBar is a persistent horizontal strip typically rendered at the bottom of the canvas. It contains StatusBarItem children that display text, icons, or progress indicators.

PropertyTypeDescription
Items List<StatusBarItem> Collection of status items displayed left-to-right in the bar.
BarHeight float Height of the status bar. Default is 24f.
ShowGrip bool When true, a resize grip icon is rendered at the right edge. Default is false.

StatusBarItem

PropertyTypeDescription
TextstringThe status text label.
IconSKPathOptional icon rendered before the text.
WidthfloatFixed width of the item cell. Items with Width = 0 auto-size to their content.
AlignmentStatusAlignmentEnum: Left (default) or Right. Right-aligned items are pushed to the bar's right edge.

Dialog Support

The Dialog control renders a modal overlay dialog following MD3 dialog specifications. A semi-transparent scrim covers the canvas behind the dialog, and pointer events outside the dialog bounds are intercepted to enforce modality.

PropertyTypeDescription
Title string Dialog headline text. Rendered using HeadlineSmall typography. Set to null to hide.
Body string or SkiaComponent The dialog's body content. Can be a simple string (rendered as BodyMedium text) or a SkiaComponent for custom content (forms, lists, etc.).
Buttons List<Button> Action buttons rendered in the dialog footer, right-aligned. Typical use: one or two Button instances (e.g., Cancel + Confirm).
IsOpen bool Controls dialog visibility. Setting to true registers the scrim and dialog with OverlayManager and plays the enter animation.
IsModal bool When true (default), the scrim is rendered and background interaction is blocked. When false, the dialog is non-modal and background clicks pass through.
ScrimOpacity float Opacity of the background scrim (0.0–1.0). Default is 0.32f per MD3 spec.
CornerRadius float Dialog surface corner rounding. Default is 28f per MD3 dialog spec.
Elevation int Material elevation shadow. Default is 8.
MaxWidth float Maximum dialog width. Default is 560f. The dialog auto-sizes to content within this constraint.
MinHeight float Minimum dialog height. Default is 0 (auto-size).
EventSignatureDescription
OpenedEventHandlerRaised after the dialog enter animation completes.
ClosedEventHandlerRaised after the dialog exit animation completes and the dialog is removed from the overlay layer.
ActionClickedEventHandler<string>Raised when an action button is clicked. The argument is the Tag of the button.
ActionClickedEventHandler<string> (Notification)Raised when the notification's ActionText button is clicked.

Notification Types

TypeIconAccent ColorUse When
NotificationType.Info Information circle (i) Primary from theme Neutral status messages, tips, procedural feedback
NotificationType.Success Checkmark circle #4CAF50 (MD3 green) Successful operations: save, export, upload, apply
NotificationType.Warning Warning triangle #FF9800 (MD3 orange) Non-critical issues: unsaved changes, deprecated feature, approaching limits
NotificationType.Error Error circle with X #F44336 (MD3 red) Failed operations: save error, connection lost, validation failure

The accent color tints the leading icon and the left border of the notification surface. The background is always InverseSurface with InverseOnSurface text for high contrast.

Code Example

Showing a Success Notification

var notification = new Notification
{
    Message = "Project saved successfully.",
    Type = NotificationType.Success,
    Duration = 3000,
    Position = NotificationPosition.Bottom,
    ShowProgress = true
};

notification.ActionClicked += (s, action) =>
    Console.WriteLine($"Action: {action}");

notification.Initialize();
notification.Show();

drawingManager.RequestRedraw();

Snackbar with Undo Action

var snackbar = new Notification
{
    Message = "Item deleted.",
    Type = NotificationType.Info,
    Duration = 5000,
    Position = NotificationPosition.Bottom,
    ActionText = "Undo",
    ShowProgress = true
};

snackbar.Initialize();

snackbar.ActionClicked += (s, action) =>
{
    if (action == "Undo")
    {
        RestoreDeletedItem();
    }
};

snackbar.Show();

StatusBar with Multiple Items

var statusBar = new StatusBar
{
    X = 0, Y = 0,
    Width = 800,
    BarHeight = 28,
    Items = new List<StatusBarItem>
    {
        new() { Text = "Ready", Icon = null, Width = 120 },
        new() { Text = "", Width = 0 },
        new() { Text = "Ln 24, Col 12", Alignment = StatusAlignment.Right, Width = 140 },
        new() { Text = "UTF-8", Alignment = StatusAlignment.Right, Width = 80 },
        new() { Text = "100%", Alignment = StatusAlignment.Right, Width = 60 }
    }
};

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

Modal Confirmation Dialog

var cancelButton = new Button
{
    Text = "Cancel",
    ButtonStyle = ButtonStyle.Text,
    Width = 80, Height = 40,
    Tag = "cancel"
};

var confirmButton = new Button
{
    Text = "Delete",
    ButtonStyle = ButtonStyle.Filled,
    Width = 80, Height = 40,
    Tag = "confirm"
};

cancelButton.Initialize();
confirmButton.Initialize();

var dialog = new Dialog
{
    Title = "Delete Project?",
    Body = "This action cannot be undone. All associated files and configurations will be permanently removed.",
    Buttons = new List<Button> { cancelButton, confirmButton },
    IsModal = true,
    MaxWidth = 480
};

dialog.Initialize();

dialog.ActionClicked += (s, tag) =>
{
    if (tag == "confirm")
    {
        DeleteProject();
        ShowNotification("Project deleted.", NotificationType.Success);
    }
    dialog.Close();
};

dialog.Open();
drawingManager.RequestRedraw();

Error Notification (Top-Right, Persistent)

var errorNotification = new Notification
{
    Message = "Failed to connect to database.\nCheck your connection settings and try again.",
    Type = NotificationType.Error,
    Duration = 0,
    Position = NotificationPosition.TopRight,
    IsDismissible = true,
    ActionText = "Retry"
};

errorNotification.Initialize();

errorNotification.ActionClicked += (s, action) =>
{
    if (action == "Retry") RetryConnection();
};

errorNotification.Show();

Notification Manager (Helper Pattern)

public static class NotificationManager
{
    public static void ShowInfo(string message, string actionText = null,
        Action action = null)
    {
        Show(message, NotificationType.Info, actionText, action);
    }

    public static void ShowSuccess(string message)
    {
        Show(message, NotificationType.Success);
    }

    public static void ShowError(string message, string actionText = null,
        Action action = null)
    {
        Show(message, NotificationType.Error, actionText, action, duration: 0);
    }

    private static void Show(string message, NotificationType type,
        string actionText = null, Action action = null, float duration = 4000)
    {
        var notification = new Notification
        {
            Message = message,
            Type = type,
            Duration = duration,
            Position = NotificationPosition.Bottom,
            ActionText = actionText
        };
        notification.Initialize();

        if (actionText != null && action != null)
            notification.ActionClicked += (s, a) => action();

        notification.Show();
    }
}