Skip to main content

Overview

DaisyModal is a modal dialog overlay with backdrop, supporting draggable positioning, ESC key to close, and click-outside-to-close behavior.

Properties

IsOpen

IsOpen
bool
default:"false"
Controls whether the modal is visible. Setting to true opens the modal, false closes it.

IsDraggable

IsDraggable
bool
default:"false"
Whether the dialog can be dragged by pointer. When enabled, a grab bar appears at the top.

Corner Radius

TopLeftRadius
double
default:"16.0"
Corner radius for the top-left corner.
TopRightRadius
double
default:"16.0"
Corner radius for the top-right corner.
BottomLeftRadius
double
default:"16.0"
Corner radius for the bottom-left corner.
BottomRightRadius
double
default:"16.0"
Corner radius for the bottom-right corner.

Protected Properties

These properties can be overridden in derived classes:
DialogBoundsMargin
double
default:"16"
Margin between the dialog and the viewport edges. Controls max width/height and drag bounds.
DialogOverlayLayer
Panel
Panel for adding overlay elements on top of the dialog content.
DialogOffset
Point
Current X/Y offset of the dialog from its centered position.

Protected Methods

SetDialogSize()

Sets the dialog host size. Useful for derived classes that calculate their own sizing.
protected void SetDialogSize(double width, double height)

ShouldCloseOnOutsideClick()

Controls whether tapping outside the dialog closes the modal. Override to customize.
protected virtual bool ShouldCloseOnOutsideClick() // Returns true by default

GetNeumorphicHostElement()

Returns the element that receives neumorphic effects (the dialog host).
protected override FrameworkElement? GetNeumorphicHostElement()

Usage Examples

XAML - Basic Modal

<controls:DaisyModal x:Name="MyModal">
    <StackPanel Padding="24" Spacing="16">
        <TextBlock Text="Modal Title" FontSize="20" FontWeight="SemiBold" />
        <TextBlock Text="This is a modal dialog." TextWrapping="Wrap" />
        <controls:DaisyButton 
            Content="Close" 
            Click="CloseModal" />
    </StackPanel>
</controls:DaisyModal>
private void OpenModal(object sender, RoutedEventArgs e)
{
    MyModal.IsOpen = true;
}

private void CloseModal(object sender, RoutedEventArgs e)
{
    MyModal.IsOpen = false;
}

XAML - Draggable Modal

<controls:DaisyModal IsDraggable="True">
    <StackPanel Padding="24" Spacing="12">
        <TextBlock Text="Drag me!" FontSize="18" FontWeight="SemiBold" />
        <TextBlock Text="You can drag this modal by the grab bar at the top." TextWrapping="Wrap" />
    </StackPanel>
</controls:DaisyModal>

XAML - Custom Corner Radius

<!-- Rounded top corners only -->
<controls:DaisyModal 
    TopLeftRadius="24" 
    TopRightRadius="24" 
    BottomLeftRadius="0" 
    BottomRightRadius="0">
    <TextBlock Text="Custom corners" Padding="24" />
</controls:DaisyModal>

XAML - Modal with Actions

<controls:DaisyModal x:Name="ConfirmModal">
    <StackPanel Padding="24" Spacing="16">
        <TextBlock Text="Confirm Action" FontSize="20" FontWeight="SemiBold" />
        <TextBlock Text="Are you sure you want to proceed?" TextWrapping="Wrap" />
        
        <StackPanel Orientation="Horizontal" Spacing="8" HorizontalAlignment="Right">
            <controls:DaisyButton 
                Content="Cancel" 
                Variant="Ghost" 
                Click="CancelAction" />
            <controls:DaisyButton 
                Content="Confirm" 
                Variant="Primary" 
                Click="ConfirmAction" />
        </StackPanel>
    </StackPanel>
</controls:DaisyModal>

C# - Programmatic Modal

var modal = new DaisyModal
{
    Content = new StackPanel
    {
        Padding = new Thickness(24),
        Spacing = 16,
        Children =
        {
            new TextBlock 
            { 
                Text = "Dynamic Modal", 
                FontSize = 20, 
                FontWeight = FontWeights.SemiBold 
            },
            new TextBlock 
            { 
                Text = "This modal was created programmatically.", 
                TextWrapping = TextWrapping.Wrap 
            }
        }
    }
};

// Add to page
RootGrid.Children.Add(modal);

// Open modal
modal.IsOpen = true;

C# - Custom Derived Modal

public class CustomModal : DaisyModal
{
    protected override bool ShouldCloseOnOutsideClick()
    {
        // Prevent closing when clicking outside
        return false;
    }
    
    protected override double DialogBoundsMargin => 32; // Larger margin
    
    public CustomModal()
    {
        // Set custom size
        SetDialogSize(400, 300);
        
        // Custom corner radius
        TopLeftRadius = 24;
        TopRightRadius = 24;
        BottomLeftRadius = 8;
        BottomRightRadius = 8;
    }
}

C# - Modal with Callback

public void ShowConfirmDialog(Action onConfirm, Action onCancel)
{
    var modal = new DaisyModal();
    
    var stack = new StackPanel 
    { 
        Padding = new Thickness(24), 
        Spacing = 16 
    };
    
    stack.Children.Add(new TextBlock 
    { 
        Text = "Confirm?", 
        FontSize = 18, 
        FontWeight = FontWeights.SemiBold 
    });
    
    var buttonPanel = new StackPanel 
    { 
        Orientation = Orientation.Horizontal, 
        Spacing = 8, 
        HorizontalAlignment = HorizontalAlignment.Right 
    };
    
    var cancelBtn = new DaisyButton 
    { 
        Content = "Cancel", 
        Variant = DaisyButtonVariant.Ghost 
    };
    cancelBtn.Click += (s, e) =>
    {
        modal.IsOpen = false;
        onCancel?.Invoke();
    };
    
    var confirmBtn = new DaisyButton 
    { 
        Content = "Confirm", 
        Variant = DaisyButtonVariant.Primary 
    };
    confirmBtn.Click += (s, e) =>
    {
        modal.IsOpen = false;
        onConfirm?.Invoke();
    };
    
    buttonPanel.Children.Add(cancelBtn);
    buttonPanel.Children.Add(confirmBtn);
    stack.Children.Add(buttonPanel);
    
    modal.Content = stack;
    RootGrid.Children.Add(modal);
    modal.IsOpen = true;
}

Behavior Notes

  • ESC Key: Pressing ESC closes the modal (when IsOpen="True")
  • Click Outside: Clicking the backdrop closes the modal by default (override ShouldCloseOnOutsideClick() to change)
  • Focus: Modal automatically receives focus when opened to capture keyboard events
  • Drag Bounds: When IsDraggable="True", the dialog is constrained within the viewport with DialogBoundsMargin spacing
  • Hit Testing: When closed, the modal is not hit-testable, allowing interaction with elements behind it
  • Z-Index: Modal uses ThemeShadow with elevation (Z=32) for depth

Theming

The modal respects these theme resources:
  • DaisyModalBackdropBrush - Backdrop overlay color (default: semi-transparent black)
  • DaisyModalBackground - Dialog background color (default: Base100)
  • DaisyModalForeground - Dialog text color (default: BaseContent)
  • DaisyModalGrabBarBrush - Grab bar color (default: Base300)

Build docs developers (and LLMs) love