https://github.com/zettersten/blazorfastaddtocart
A high-performance Blazor component for animating items into a cart with customizable easing functions
https://github.com/zettersten/blazorfastaddtocart
add-to-cart animation blazor blazor-server blazor-webassembly dotnet
Last synced: 4 months ago
JSON representation
A high-performance Blazor component for animating items into a cart with customizable easing functions
- Host: GitHub
- URL: https://github.com/zettersten/blazorfastaddtocart
- Owner: Zettersten
- Created: 2025-11-14T15:29:34.000Z (8 months ago)
- Default Branch: main
- Last Pushed: 2026-01-12T14:16:14.000Z (6 months ago)
- Last Synced: 2026-01-12T20:57:48.743Z (6 months ago)
- Topics: add-to-cart, animation, blazor, blazor-server, blazor-webassembly, dotnet
- Language: CSS
- Homepage: https://zettersten.github.io/BlazorFastAddToCart/
- Size: 8.82 MB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Blazor Fast Add To Cart
[](https://www.nuget.org/packages/BlazorFastAddToCart/)
[](https://deepwiki.com/Zettersten/BlazorFastAddToCart)
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
**[View the interactive demo](https://zettersten.github.io/BlazorFastAddToCart/)**

## โจ Features
- **High Performance**: Allocation-conscious cubic bezier easing (passes control points to JS to avoid per-click easing-string formatting and regex parsing)
- **Customizable Animations**: Independent easing functions for X, Y, and scale transformations
- **Multiple Items**: Animate multiple items with staggered timing using the `Count` parameter
- **Custom Triggers**: Specify which element triggers the animation with the `Trigger` parameter
- **Progress Tracking**: Track animation progress in real-time with `OnAnimationProgress`
- **Accessibility**: Respects `prefers-reduced-motion` and 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:
```bash
dotnet add package BlazorFastAddToCart
```
Or via Package Manager Console:
```powershell
Install-Package BlazorFastAddToCart
```
Or add directly to your `.csproj`:
```xml
```
## ๐ฏ Quick Start
### 1. Add Namespace
Add the namespace to your `_Imports.razor` file:
```razor
@using BlazorFastAddToCart
```
### 2. Basic Usage
Wrap any content you want to animate with the `AddToCart` component:
```razor

```
### 3. With Event Callback
Handle when the animation completes:
```razor
Add to Cart
@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.
```razor
```
### `Speed`
**Type**: `double`
**Default**: `0.6`
Animation duration in seconds. Lower values = faster animation.
```razor


```
**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.
```razor

```
### `EasingY`
**Type**: `CubicBezier`
**Default**: `CubicBezier.CartY`
Easing function for vertical (Y-axis) movement. Controls how the item accelerates/decelerates vertically.
```razor

```
### `EasingScale`
**Type**: `CubicBezier`
**Default**: `CubicBezier.CartScale`
Easing function for scale transformation. Controls how the item scales down during the animation.
```razor

```
### `OnBeforeAnimation`
**Type**: `EventCallback`
**Default**: `null`
Callback invoked before the animation starts. Use this to prepare data, update UI state, perform validation, or execute any logic that should happen before the animation begins. This callback fires once per click, even when `Count > 1`.
```razor

@code {
private async Task PrepareAnimation()
{
// Prepare data, update UI, or perform validation before animation starts
await ValidateItemAsync();
StateHasChanged();
}
}
```
### `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.
```razor

@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.
```razor
Add 10 Items
@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.
```razor
Product Name
Add to Cart
```
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`
**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.
```razor
Add Items
@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.
```razor
Product Name
Add to Cart
```
## ๐จ Easing Functions
The component includes a comprehensive set of predefined easing functions via the `CubicBezier` struct. The predefined `CubicBezier` values are allocation-free; `ToCssString()` allocates the returned string and is meant for display/debugging.
### Standard Easing Functions
```csharp
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
```csharp
CubicBezier.EaseInQuad
CubicBezier.EaseOutQuad
CubicBezier.EaseInOutQuad
```
### Cubic Easing
```csharp
CubicBezier.EaseInCubic
CubicBezier.EaseOutCubic
CubicBezier.EaseInOutCubic
```
### Quartic Easing
```csharp
CubicBezier.EaseInQuart
CubicBezier.EaseOutQuart
CubicBezier.EaseInOutQuart
```
### Quintic Easing
```csharp
CubicBezier.EaseInQuint
CubicBezier.EaseOutQuint
CubicBezier.EaseInOutQuint
```
### Bouncy/Elastic Easing
```csharp
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:
```csharp
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:
```razor
@code {
// Custom easing: fast start, slow end with overshoot
private CubicBezier customEasing = new CubicBezier(0.68f, -0.55f, 0.265f, 1.55f);
}

```
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
```razor
@foreach (var product in products)
{
@product.Name
$@product.Price
Add to Cart
}
@code {
private List 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
```razor

```
### Example 3: Dynamic Speed Based on Distance
```razor
@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);
}
}

```
### Example 4: Multiple Destinations
```razor
โค๏ธ
๐

@code {
private bool isWishlist = false;
private void HandleAction()
{
if (isWishlist)
AddToWishlist();
else
AddToCart();
}
}
```
### Example 5: Async Operations
```razor
Add to Cart
@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
```razor

```
### Example 7: Complex Nested Content
```razor
New
```
### Example 8: Conditional Rendering
```razor
@if (product.InStock)
{
Add to Cart
}
else
{
Out of Stock
}
```
### Example 9: Using with Forms
```razor
Add to Cart
@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
```razor
โญ
โก
```
### Example 11: Multiple Items with Count
```razor
Add 10 Items
@code {
private void HandleBulkAdd()
{
// Fires once after all 10 animations complete
cartCount += 10;
StateHasChanged();
}
}
```
### Example 12: Custom Trigger Element
```razor
Product Name
$99.99
Add to Cart
```
### Example 13: Progress Tracking
```razor
Add 5 Items
@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
```razor
@product.Name
$@product.Price
Add @quantity to Cart
@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:
```razor
@foreach (var product in products)
{
}
```
### Performance Optimization
For large product lists, consider using virtualization:
```razor
```
### CSS Styling
The component uses `display: contents` by default, so it doesn't add extra DOM elements. Style your content directly:
```css
/* 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: reduce` is 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
- **Low Allocation**: Easing control points are passed to JS (avoids per-click easing-string formatting in .NET and regex parsing in JS). `CubicBezier.ToCssString()` is intended for display/debugging and allocates the returned string.
- **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 bUnit tests covering:
- Component rendering
- Event callbacks
- JS interop initialization / invocations
Run tests locally:
```bash
dotnet test
```
## ๐ Changelog
See [CHANGELOG.md](CHANGELOG.md).
## ๐ 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 |
| `OnBeforeAnimation` | `EventCallback` | No | `null` | Callback before animation starts (fires once per click) |
| `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` | 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:**
```csharp
public CubicBezier(float x1, float y1, float x2, float y2)
```
**Methods:**
```csharp
string ToCssString() // Converts to CSS cubic-bezier() string
```
**Static Properties:** See [Easing Functions](#-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.