Tailbox CVA
High-performance, zero-allocation variant management for s&box UI, inspired by class-variance-authority (CVA).
About
Tailbox CVA is a professional-grade C# utility designed for managing component styles and variants within the s&box environment. It allows developers to define a clean design system for their components, handling different states (sizes, variants, statuses) without messy string concatenation or complex logic.
Built with a "Performance-First" mindset, Tailbox CVA is optimized for the high-frequency rendering requirements of a game engine, reaching near-theoretical limits for style resolution speeds.
Features
- Type-Safe Design System: Define your component's look and feel with clear categories and cases.
- Dynamic Bit-Packing: Compresses component states into a single
ulong hash for $O(1)$ lookups. - Thread-Static Composition: Eliminates runtime allocations by reusing thread-local buffers.
- Fluent Resolver API: Optimized
ref struct resolver for zero-allocation property assignment. - Compound Variants: Apply specific styles only when multiple conditions are met. Supports automatic boolean variant generation.
- Permutation Caching: Blazing fast result retrieval using a thread-safe
ConcurrentDictionary cache.
Usage
1. Defining a CVA
using Tailbox;
public static class ButtonStyles
{
// Implicit operator supports .Bake() automatically
public static readonly TailboxCva Styles = TailboxCva.Create("inline-flex items-center justify-center rounded-md")
.Variant("variant", v => v
.Case("default", "bg-primary text-primary-foreground", isDefault: true)
.Case("destructive", "bg-destructive text-destructive-foreground")
.Case("outline", "border border-input bg-background")
)
.Variant("size", s => s
.Case("default", "h-10 px-4", isDefault: true)
.Case("sm", "h-9 px-3")
.Case("lg", "h-11 px-8")
)
// Compounds support boolean logic and automatic variant registration
.Compound("opacity-50 grayscale", ("disabled", true));
}
2. Applying Styles
The Optimized Way (Zero-Allocation)
Using the Resolve() API is the most efficient method for hot-path rendering (UI panels).
// Returns a CvaResult (struct) - No allocation!
var result = ButtonStyles.Styles.Resolve()
.With("variant", "destructive")
.With("size", "sm")
.With("disabled", IsDisabled)
.Build("extra-margin-class");
// Use result.BaseClasses and result.ExtraClasses separately
// or call .ToString() / .Merge()
string finalClasses = result.ToString();
The Helper Way (Compatibility)
string classes = ButtonStyles.Styles.Build("extra-class", ("variant", "outline"), ("size", "lg"));
3. Setting up Automatic Merging
To enable automatic conflict resolution (requires TailboxMerge), set the MergeHandler once at app startup:
TailboxCva.MergeHandler = (baseStyles, extra) => TailboxMerge.Merge(baseStyles, extra);
Performance Note
Tailbox CVA is built for game engine hot-paths:
Zero Runtime Reflection: Completely eliminates reflection and TypeLibrary lookups in favor of pre-calculated integer IDs.
Dynamic Bit-Packing: States are packed into bits based on the number of options (e.g., 2 bits for 4 states). This allows caching thousands of permutations in a single ulong key.
ThreadStatic Buffers: Uses [ThreadStatic] to avoid GC pressure from StringBuilder or intermediate arrays.
CvaResult Struct: Returns style components as a ref struct to defer or eliminate final string concatenation.
Enum String Cache: High-performance ConcurrentDictionary for zero-allocation enum-to-string conversion.
License
Tailbox CVA is licensed under the MIT license.