RestructureRequires Rework
Voucher Asset Component link

A ticket-shaped image clipped into a notched frame, used as the visual on voucher placements.

Collapse use-case variants into an image Slot
Use case is illustration content — it does not belong as a Figma variant axis. A new category launch should not require a new DS variant. Retire type=midfi|hifi (authoring fidelity, not product concern) and use case (content, not variant). Ship a single Voucher Image Frame with size: small | large + orientation: vertical | horizontal, plus an image Slot and a discount string. Category artwork lives in a separate asset library, instance-swapped into the Slot.
Live Preview
Placeholder35% offPlaceholder35% off
placeholder
Restaurant35% offRestaurant35% off
restaurant
Vacation35% offVacation35% off
vacation
Beverage35% offBeverage35% off
beverage
Snack35% offSnack35% off
snack
Fashion35% offFashion35% off
fashion
Party35% offParty35% off
party
Meal35% offMeal35% off
meal
Games35% offGames35% off
games
Placeholder Image35% off
default · horizontal
Food35% off
food · horizontal
Variants
Categoriesplaceholder · restaurant · vacation · beverage · snack · fashion · party · meal · games · food
Sizes110×68 · 110×104 · 226×96
Discount badgealways shown
Composition
Image fillpublisher-supplied
Notch shapeSVG clip-path
DS Health
Reusable
Fail
Tied to specific illustration categories. Consumers cannot supply their own voucher image — they must pick from the 10 baked-in use cases or detach the component.
Self-contained
Warn
Ships the ticket frame and Badge instance, but the voucher amount ("35% off") is hardcoded into the image, not a property. Consumers can't change the discount without swapping the whole variant.
Consistent
Fail
Property schema is contradictory. type=midfi is an authoring state, use case is content, size and orientation are geometry. Cartesian space is sparse — only default and food exist in horizontal; most use cases don't. New categories require new variants.
Composable
Warn
Used inside Vertical Voucher, Horizontal Voucher, and Voucher Card Horizontal — composition works. But since content is locked to 10 categories, the parent voucher components inherit the same constraint.
Behavior
State iOS Android Figma Property Notes
Image source N/A N/A use case enum Native doesn't switch on an enum — it reads a named asset. The Figma enum is a Figma-only crutch.
Size N/A N/A size enum Two fixed sizes; horizontal variants override to 336×144.
Discount label N/A N/A Badge instance Currently hardcoded string. Should be a discount property on the parent component.
Clipping shape No No Mask Ticket notch + dashed center line is the only DS-specific visual primitive here.
Open Issues
  • Use-case axis promotes illustration content into variants. 10 use-case values (restaurant, vacation, beverage, snack, fashion, party, meal, games, food, default) mean every new voucher category ships a new DS variant. This is the same anti-pattern Ad Space retired. Consumers should instance-swap an illustration into a Slot, not pick from a DS-owned enum. C2 · Variant & Property Naming
  • Fidelity axis type=midfi|hifi is not a product concern. Mid-fidelity "Placeholder image" wireframes vs hi-fidelity final photos is an authoring-workflow state, not a variant the product should expose. Native has no concept of "mid-fidelity"; this axis will not map. Same pattern retired on Ad Space. C2 · Variant & Property Naming
  • Cartesian space is sparse (20/40 shipped). 10 use cases × 2 sizes × 2 orientations = 40 possible variants. Only 20 actually exist. Horizontal orientation only exists for default (midfi wireframe) and food (hifi GrabFood). Most use cases have no horizontal artwork. The matrix is authored ad-hoc, not systematically. C1 · Layer Structure & Naming
  • Discount amount "35% off" is hardcoded. The Badge instance inside every variant renders a fixed "35% off" string. There is no property to change the voucher discount — consumers with a 50% off or BUY1TAKE1 promo must detach. C2 · Variant & Property Naming
  • All artwork is raster image fill. 19 of 20 variants are photographic images; 1 is a grey placeholder. No vector illustrations, no token-driven coloring. Images live inside the component, not in a separate asset library, which means they ship with every DS publish and bloat the library. C6 · Asset & Icon Quality
  • No native component to map to. Native handoff for category illustration is an asset catalog entry (Image("voucher-restaurant-large")) — not a Code-Connected DS component. Only the ticket frame + badge overlay warrants a component on native. The use-case enum has no iOS/Android correlate. C4 · Native Mappability
  • Code Connect cannot map a 10-value content enum. Even if a mapping existed, it would force 10 named image assets per size × orientation combination into the codebase, locked to the Figma enum. Any new category requires a Figma variant ship + a native code ship in lockstep. C7 · Code Connect Linkability
Design Recommendations
  • Collapse into one Voucher Image Frame component. Retire use case and type. Keep size: small | large and orientation: vertical | horizontal. Add an image Slot that accepts any illustration instance, plus a discount string (default "35% off") that drives the Badge. Target schema: 2 × 2 = 4 variants instead of 20. Property
  • Move category artwork to a separate Voucher Illustrations library. Ship a sibling library with named illustration instances organized by category (Food, Travel, Entertainment, etc.). Consumers instance-swap the illustration into the Voucher Image Frame's Slot. New categories are added to the library, not to the DS component. Family
  • Adopt a Figma Slot for the image fill. The current pattern (hardcoded image fill per variant) prevents consumers from using branded partner artwork (GrabFood, Tim Hortons, etc. — already visible in current variants) without detaching. A Slot lets product teams bring their own asset. Slot
  • Promote discount to a string property. Extract the "35% off" text out of the variants so vouchers can show any discount format ("50% off", "BUY1 TAKE1", "₱100 OFF"). The Badge instance is already composable; only the string needs exposing. Property
  • Close the orientation matrix. Either commit to supporting horizontal for every size (ship the missing artwork through the Slot), or drop orientation as an axis and let parents set aspect ratio. The current sparse matrix (2 horizontal variants out of 20) signals the axis is accidental. Property
  • Native handoff is asset catalog, not Code Connect. Document that voucher illustrations ship via Assets.xcassets (iOS) and res/drawable/ (Android). The DS component's Code Connect mapping should cover only the ticket frame + Badge + discount string; category art is a product-team responsibility. Docs
