Skip to content
Shiny.NET

Confetti

Confetti bursts on a tap, a click or from code, in the style of Magic UI’s confetti. The physics are canvas-confetti’s (the library Magic UI wraps), copied frame for frame. The option names and defaults are the same too, so a recipe written for the web works unchanged.

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

Blazor

Stars preset Emoji (custom options)
Gold stars bursting from a ShinyButton wrapped in a Confetti component Unicorn and party-popper emoji confetti from custom ConfettiOptions
Fireworks from the service Side cannons from the service
The Fireworks preset fired from IConfettiService, scattered across the page The Side cannons preset streaming in from both edges of the page

MAUI (iOS)

Emoji (custom options) Fireworks Side cannons
Emoji confetti bursting from a button on .NET MAUI The Fireworks preset over the page on .NET MAUI The Side cannons preset filling the page on .NET MAUI

Attach it to any view. You don’t need to write any code.

<Button Text="Ship it" shiny:Confetti.Trigger="Tap" />
<shiny:ShinyButton Text="Stars" shiny:Confetti.Trigger="Tap" shiny:Confetti.Preset="Stars" />
<Border shiny:Confetti.Trigger="DoubleTap">...</Border>
Attached property Default Description
Confetti.Trigger None Tap or DoubleTap. None removes the hook
Confetti.Preset Burst The preset to fire
Confetti.Options null A custom ConfettiOptions. Takes priority over Preset, and its origin is replaced by the tap point

Button, ImageButton, ShinyButton and Fab are hooked through Clicked, because MAUI’s own buttons ignore gesture recognizers. They burst from their centre. Any other view gets a tap recognizer and bursts from the point you touched. Either way, the view’s own click and command still run.

Wrap the element. The wrapper is display: contents, so the layout doesn’t change.

<Confetti Preset="ConfettiPreset.Stars">
<ShinyButton Text="Ship it" />
</Confetti>
<Confetti Trigger="ConfettiTrigger.DoubleTap" Options="@unicorns">
<div class="card">...</div>
</Confetti>
@code {
readonly ConfettiOptions unicorns = new() { Emoji = ["🦄", "🎉"], Scalar = 2, ParticleCount = 30 };
}

The click is handled in JavaScript, so the burst starts on the same frame as the click. On Blazor Server, nothing waits on the network first. A click from the keyboard bursts from the centre of the element.

IConfettiService is registered by UseShinyControls() on MAUI, and by AddShinyControls() or AddShinyConfetti() on Blazor, where it is scoped. It needs no host component. Every call completes once the last particle has faded.

await confetti.FireAsync(ConfettiPreset.Fireworks);
await confetti.FireAsync(ConfettiPreset.Burst, new Point(0.5, 0.3)); // Blazor: FireAsync(preset, 0.5, 0.3)
await confetti.FireFromAsync(saveButton, ConfettiPreset.Stars); // VisualElement / ElementReference
await confetti.FireAsync(new ConfettiOptions { ParticleCount = 150, Spread = 180 });
confetti.Clear(); // Blazor: await ClearAsync()
Preset Description
Burst 100 particles with a 70° spread, from the origin
Random A random angle, spread and count, so no two taps look the same
Fireworks 5 seconds of 360° bursts at random points near the top. Ignores the origin
SideCannons 3 seconds of streams from both side edges. Ignores the origin
Stars Three waves of gold stars and sparks, with no gravity
Property Default Description
ParticleCount 50 Particles to launch
Angle 90 Launch direction in degrees (90 is up)
Spread 45 Total deviation around Angle
StartVelocity 45 Launch speed per frame
Decay 0.9 Share of its speed a particle keeps each frame
Gravity 1 0 floats
Drift 0 Sideways drift
Flat false Stops particles tumbling
Ticks 200 Frames a particle lives, fading as it goes
OriginX / OriginY 0.5 / 0.5 Launch point as a fraction of the page (MAUI) or window (Blazor)
Colors 7-color palette Color on MAUI, CSS strings on Blazor
Shapes Square, Circle Square, Circle, Star
Emoji empty Text to throw. When it has anything in it, Shapes and Colors are ignored
Scalar 1 Size multiplier
DisableForReducedMotion false Skips the burst when the OS or browser asks for reduced motion