Skip to content
Shiny.Maui.Shell v6 support for AI routing tools Learn More

SignaturePad

A signature capture control that opens in a FloatingPanel overlay (MAUI) or SheetView (Blazor). Users draw on a canvas and tap Sign to export the signature as a PNG image. The Sign button is disabled until the user actually draws something. A Clear button lets users erase and start over.

  • NuGet downloads for Shiny.Maui.Controls
  • NuGet downloads for Shiny.Blazor.Controls
Frameworks
.NET MAUI
Blazor

SignaturePad uses a FloatingPanel internally, so it must be placed inside an OverlayHost or ShinyContentPage.Panels — just like a standalone FloatingPanel. Placing it outside an overlay host will not display correctly.

<shiny:ShinyContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:shiny="http://shiny.net/maui/controls"
x:Class="MyApp.SignaturePage">
<shiny:ShinyContentPage.PageContent>
<VerticalStackLayout Padding="20" Spacing="10">
<Button Text="Capture Signature" Command="{Binding OpenSignatureCommand}" />
<Border StrokeShape="RoundRectangle 12"
Stroke="LightGray"
StrokeThickness="1"
Padding="10"
IsVisible="{Binding HasSignature}">
<Image Source="{Binding SignatureImage}"
HeightRequest="150"
Aspect="AspectFit" />
</Border>
</VerticalStackLayout>
</shiny:ShinyContentPage.PageContent>
<shiny:ShinyContentPage.Panels>
<shiny:SignaturePad IsOpen="{Binding IsSignatureOpen}"
StrokeColor="Black"
SignatureBackgroundColor="#F8F8F8"
StrokeWidth="3"
SignButtonColor="#6C63FF"
CancelButtonColor="#94A3B8"
SignCommand="{Binding HandleSignedCommand}"
CancelCommand="{Binding HandleCancelledCommand}" />
</shiny:ShinyContentPage.Panels>
</shiny:ShinyContentPage>
<ContentPage>
<Grid>
<ScrollView>
<VerticalStackLayout Padding="20" Spacing="10">
<Button Text="Capture Signature" Command="{Binding OpenSignatureCommand}" />
</VerticalStackLayout>
</ScrollView>
<shiny:OverlayHost>
<shiny:SignaturePad IsOpen="{Binding IsSignatureOpen}"
StrokeColor="Black"
SignCommand="{Binding HandleSignedCommand}" />
</shiny:OverlayHost>
</Grid>
</ContentPage>
PropertyTypeDefaultDescription
IsOpenboolfalseOpens/closes the signature panel (TwoWay)
PositionFloatingPanelPositionBottomPanel slide direction (Bottom, BottomTabs, Top)
IsLockedbooltruePrevents drag dismiss of the panel
DetentDetentValueHalfPanel snap position
StrokeColorColorBlackDrawing stroke color
SignatureBackgroundColorColorWhiteCanvas background color
StrokeWidthdouble3.0Drawing stroke width
SignButtonTextstring"Sign"Sign button label
CancelButtonTextstring"Cancel"Cancel button label
SignButtonColorColorBlueSign button background color
CancelButtonColorColorGrayCancel button background color
ShowCancelButtonbooltrueShow/hide the cancel button
PanelBackgroundColorColorWhitePanel background color
PanelCornerRadiusdouble16Panel corner radius
HasBackdropbooltrueShow backdrop behind the panel
ExportWidthint600Exported PNG width in pixels
ExportHeightint200Exported PNG height in pixels
SignCommandICommand?nullCommand invoked on sign with SignatureImageEventArgs
CancelCommandICommand?nullCommand invoked on cancel
EventArgsDescription
SignedSignatureImageEventArgsFires when the user taps Sign; ImageStream contains the PNG
CancelledEventArgsFires when the user taps Cancel
PropertyTypeDescription
ImageStreamStreamPNG image stream of the captured signature
public partial class SignatureViewModel : ObservableObject
{
[ObservableProperty]
bool isSignatureOpen;
[ObservableProperty]
ImageSource? signatureImage;
public bool HasSignature => SignatureImage != null;
[RelayCommand]
void OpenSignature() => IsSignatureOpen = true;
[RelayCommand]
void HandleSigned(SignatureImageEventArgs args)
{
var ms = new MemoryStream();
args.ImageStream.CopyTo(ms);
ms.Position = 0;
SignatureImage = ImageSource.FromStream(() => ms);
OnPropertyChanged(nameof(HasSignature));
}
[RelayCommand]
void HandleCancelled() { }
[RelayCommand]
void ClearSignature()
{
SignatureImage = null;
OnPropertyChanged(nameof(HasSignature));
}
}
<button @onclick="() => isOpen = true">Capture Signature</button>
@if (signatureDataUrl != null)
{
<img src="@signatureDataUrl" alt="Captured signature"
style="max-width:100%;border:1px solid #E5E7EB;border-radius:8px;" />
<button style="background:#EF4444;color:white;" @onclick="ClearSignature">Clear</button>
}
<SignaturePad @bind-IsOpen="isOpen"
StrokeColor="#000000"
SignatureBackgroundColor="#F8F8F8"
StrokeWidth="3"
SignButtonColor="#6C63FF"
CancelButtonColor="#94A3B8"
Signed="OnSigned"
Cancelled="OnCancelled" />
@code {
bool isOpen;
string? signatureDataUrl;
void OnSigned(byte[] pngBytes)
{
var base64 = Convert.ToBase64String(pngBytes);
signatureDataUrl = $"data:image/png;base64,{base64}";
}
void OnCancelled() { }
void ClearSignature() => signatureDataUrl = null;
}
ParameterTypeDefaultDescription
IsOpenboolfalseOpens/closes the sheet (two-way via @bind-IsOpen)
DirectionSheetDirectionBottomSheet slide direction
IsLockedbooltruePrevents drag dismiss
DetentDetentValueHalfSheet snap position
StrokeColorstring"#000000"CSS stroke color
SignatureBackgroundColorstring"#FFFFFF"CSS canvas background
StrokeWidthdouble3Stroke width
SignButtonTextstring"Sign"Sign button label
CancelButtonTextstring"Cancel"Cancel button label
SignButtonColorstring"#6C63FF"CSS sign button color
CancelButtonColorstring"#94A3B8"CSS cancel button color
ShowCancelButtonbooltrueShow/hide cancel button
PanelBackgroundColorstring"#FFFFFF"CSS panel background
PanelCornerRadiusdouble16Panel corner radius
HasBackdropbooltrueShow backdrop
ExportWidthint600Exported PNG width
ExportHeightint200Exported PNG height
EventTypeDescription
SignedEventCallback<byte[]>Fires with raw PNG bytes when the user signs
CancelledEventCallbackFires when the user cancels
  • Canvas drawing — Touch/pointer-based freehand drawing on a canvas surface
  • Sign button gating — The Sign button is disabled until the user draws something
  • Clear button — Erase the canvas and start over without closing the panel
  • PNG export — Signature is exported as a PNG image at configurable resolution (ExportWidth x ExportHeight)
  • FloatingPanel integration — Opens as a bottom/top panel overlay with configurable detent, backdrop, and corner radius
  • Auto-reset — Canvas resets automatically after signing or cancelling
  • Auto-close — Panel closes automatically after sign or cancel
  • Customizable buttons — Configure text, colors, and visibility of the Sign and Cancel buttons
claude plugin marketplace add shinyorg/skills
claude plugin install shiny-controls@shiny
copilot plugin marketplace add https://github.com/shinyorg/skills
copilot plugin install shiny-controls@shiny
View shiny-controls Plugin