Styles
Default — with discount badge
DES DEV

Default voucher asset with brand discount badge in the top-left. Used as the visual hero on Voucher Card.

Voucher Image50% OFF
Properties
Status
Discount badge
Properties
Status Default
Has discount badge Yes
Badge label 50% OFF
Colors
Badge bg #1972F9
Badge label #FFFFFF
Layout
Width 144 (fill image)
Height 144
Badge height 20
Badge padding (h) 8
Badge radius 4
Badge top 8
Badge left 8
Typography
Badge style Primary/Label/Small
Font Proxima Soft
Size 14
Weight 700 (Bold)
Line-height 14
Tracking 0.25
Default — Colors

Image-led voucher asset with a brand-blue category badge clipped at the bottom-left.

Role Token Default
Badge bg main/badge/brand/heavy/background #1972F9
Badge label main/badge/brand/heavy/label #FFFFFF
No badge — image only
DES DEV

Voucher asset rendered without the discount badge — used when the parent card already shows discount info elsewhere.

Voucher Image
Properties
Status
Discount badge
Properties
Status Default
Has discount badge No
Badge label
Colors
Surface Image only
Layout
Width 144 (fill image)
Height 144
Padding 0
Radius 0
Typography
N/A No text in this variant
Image Only — Colors

Pure image fill — no DS-owned color tokens beyond the publisher-supplied creative.

Role Token Default
Surface image fill (no token) Image only
Expired — dimmed with overlay
DES DEV

Voucher asset for expired vouchers — image rendered behind a translucent dimmer to signal unavailability.

Voucher Image50% OFF
Properties
Status
Discount badge
Properties
Status Expired
Has discount badge Yes
Has overlay Yes
Colors
Overlay bg #020E223D (24% opacity)
Badge bg (muted) #C2C5CA
Badge label #FFFFFF
Layout
Width 144
Height 144
Overlay coverage Full image
Badge height 20
Badge top 8
Badge left 8
Typography
Badge style Primary/Label/Small
Font Proxima Soft · Bold 14
Expired — Colors

Scrim overlay + muted badge to signal the voucher is no longer valid.

Role Token Default
Overlay bg bg/color-bg-overlay-weak #020E22 @ 24%
Badge bg (muted) main/badge/muted/light/background #C2C5CA
Badge label main/badge/muted/light/label #FFFFFF
Property Mapping
Figma PropertySwiftUICompose
size size: EBVoucherImageFrameSize size = EBVoucherImageFrameSize
orientation orientation: .vertical | .horizontal orientation = Vertical | Horizontal
discount (string) discount: String discount: String
Image Slot content: () -> Image content: @Composable () -> Unit
use case
type (midfi/hifi)
Criteria Scorecard
ID Criterion Status Notes
C1 Layer Structure & Naming Requires Rework 20 variants with sparse orientation coverage — only default and food have horizontal artwork. Matrix is not closed.
C2 Variant & Property Naming Requires Rework use case is content, not a variant. type=midfi|hifi is authoring fidelity, not a product axis. "35% off" is hardcoded.
C3 Token Coverage Needs Refinement Badge uses token-bound colors and typography. Image fills bypass tokens (raster).
C4 Native Mappability Requires Rework No native correlate for a 10-value illustration enum. Correct handoff is asset catalog + lean frame component.
C5 Interaction State Coverage Not Applicable Display-only artwork; no interactive states.
C6 Asset & Icon Quality Requires Rework All raster. 19/20 variants are photos; 1 placeholder. Assets should live in a sibling library, not the component.
C7 Code Connect Linkability Requires Rework Cannot map a 10-value content enum 1:1 to a native parameter. Linkability requires collapsing use case first.
Variants Inventory (20 total)

Current shape: type × size × use case × orientation. Cartesian space is 2 × 2 × 10 × 2 = 80, only 20 shipped. Heavily skewed toward type=hifi / orientation=Default (16 of 20). midfi exists only for use case=Default; every other use case has only hifi artwork.

Use caseSizes shippedOrientations shippedCount
Default (midfi)small, largeDefault, horizontal3
Restaurantsmall, largeDefault2
Vacationsmall, largeDefault2
Beveragesmall, largeDefault2
Snacksmall, largeDefault2
Fashionsmall, largeDefault2
Partysmall, largeDefault2
Mealsmall, largeDefault2
Gamessmall, largeDefault2
Foodlargehorizontal1
1.0.0 — April 2026Major
Initial Assessment · node 5119:1664
Assessed with Restructure verdict. 20-variant sprawl driven by a 10-value use case enum and a type=midfi|hifi fidelity axis — both are anti-patterns. Open
Design Decision
Proposed restructure. Collapse to a single Voucher Image Frame with size + orientation + image Slot + discount string. Move category artwork to a sibling asset library. Target: 4 variants instead of 20. Open
Design Decision