BlazorFastAddToCart 1.0.2
See the version list below for details.
dotnet add package BlazorFastAddToCart --version 1.0.2
NuGet\Install-Package BlazorFastAddToCart -Version 1.0.2
<PackageReference Include="BlazorFastAddToCart" Version="1.0.2" />
<PackageVersion Include="BlazorFastAddToCart" Version="1.0.2" />
<PackageReference Include="BlazorFastAddToCart" />
paket add BlazorFastAddToCart --version 1.0.2
#r "nuget: BlazorFastAddToCart, 1.0.2"
#:package BlazorFastAddToCart@1.0.2
#addin nuget:?package=BlazorFastAddToCart&version=1.0.2
#tool nuget:?package=BlazorFastAddToCart&version=1.0.2
Blazor Fast Add To Cart
A high-performance Blazor component that animates items flying into a shopping cart (or any destination) with customizable easing functions. Optimized for AOT compilation, trimming-friendly, and designed for both Blazor Server and WebAssembly hosting models.
๐ Live Demo
โจ Features
- High Performance: Zero-allocation cubic bezier easing, optimized for AOT compilation
- Customizable Animations: Independent easing functions for X, Y, and scale transformations
- Multiple Items: Animate multiple items with staggered timing using the
Countparameter - Custom Triggers: Specify which element triggers the animation with the
Triggerparameter - Progress Tracking: Track animation progress in real-time with
OnAnimationProgress - Accessibility: Respects
prefers-reduced-motionand provides fallback feedback - Concurrent Animations: Supports multiple simultaneous animations without conflicts
- Flexible Content: Works with images, buttons, divs, or any HTML content
- Blazor Server & WASM: Compatible with both hosting models
- Trimming-Friendly: Fully compatible with .NET trimming and AOT compilation
- Type-Safe: Strongly-typed easing functions with compile-time constants
๐ฆ Installation
Install the package via NuGet Package Manager:
dotnet add package BlazorFastAddToCart
Or via Package Manager Console:
Install-Package BlazorFastAddToCart
Or add directly to your .csproj:
<PackageReference Include="BlazorFastAddToCart" Version="1.0.0" />
๐ฏ Quick Start
1. Add Namespace
Add the namespace to your _Imports.razor file:
@using BlazorFastAddToCart
2. Basic Usage
Wrap any content you want to animate with the AddToCart component:
<div id="cart" class="cart-icon">๐</div>
<AddToCart Destination="#cart">
<img src="product.jpg" alt="Product" />
</AddToCart>
3. With Event Callback
Handle when the animation completes:
<AddToCart Destination="#cart" OnAnimationComplete="HandleAddToCart">
<button class="btn btn-primary">Add to Cart</button>
</AddToCart>
@code {
private void HandleAddToCart()
{
// Update cart count, make API call, etc.
cartCount++;
}
}
๐ Component Parameters
Destination (Required)
Type: string
Default: None (required)
CSS selector for the destination element where the animation should end. Can be an ID selector (#cart), class selector (.cart-icon), or any valid CSS selector.
<AddToCart Destination="#shopping-cart">
</AddToCart>
Speed
Type: double
Default: 0.6
Animation duration in seconds. Lower values = faster animation.
<AddToCart Destination="#cart" Speed="0.5">
<img src="product.jpg" />
</AddToCart>
<AddToCart Destination="#cart" Speed="2.0">
<img src="product.jpg" />
</AddToCart>
Note: The default value of 0.6 seconds provides a smooth, fast animation. For typical e-commerce use cases, values between 0.5 and 1.5 seconds work best.
EasingX
Type: CubicBezier
Default: CubicBezier.CartX
Easing function for horizontal (X-axis) movement. Controls how the item accelerates/decelerates horizontally.
<AddToCart Destination="#cart" EasingX="@CubicBezier.EaseOut">
<img src="product.jpg" />
</AddToCart>
EasingY
Type: CubicBezier
Default: CubicBezier.CartY
Easing function for vertical (Y-axis) movement. Controls how the item accelerates/decelerates vertically.
<AddToCart Destination="#cart" EasingY="@CubicBezier.EaseInOut">
<img src="product.jpg" />
</AddToCart>
EasingScale
Type: CubicBezier
Default: CubicBezier.CartScale
Easing function for scale transformation. Controls how the item scales down during the animation.
<AddToCart Destination="#cart" EasingScale="@CubicBezier.EaseIn">
<img src="product.jpg" />
</AddToCart>
OnAnimationComplete
Type: EventCallback
Default: null
Callback invoked when the animation completes. Use this to update cart counts, make API calls, or perform other actions. When using Count > 1, this callback fires only once after all animations complete.
<AddToCart Destination="#cart" OnAnimationComplete="HandleAddToCart">
<img src="product.jpg" />
</AddToCart>
@code {
private async Task HandleAddToCart()
{
cartCount++;
await AddItemToCartAsync(productId);
StateHasChanged();
}
}
Count
Type: int
Default: 1
Number of items to animate. When set to a value greater than 1, multiple animations will be triggered with staggered timing. All animations complete before OnAnimationComplete fires once.
<AddToCart Destination="#cart" Count="10" OnAnimationComplete="HandleBulkAdd">
<button>Add 10 Items</button>
</AddToCart>
@code {
private void HandleBulkAdd()
{
// This fires once after all 10 animations complete
cartCount += 10;
}
}
Trigger
Type: string?
Default: null
CSS selector for the specific element that should trigger the animation. When provided, only clicks on the matching element will trigger the animation. Useful when you want to animate a specific part of your content (like a button) rather than the entire wrapped content.
<AddToCart Destination="#cart" Trigger=".add-to-cart-btn">
<div class="product-card">
<img src="product.jpg" />
<h3>Product Name</h3>
<button class="add-to-cart-btn">Add to Cart</button>
</div>
</AddToCart>
The selector can be:
- A class selector:
".add-to-cart-btn" - An ID selector:
"#product-button" - Any valid CSS selector:
"button[type='submit']"
If null, the entire wrapped content acts as the trigger.
OnAnimationProgress
Type: EventCallback<double>
Default: null
Callback invoked during animation to report progress. Progress ranges from 0.0 (start) to 1.0 (complete). Updates are throttled to reduce callback frequency. When using Count > 1, progress represents the overall progress across all animations.
<AddToCart Destination="#cart"
Count="5"
OnAnimationProgress="HandleProgress"
OnAnimationComplete="HandleComplete">
<button>Add Items</button>
</AddToCart>
@code {
private double progress = 0.0;
private void HandleProgress(double progressValue)
{
progress = progressValue; // 0.0 to 1.0
StateHasChanged();
}
private void HandleComplete()
{
progress = 0.0; // Reset for next animation
}
}
ChildContent
Type: RenderFragment
Default: null
The content to wrap and animate. Can be any HTML element, image, button, or complex markup.
<AddToCart Destination="#cart">
<div class="product-card">
<img src="product.jpg" />
<h3>Product Name</h3>
<button>Add to Cart</button>
</div>
</AddToCart>
๐จ Easing Functions
The component includes a comprehensive set of predefined easing functions via the CubicBezier struct. All easing functions are compile-time constants with zero allocations.
Standard Easing Functions
CubicBezier.Linear // Linear interpolation (no easing)
CubicBezier.Ease // Default easing (slow start, fast middle, slow end)
CubicBezier.EaseIn // Slow start
CubicBezier.EaseOut // Slow end
CubicBezier.EaseInOut // Slow start and end
Quadratic Easing
CubicBezier.EaseInQuad
CubicBezier.EaseOutQuad
CubicBezier.EaseInOutQuad
Cubic Easing
CubicBezier.EaseInCubic
CubicBezier.EaseOutCubic
CubicBezier.EaseInOutCubic
Quartic Easing
CubicBezier.EaseInQuart
CubicBezier.EaseOutQuart
CubicBezier.EaseInOutQuart
Quintic Easing
CubicBezier.EaseInQuint
CubicBezier.EaseOutQuint
CubicBezier.EaseInOutQuint
Bouncy/Elastic Easing
CubicBezier.EaseInBack // Bounces backward at start
CubicBezier.EaseOutBack // Bounces forward at end
CubicBezier.EaseInOutBack // Bounces at both ends
Custom Cart Easing (Default)
These are optimized specifically for shopping cart animations:
CubicBezier.CartX // Default X-axis easing (slight overshoot)
CubicBezier.CartY // Default Y-axis easing (bouncy arc)
CubicBezier.CartScale // Default scale easing (smooth shrink)
Creating Custom Easing Functions
You can create custom easing functions by instantiating CubicBezier with your own control points:
@code {
// Custom easing: fast start, slow end with overshoot
private CubicBezier customEasing = new CubicBezier(0.68f, -0.55f, 0.265f, 1.55f);
}
<AddToCart Destination="#cart" EasingX="@customEasing">
<img src="product.jpg" />
</AddToCart>
The CubicBezier constructor takes four float parameters: (x1, y1, x2, y2) representing the control points of the cubic bezier curve. Values typically range from 0 to 1, but can exceed 1 for overshoot effects.
๐ก Usage Examples
Example 1: Simple Product Card
<div class="product-grid">
@foreach (var product in products)
{
<div class="product-card">
<AddToCart Destination="#cart" OnAnimationComplete="() => AddToCart(product.Id)">
<div class="product-image">
<img src="@product.ImageUrl" alt="@product.Name" />
</div>
<div class="product-info">
<h3>@product.Name</h3>
<p class="price">$@product.Price</p>
<button class="btn-add-to-cart">Add to Cart</button>
</div>
</AddToCart>
</div>
}
</div>
@code {
private List<Product> products = new();
private int cartCount = 0;
private void AddToCart(int productId)
{
cartCount++;
// Add product to cart via API, etc.
}
}
Example 2: Custom Speed and Easing
<AddToCart
Destination="#cart"
Speed="0.8"
EasingX="@CubicBezier.EaseOutBack"
EasingY="@CubicBezier.EaseInOut"
EasingScale="@CubicBezier.EaseIn"
OnAnimationComplete="HandleAddToCart">
<img src="product.jpg" alt="Product" />
</AddToCart>
Example 3: Dynamic Speed Based on Distance
@code {
private double CalculateSpeed(Product product)
{
// Calculate speed based on product position or other factors
var baseSpeed = 0.6;
var distanceFactor = CalculateDistanceToCart(product);
return baseSpeed + (distanceFactor * 0.1);
}
}
<AddToCart Destination="#cart" Speed="@CalculateSpeed(product)">
<img src="@product.ImageUrl" />
</AddToCart>
Example 4: Multiple Destinations
<div id="wishlist">โค๏ธ</div>
<div id="cart">๐</div>
<AddToCart Destination="@(isWishlist ? "#wishlist" : "#cart")"
OnAnimationComplete="HandleAction">
<img src="product.jpg" />
</AddToCart>
@code {
private bool isWishlist = false;
private void HandleAction()
{
if (isWishlist)
AddToWishlist();
else
AddToCart();
}
}
Example 5: Async Operations
<AddToCart Destination="#cart" OnAnimationComplete="HandleAddToCartAsync">
<button class="btn-primary">Add to Cart</button>
</AddToCart>
@code {
private async Task HandleAddToCartAsync()
{
try
{
await cartService.AddItemAsync(productId);
cartCount = await cartService.GetItemCountAsync();
StateHasChanged();
// Show success notification
toastService.ShowSuccess("Item added to cart!");
}
catch (Exception ex)
{
toastService.ShowError("Failed to add item to cart.");
}
}
}
Example 6: Image-Only Animation
<AddToCart Destination="#cart">
<img src="product.jpg" alt="Product" class="product-thumbnail" />
</AddToCart>
Example 7: Complex Nested Content
<AddToCart Destination="#cart" OnAnimationComplete="UpdateCart">
<div class="product-card">
<div class="product-badge">New</div>
<img src="product.jpg" alt="Product" />
<div class="product-overlay">
<h3>Product Name</h3>
<p>$99.99</p>
</div>
</div>
</AddToCart>
Example 8: Conditional Rendering
@if (product.InStock)
{
<AddToCart Destination="#cart" OnAnimationComplete="AddToCart">
<button class="btn-add-to-cart">Add to Cart</button>
</AddToCart>
}
else
{
<button class="btn-disabled" disabled>Out of Stock</button>
}
Example 9: Using with Forms
<EditForm Model="@product" OnValidSubmit="HandleSubmit">
<DataAnnotationsValidator />
<InputNumber @bind-Value="product.Quantity" />
<AddToCart Destination="#cart" OnAnimationComplete="SubmitForm">
<button type="submit" class="btn-primary">Add to Cart</button>
</AddToCart>
</EditForm>
@code {
private Product product = new();
private void SubmitForm()
{
// Form validation happens before animation
// This callback fires after animation completes
}
}
Example 10: Creative Non-Ecommerce Uses
<AddToCart Destination="#star-collection" OnAnimationComplete="CollectStar">
<div class="star">โญ</div>
</AddToCart>
<AddToCart Destination="#inbox" OnAnimationComplete="SendMessage">
<div class="message-bubble">Hello!</div>
</AddToCart>
<AddToCart Destination="#battery" OnAnimationComplete="TransferEnergy">
<div class="energy-source">โก</div>
</AddToCart>
Example 11: Multiple Items with Count
<AddToCart Destination="#cart" Count="10" OnAnimationComplete="HandleBulkAdd">
<button class="btn-primary">Add 10 Items</button>
</AddToCart>
@code {
private void HandleBulkAdd()
{
// Fires once after all 10 animations complete
cartCount += 10;
StateHasChanged();
}
}
Example 12: Custom Trigger Element
<AddToCart Destination="#cart" Trigger=".add-to-cart-btn">
<div class="product-card">
<img src="product.jpg" />
<h3>Product Name</h3>
<p>$99.99</p>
<button class="add-to-cart-btn">Add to Cart</button>
</div>
</AddToCart>
Example 13: Progress Tracking
<AddToCart Destination="#cart"
Count="5"
OnAnimationProgress="UpdateProgress"
OnAnimationComplete="HandleComplete">
<button>Add 5 Items</button>
</AddToCart>
<div class="progress-bar">
<div class="progress-fill" style="width: @($"{progress * 100}%")"></div>
</div>
@code {
private double progress = 0.0;
private void UpdateProgress(double progressValue)
{
progress = progressValue; // 0.0 to 1.0
StateHasChanged();
}
private void HandleComplete()
{
progress = 0.0;
StateHasChanged();
}
}
Example 14: Combining All Features
<AddToCart Destination="#cart"
Count="@quantity"
Trigger=".add-to-cart-btn"
Speed="0.8"
OnAnimationProgress="HandleProgress"
OnAnimationComplete="HandleComplete">
<div class="product-card">
<img src="@product.ImageUrl" />
<h3>@product.Name</h3>
<p>$@product.Price</p>
<button class="add-to-cart-btn">Add @quantity to Cart</button>
</div>
</AddToCart>
@code {
private int quantity = 5;
private double progress = 0.0;
private void HandleProgress(double p) => progress = p;
private async Task HandleComplete()
{
await cartService.AddItemsAsync(productId, quantity);
progress = 0.0;
StateHasChanged();
}
}
๐ฏ Advanced Usage
Handling Multiple Rapid Clicks
The component supports concurrent animations, so users can rapidly click multiple items without issues:
@foreach (var product in products)
{
<AddToCart Destination="#cart" OnAnimationComplete="() => AddToCart(product.Id)">
<img src="@product.ImageUrl" />
</AddToCart>
}
Performance Optimization
For large product lists, consider using virtualization:
<Virtualize Items="@products" Context="product">
<AddToCart Destination="#cart" OnAnimationComplete="() => AddToCart(product.Id)">
<div class="product-card">
<img src="@product.ImageUrl" />
</div>
</AddToCart>
</Virtualize>
CSS Styling
The component uses display: contents by default, so it doesn't add extra DOM elements. Style your content directly:
/* Style the content inside AddToCart */
.product-card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 1rem;
transition: transform 0.2s;
}
.product-card:hover {
transform: scale(1.05);
}
.product-card img {
width: 100%;
height: auto;
border-radius: 4px;
}
โฟ Accessibility
The component automatically respects user preferences:
- Reduced Motion: If
prefers-reduced-motion: reduceis detected, animations are skipped and a visual feedback (ping effect) is shown instead - High Contrast: Supports high contrast mode with appropriate outlines
- Dark Mode: Optimized for dark color schemes
- Print Styles: Animations are hidden when printing
No additional configuration needed - these features work automatically!
๐ง Browser Compatibility
- Chrome/Edge (latest)
- Firefox (latest)
- Safari (latest)
- All modern browsers with CSS transform and requestAnimationFrame support
โก Performance Considerations
- Zero Allocations: Easing functions use stack allocation for string formatting
- Concurrent Animations: Multiple animations can run simultaneously without performance degradation
- GPU Acceleration: Uses CSS transforms for hardware-accelerated animations
- AOT Compatible: Fully compatible with .NET AOT compilation
- Trimming-Friendly: No reflection or dynamic code generation
๐งช Testing
The solution includes comprehensive BUnit tests covering:
- Component rendering
- Lifecycle methods
- Event callbacks
- Parameter forwarding
- Animation completion
Run tests locally:
dotnet test
๐ API Reference
AddToCart Component
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
Destination |
string |
Yes | - | CSS selector for animation destination |
Speed |
double |
No | 0.6 |
Animation duration in seconds |
EasingX |
CubicBezier |
No | CubicBezier.CartX |
Horizontal movement easing |
EasingY |
CubicBezier |
No | CubicBezier.CartY |
Vertical movement easing |
EasingScale |
CubicBezier |
No | CubicBezier.CartScale |
Scale transformation easing |
OnAnimationComplete |
EventCallback |
No | null |
Callback when animation completes (fires once for multiple animations) |
Count |
int |
No | 1 |
Number of items to animate with staggered timing |
Trigger |
string? |
No | null |
CSS selector for specific trigger element |
OnAnimationProgress |
EventCallback<double> |
No | null |
Callback for progress updates (0.0 to 1.0) |
ChildContent |
RenderFragment |
No | null |
Content to animate |
CubicBezier Struct
Represents a cubic bezier easing function with compile-time constants.
Constructor:
public CubicBezier(float x1, float y1, float x2, float y2)
Methods:
string ToCssString() // Converts to CSS cubic-bezier() string
Static Properties: See Easing Functions section above.
๐ค Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
๐ License
MIT License - see LICENSE file for details.
๐ Acknowledgments
Inspired by modern e-commerce animations and optimized for Blazor applications.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.AspNetCore.Components.Web (>= 10.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
See https://github.com/Zettersten/BlazorFastAddToCart/releases for release notes.