@loyalteez/react-components
v0.6.0
Published
React components for building loyalty program interfaces with Loyalteez
Maintainers
Readme
@loyalteez/react-components
React components for building loyalty program interfaces with Loyalteez
Overview
@loyalteez/react-components provides drop-in React components for building loyalty program interfaces. Launch polished loyalty experiences in hours instead of weeks.
Features
- 🎮 Game-like effects — Glows, shimmers, particles, shakes, dramatic reveals
- 🎨 Beautiful defaults — Dark theme with customizable CSS variables
- 🎭 Tone system — 10 theme presets (arcade, casino, cyberpunk, fantasy...)
- 🧩 Composable — Use individual components or compose your own
- 🪝 Headless hooks — Full control when you need custom UI
- ⚡ Lightweight — Tree-shakeable, minimal dependencies
- 📱 Responsive — Mobile-first design
- ♿ Accessible — WCAG 2.1 AA compliant
- 🔥 Gamification — Streaks, leaderboards, challenges, confetti!
Installation
npm install @loyalteez/react-components
# or
pnpm add @loyalteez/react-components
# or
yarn add @loyalteez/react-componentsQuick Start
import {
BalanceDisplay,
TierBadge,
StreakCounter,
ToastProvider,
useToast
} from '@loyalteez/react-components';
import '@loyalteez/react-components/styles.css';
function App() {
return (
<ToastProvider>
<MyLoyaltyWidget />
</ToastProvider>
);
}
function MyLoyaltyWidget() {
const { reward } = useToast();
return (
<div className="flex gap-4">
<TierBadge tier="gold" />
<BalanceDisplay balance={5420} showDollarValue animated />
<StreakCounter streak={7} />
<button onClick={() => reward({ amount: 100 })}>
Earn Rewards!
</button>
</div>
);
}Components
Core Display
| Component | Description |
|-----------|-------------|
| BalanceDisplay | Display LTZ balance with animated counter and dollar value |
| ProgressBar | Generic progress indicator with gradient/glow variants |
| TierBadge | Bronze/Silver/Gold/Platinum/Diamond tier badges with glow effects |
| Badge | Pre-styled badges: Featured, Sponsored, Premium, SoldOut, etc. |
Perk Marketplace
| Component | Description |
|-----------|-------------|
| PerkCard | Full perk card with image, badges, supply, price, actions |
| PerkCard.Root | Composable root for custom layouts |
| PerkCard.Image | Perk image with overlay badges |
| PerkCard.Content | Content container |
| PerkCard.Title | Perk title |
| PerkCard.Brand | Brand name and logo |
| PerkCard.Supply | Supply progress indicator |
| PerkCard.Price | LTZ price display |
| PerkCard.Actions | Claim/purchase buttons |
| SupplyProgress | Supply bar with urgency indicators |
Gamification
| Component | Description |
|-----------|-------------|
| StreakCounter | Daily/weekly streak with animated flame, milestones |
| Leaderboard | Top earners with medals, rank changes, current user highlight |
| ChallengeCard | Active challenges with timer, progress, rewards |
Interactive
| Component | Description |
|-----------|-------------|
| ToastProvider | Toast notification system context |
| useToast | Hook for showing reward/success/error toasts |
| ClaimModal | Transaction flow modal (idle→processing→success/error) |
| ConfettiExplosion | Canvas-based confetti celebration |
| useConfetti | Hook for imperative confetti control |
Layout & Utility
| Component | Description |
|-----------|-------------|
| EmptyState | Flexible empty state with presets (noPerks, noFavorites, etc.) |
| Skeleton | Loading skeletons for cards, lists, balance displays |
| Tooltip | Smart-positioned tooltips with arrow |
| FilterBar | Filter dropdowns, search, sort, view toggle |
Effects Module 🎮
| Effect | Description |
|--------|-------------|
| GlowEffect | Pulsing, breathing, heartbeat, flicker, rainbow glows |
| ShimmerEffect | Metallic, holographic, gold, frost, fire, neon, diamond shimmers |
| ParticleEffect | Coins, stars, embers, sparkles, confetti, snow, hearts |
| ShakeEffect | Horizontal, vertical, rotational, impact, vibrate, earthquake |
| CountEffect | Simple, slot machine, flip, cascade, scramble, typewriter |
| ToneProvider | Theme system with 10 presets (arcade, casino, cyberpunk, etc.) |
Examples
Streak Counter with Flame Animation
<StreakCounter
streak={14}
bestStreak={21}
showFlame
showMilestones
breakWarning={{ hoursRemaining: 4, show: true }}
/>Leaderboard with Medals
<Leaderboard
entries={leaderboardData}
currentUserId="user123"
showMedals
showRankChange
showAvatars
/>Challenge Card with Timer
<ChallengeCard
challenge={{
id: '1',
title: 'Daily Login',
description: 'Log in 7 days in a row',
progress: 5,
goal: 7,
status: 'active',
difficulty: 'medium',
reward: { amount: 500 },
endTime: '2024-12-31T23:59:59Z'
}}
onClaim={handleClaim}
/>Toast Notifications
function RewardButton() {
const { reward, success, error } = useToast();
const handleClaim = async () => {
try {
await claimReward();
reward({ amount: 500, description: 'Daily bonus claimed!' });
} catch (e) {
error({ title: 'Claim failed', description: e.message });
}
};
return <button onClick={handleClaim}>Claim</button>;
}Claim Modal with Transaction Flow
<ClaimModal
isOpen={isOpen}
onClose={() => setIsOpen(false)}
item={{ id: '1', title: 'Coffee Reward', cost: 500 }}
state={claimState} // 'idle' | 'confirming' | 'processing' | 'success' | 'error'
userBalance={1000}
onConfirm={handleClaim}
transactionHash={txHash}
explorerUrlTemplate="https://explorer.soneium.org/tx/{hash}"
/>Confetti Celebration
function Celebration() {
const { fire, props } = useConfetti();
return (
<>
<button onClick={() => fire()}>🎉 Celebrate!</button>
<ConfettiExplosion {...props} />
</>
);
}Composable PerkCard
<PerkCard.Root perk={perkData} variant="featured">
<PerkCard.Image />
<PerkCard.Content>
<PerkCard.Badges />
<PerkCard.Brand />
<PerkCard.Title />
<PerkCard.Tags />
<PerkCard.Supply />
<div className="flex justify-between items-center">
<PerkCard.Price />
<CustomClaimButton />
</div>
</PerkCard.Content>
</PerkCard.Root>Theming
CSS Variables
:root {
/* Brand Colors */
--ltz-cyan: 0 224 255;
--ltz-purple: 108 51 234;
--ltz-pink: 255 63 164;
--ltz-green: 166 255 0;
/* Backgrounds */
--ltz-bg-primary: 10 12 28;
--ltz-bg-secondary: 26 29 46;
/* Text */
--ltz-text-primary: 255 255 255;
--ltz-text-secondary: 140 140 153;
/* Radius */
--ltz-radius: 0.75rem;
}Tailwind CSS
// tailwind.config.js
import { loyalteezPreset } from '@loyalteez/react-components/tailwind';
export default {
presets: [loyalteezPreset],
// ...
};Framer Motion (Optional)
For enhanced animations, import from /motion:
import {
BalanceDisplayMotion,
StreakCounterMotion,
LeaderboardMotion,
ChallengeCardMotion,
AnimatedList,
AnimatedItem
} from '@loyalteez/react-components/motion';
// Physics-based balance counter
<BalanceDisplayMotion balance={5420} showDollarValue />
// Animated flame with intensity levels
<StreakCounterMotion streak={14} showFlame />
// Staggered entry animations for leaderboards
<LeaderboardMotion entries={data} currentUserId="user123" />
// Animated progress bars and timers
<ChallengeCardMotion challenge={challengeData} onClaim={handleClaim} />
// Stagger animate any list
<AnimatedList preset="spring" staggerDelay={0.1}>
{items.map(item => <Card key={item.id} />)}
</AnimatedList>Motion Components
| Component | Features |
|-----------|----------|
| BalanceDisplayMotion | Spring-based number transitions |
| StreakCounterMotion | Physics-based flame, smooth count updates |
| LeaderboardMotion | Staggered entries, layout animations, rank changes |
| ChallengeCardMotion | Animated progress, pulsing timers, spring physics |
| AnimatedList | Generic stagger wrapper with presets (fade, slide, scale, spring, bounce) |
| AnimatedItem | Individual animated item control |
Requires framer-motion as a peer dependency:
pnpm add framer-motionEffects Module 🎮
The Effects module provides game-like visual feedback for any UI element.
Glow Effects
import { GlowEffect, PulseGlow, LegendaryGlow, RainbowGlow } from '@loyalteez/react-components';
// Pulsing cyan glow
<GlowEffect color="cyan" pattern="pulse" intensity="normal">
<Card>Content</Card>
</GlowEffect>
// Heartbeat gold glow for rewards
<GlowEffect color="gold" pattern="heartbeat" intensity="intense">
<Badge>Premium</Badge>
</GlowEffect>
// Legendary rainbow glow
<LegendaryGlow>
<PerkCard perk={legendaryPerk} />
</LegendaryGlow>Shimmer Effects
import { ShimmerEffect, HolographicShimmer, GoldShimmer } from '@loyalteez/react-components';
// Holographic on hover
<ShimmerEffect variant="holographic" trigger="hover">
<Badge>New</Badge>
</ShimmerEffect>
// Auto gold shimmer for rewards
<GoldShimmer trigger="auto" delay={3000}>
<RewardCard />
</GoldShimmer>Particle Effects
import { ParticleEffect, CoinBurst, StarBurst, EmberEffect } from '@loyalteez/react-components';
// Coin collect on reward
<CoinBurst active={showReward} count={20} onComplete={hideReward} />
// Continuous ember particles
<EmberEffect active continuous emitRate={10}>
<StreakCounter streak={14} />
</EmberEffect>
// Custom particle configuration
<ParticleEffect
active={celebrating}
shape="star"
motion="burst"
colors={['#FFD700', '#FFA500', '#FF6B35']}
count={50}
intensity="intense"
/>Shake Effects
import { ShakeEffect, ErrorShake, ImpactShake, useShake } from '@loyalteez/react-components';
// Error shake on validation failure
<ErrorShake trigger={hasError}>
<Input />
</ErrorShake>
// Impact shake on achievement unlock
<ImpactShake trigger={unlocked} intensity="intense">
<AchievementBadge />
</ImpactShake>
// Imperative shake hook
function Component() {
const { shake, props } = useShake({ pattern: 'earthquake' });
return (
<ShakeEffect {...props}>
<button onClick={shake}>Trigger!</button>
</ShakeEffect>
);
}Count Effects (Dramatic Number Reveals)
import { CountEffect, SlotCounter, ScrambleCounter, useCountUp } from '@loyalteez/react-components';
// Slot machine reveal
<SlotCounter value={jackpot} intensity="extreme" showDelta />
// Scramble then settle
<ScrambleCounter value={score} from={previousScore} easing="bounce" />
// Imperative count hook
function PointsDisplay() {
const { countTo, props } = useCountUp();
return (
<>
<CountEffect {...props} />
<button onClick={() => countTo(1000)}>Add Points</button>
</>
);
}Tone System (Theme Presets)
import { ToneProvider, useTone, TONES } from '@loyalteez/react-components';
// Wrap your app with a tone
<ToneProvider tone="arcade">
<App />
</ToneProvider>
// Available tones:
// - default (Loyalteez signature)
// - arcade (bright, bouncy, retro)
// - casino (gold, luxury, high-stakes)
// - cyberpunk (neon, glitch, dark)
// - minimal (clean, subtle, professional)
// - playful (rounded, colorful, fun)
// - competitive (sports/esports energy)
// - fantasy (RPG, magical, mystical)
// - scifi (futuristic, tech, sleek)
// - retro (80s/90s nostalgia)
// Access current tone
function Component() {
const { tone, toneId, setTone } = useTone();
return <button onClick={() => setTone('cyberpunk')}>Go Cyber</button>;
}Effect Presets
import { EFFECT_PRESETS } from '@loyalteez/react-components';
// Pre-configured effect combos:
// - coinCollect, levelUp, milestone, streak
// - success, error, warning
// - common, rare, epic, legendary, mythic
// Use with components:
<GlowEffect {...EFFECT_PRESETS.legendary.glow} />
<ParticleEffect {...EFFECT_PRESETS.coinCollect.particles} />Utilities
import {
formatLTZ, // 1500000 → "1,500,000"
formatCompact, // 1500000 → "1.5M"
formatLTZAsDollars, // 5000 → "$5.00"
cn // Tailwind class merge utility
} from '@loyalteez/react-components';Documentation
- Storybook — Interactive component playground
- Full Documentation — API reference and guides
Development
# Install dependencies
pnpm install
# Start Storybook
pnpm dev
# Run tests
pnpm test
# Build library
pnpm build
# Type check
pnpm typecheck
# Lint
pnpm lintContributing
We welcome contributions! Please see our Contributing Guide for details.
License
MIT © Loyalteez
