A ticket-shaped image clipped into a notched frame, used as the visual on voucher placements.
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.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.| 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. |
- 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|hifiis 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) andfood(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
- Collapse into one Voucher Image Frame component. Retire
use caseandtype. Keepsize: small | largeandorientation: vertical | horizontal. Add an image Slot that accepts any illustration instance, plus adiscountstring (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
discountto 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) andres/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
Default voucher asset with brand discount badge in the top-left. Used as the visual hero on Voucher Card.
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 |
Voucher asset rendered without the discount badge — used when the parent card already shows discount info elsewhere.
Pure image fill — no DS-owned color tokens beyond the publisher-supplied creative.
| Role | Token | Default |
|---|---|---|
| Surface | image fill (no token) | Image only |
Voucher asset for expired vouchers — image rendered behind a translucent dimmer to signal unavailability.
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 |
| Figma Property | SwiftUI | Compose |
|---|---|---|
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 |
| — | — | |
| — | — |
| 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. |
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 case | Sizes shipped | Orientations shipped | Count |
|---|---|---|---|
| Default (midfi) | small, large | Default, horizontal | 3 |
| Restaurant | small, large | Default | 2 |
| Vacation | small, large | Default | 2 |
| Beverage | small, large | Default | 2 |
| Snack | small, large | Default | 2 |
| Fashion | small, large | Default | 2 |
| Party | small, large | Default | 2 |
| Meal | small, large | Default | 2 |
| Games | small, large | Default | 2 |
| Food | large | horizontal | 1 |
use case enum and a type=midfi|hifi fidelity axis — both are anti-patterns. Opensize + orientation + image Slot + discount string. Move category artwork to a sibling asset library. Target: 4 variants instead of 20. Open