figma guide
Designing loyalty programs and rewards UI in Figma: points, tiers, and checkout redemption
Design loyalty points, tier badges, earn-and-burn flows, and checkout redemption UI in Figma with component variants, balance states, and Dev Mode specs for ecommerce teams.
- Published
- Updated
- Jun 28, 2026
- Read time
- 7 min
- Level
- Beginner
Quick answer
Loyalty UI is a small set of reusable components—balance display, tier badge, earn callout, and redemption control—wired to the same points ledger everywhere. Show points balance in the account header, cart drawer, and checkout summary. At checkout, offer a toggle or slider to apply points with live order-total updates. Tier status (Silver, Gold) appears as a compact badge on profile and PDP promos. Never design loyalty as a separate visual language; reuse pricing tokens, badges, and progress indicators from your ecommerce system. Start from the Figma guides hub and templates pillar.
Who this is for
- Product designers shipping DTC programs where repeat purchase and membership tiers drive revenue.
- Design system teams standardizing points math, tier visuals, and redemption states across web and app.
- Engineers implementing ledger APIs, partial redemption rules, promo stacking, and fraud limits.
Loyalty surfaces map
| Surface | Component | Purpose |
|---|---|---|
| Global header / account menu | PointsBalance | Always-visible balance pill |
| PDP promo band | EarnCallout | ”Earn 120 points with this purchase” |
| Cart drawer | PointsBalance + optional apply link | Remind before checkout |
| Checkout payment step | PointsRedemption | Apply/remove points with live total |
| Order confirmation | PointsEarned | Post-purchase reinforcement |
| Account loyalty hub | LoyaltyDashboard | History, tier progress, rewards catalog |
| Order history row | PointsEarnedLine | Per-order earn/spend audit |
Verdict: checkout redemption is the highest-risk surface—design every state (available, applied, insufficient, expired) before polishing the marketing dashboard.
PointsBalance anatomy
| Part | Spec | Notes |
|---|---|---|
| Icon | Star, coin, or brand mark | 16–20px; consistent everywhere |
| Balance number | Integer or formatted | ”1,240 pts” or “$12.40 value”—pick one model |
| Label (optional) | “Rewards” | Hide on compact header variant |
| Tier badge | TierBadge adjacent | Gold dot or pill |
| Loading | Skeleton or spinner | On account fetch |
PointsBalance
├── Variant: density=compact | standard
├── Variant: state=loaded | loading | error | guest
├── Property: balance=1240
├── Property: showTier=true
└── Layers:
├── Icon
├── BalanceText
└── TierBadge (optional)
Use Auto Layout with 4px gaps. Guest state should prompt Sign in to earn points with a text link—not a disabled balance that looks broken.
TierBadge and tier progress
| Tier pattern | UI treatment | When to use |
|---|---|---|
| Named tiers | Silver / Gold / Platinum pills | Status programs with thresholds |
| Progress to next tier | Bar + “Spend $80 more for Gold” | Annual spend or points-based tiers |
| Flat membership | Single “Member” chip | No tiers; perks only |
| Subscription overlap | Separate badge | When loyalty ≠ subscription product |
TierProgress
├── Variant: layout=inline | card
├── Property: currentTier=Silver
├── Property: nextTier=Gold
├── Property: progressPercent=65
└── Layers:
├── TierBadge
├── ProgressTrack → ProgressFill
└── NextTierMessage
Reuse progress indicator tokens for the track. Tier colors must pass accessibility contrast on both light PDP promos and dark account headers.
EarnCallout on PDP and cart
| Placement | Copy pattern | Avoid |
|---|---|---|
| Below price | ”Earn 50 points ($0.50)“ | Burying in footer |
| Cart line item | Per-SKU earn on eligible items | Showing earn on excluded SKUs |
| Checkout summary | Total earn for order | Conflicting with applied redemption |
Link earn copy to the same points-per-dollar rule documented in Dev Mode. If coupons reduce eligible subtotal, annotate that earn may recalculate.
PointsRedemption at checkout
| State | UI | User action |
|---|---|---|
| Available | Toggle “Apply 500 points ($5.00)“ | Toggle on |
| Applied | Green check + deducted line in summary | Toggle off or edit amount |
| Partial apply | Slider or stepper for points amount | Rare; needs clear max |
| Insufficient | Disabled toggle + explanation | None |
| Cannot combine | Inline alert when stacked with coupon | Remove coupon or points |
| Loading | Disabled toggle + spinner | Wait for ledger |
| Error | Inline alert + retry | Retry fetch |
PointsRedemption
├── Variant: state=available | applied | disabled | loading | error
├── Property: maxPoints=500
├── Property: pointsValue=5.00
├── Property: currency=USD
└── Layers:
├── ToggleRow (label + switch)
├── ValuePreview
├── SummaryDeductionLine (applied)
└── ConflictAlert (optional)
Order summary lines should mirror checkout UI: Subtotal → Discounts → Points applied (−$5.00) → Tax → Total. Tax recalculation after points is a backend rule—note it in handoff.
LoyaltyDashboard (account hub)
| Zone | Content | Components |
|---|---|---|
| Hero | Balance + tier | PointsBalance, TierProgress |
| Quick actions | Redeem, refer, view catalog | Button row |
| Activity feed | Earn/spend history | Table or list rows |
| Rewards catalog | Redeemable coupons, free products | Card grid |
| Referral block | Share link + bonus | Copy field + toast on copy |
| FAQ | Program rules | Accordion |
Align activity rows with order history patterns so users recognize the same date, status, and amount formatting.
Stacking rules comparison
| Rule | UX implication | Design note |
|---|---|---|
| Points + site-wide sale | Usually allowed | Show earn on discounted price |
| Points redemption + coupon | Often blocked | ConflictAlert variant required |
| Points on gift card purchase | Often excluded | Hide earn callout on gift card UI |
| Free shipping tier + points | Independent | Shipping bar unchanged |
| Partial points + card payment | Standard | Remaining balance on card line |
Document stacking in a Program rules frame linked from checkout—not buried in legal PDF only.
Responsive and mobile patterns
| Breakpoint | Adaptation |
|---|---|
| Mobile checkout | Full-width redemption card above payment methods |
| Mobile header | Icon-only balance with tap → loyalty hub |
| Tablet | Balance in account drawer, not crowding header |
| App | Match web component names for parity |
Use mobile frame presets for checkout and account screens. Sticky checkout summary should still show applied points when user scrolls payment methods.
Handoff checklist
| Item | Dev Mode annotation |
|---|---|
| Points ↔ currency ratio | e.g. 100 pts = $1.00 |
| Rounding rules | Floor vs round on partial redemption |
| Ledger fetch timing | On login, cart change, checkout enter |
| Toggle analytics | loyalty_apply, loyalty_remove, loyalty_error |
| Tier source | Annual spend vs rolling 12 months |
| Expiration | Show expiry date on balance when applicable |
| Guest vs member | Earn disabled; CTA to register |
| a11y | Toggle has visible label; balance not icon-only without text |
| API error copy | Exact strings for insufficient and conflict |
Use Dev Mode checklist and share props with coupon components for conflict states.
Common mistakes
| Mistake | Why it hurts | Fix |
|---|---|---|
| Different point icons per page | Breaks trust | One PointsBalance component |
| Showing earn and apply without math | Users feel cheated | Single ledger preview |
| Tier badge without progress context | Status feels arbitrary | Add TierProgress or tooltip |
| Redemption toggle with no summary line | Total looks wrong | Mirror deduction in order summary |
| Loyalty hub uses new card style | Visual fragmentation | Reuse account cards |
| No guest state | Confusing empty balance | Sign-in CTA variant |
| Points conflict with coupon silently fails | Support tickets | Explicit ConflictAlert |
| Dashboard history ≠ order history | Duplicate confusion | Link rows to order detail |
Recommended workflow
- Define program rules with product—ratio, tiers, stacking, expiration.
- Build
PointsBalance,TierBadge, andTierProgresswith guest and error variants. - Add
EarnCalloutto PDP and cart frames using pricing placement. - Design
PointsRedemptionwith all checkout states on checkout frames. - Compose
LoyaltyDashboardwith activity feed and rewards catalog. - Wire conflict states with coupon and free shipping frames.
- Annotate ledger API fields and analytics in Dev Mode.
- Run accessibility check on toggles and tier color tokens.
FAQ
Points displayed as points or dollar value?
Pick one primary display (usually points) and optional secondary value in parentheses. Switching between pages confuses users and complicates localization.
Show loyalty on every PDP?
Show earn callout on eligible SKUs only. Use a neutral “Not eligible for rewards” line only when competitors do—otherwise omit.
Separate app for loyalty?
If a standalone app exists, still match component names and states on web so design and engineering share one spec document.
Birthday rewards and campaigns?
Treat as time-boxed EarnCallout variants with campaignId prop—do not fork the base component.
B2B accounts with negotiated pricing?
Add loyaltyEligible=false at account level; hide earn and redemption with member-admin explanation in account settings.
Next steps
- Design coupons and promo codes UI in Figma — stacking and conflict states
- Design shopping cart and checkout UI in Figma — order summary lines
- Design order history and order tracking UI in Figma — activity alignment
- Design price tags and pricing UI in Figma — earn calculation base
- Design gift cards and vouchers UI in Figma — exclusion rules
§ Keep reading