A 162-wide vertical voucher tile combining a Voucher Asset image with title, description, price, validity, and status badges.
Replaced by Voucher Card Horizontal
This component is consolidated into
Voucher Card Horizontal — the canonical sibling. Use Voucher Card with orientation: vertical and the state axis instead. Once Figma usages migrate, this record will be deleted.Live Preview
Default (all props on)
Large asset only
Small asset minimal
Migration
Replaced byVoucher Card Horizontal
DS Health
Reusable
Fail
All text content is hardcoded placeholder. Consumers cannot set a title, price, validity, or badge label without detaching. A "reusable" voucher component that can only render the sample "Buy Load Pre-seeded SKU Voucher Sample" string is not reusable.
Self-contained
Warn
The symbol does carry its own layout, spacing, and token-bound colors via
main/vouchers/color/default/*. But it ships two asset frames bundled together, assuming consumers will turn one off — nothing enforces the mutual exclusion.Consistent
Fail
Parallel to Horizontal Voucher and Voucher Card Horizontal — three components for one concept. Voucher Card Horizontal ships a proper
state axis (Default/Limited/Expiring/Used/Expired); Vertical Voucher ships none. Property shape diverges across the family.Composable
Warn
Nests a Voucher Asset instance (composition works) and Badge instances (composition works). But since the voucher content is locked placeholder, a parent screen cannot actually compose real voucher data into this component.
Behavior
| State | iOS | Android | Figma Property | Notes |
|---|---|---|---|---|
| Asset size | N/A | N/A | largeAsset + smallAsset booleans | Two booleans for a mutually exclusive choice. Should be a single enum. |
| Title | N/A | N/A | header boolean (string hardcoded) | String is frozen in the symbol. Boolean only toggles visibility. |
| Price / original | N/A | N/A | amount boolean (strings hardcoded) | "PHP 100.00" and "PHP 150.00" frozen; one boolean toggles both. |
| Validity | N/A | N/A | validityPeriod boolean (string hardcoded) | "Validity: Dec 25 2022 - Jan 5 2023" frozen. |
| Status badges | N/A | N/A | prop1stRowBadges + prop2ndRowBadges | Two fixed rows of 2 fixed badge labels each. Row-level visibility only — consumers can't pick which badges to render. |
| State | N/A | N/A | Not modelled | Absent entirely. Voucher Card Horizontal has it; Vertical Voucher does not. |
| Tap target | N/A | N/A | Not modelled | Vouchers are always tappable; current symbol has no pressed/disabled states. |
Resolved Issues
- Voucher content tokens exist. Background (
main/vouchers/color/default/bg), title (label-title), description (label-description), amount (label-amount), strikethrough amount (label-amount-original), and metadata (label-metadata) are all bound to the voucher component's variable collection. C3 · Token Coverage
Open Issues
- Three parallel components for one concept. Vertical Voucher, Horizontal Voucher (
5121:4533), and Voucher Card Horizontal (5119:1786) share the same anatomy — voucher asset image + title + description + price + validity + status badges — but ship as three separate components with divergent property shapes. This is a family-level consolidation, not a single-component fix. C4 · Native Mappability - No state axis. Voucher Card Horizontal ships Default / Limited / Expiring / Used / Expired as a proper state variant that drives background, label colors, and badge treatment. Vertical Voucher has no state concept — a used or expired vertical voucher cannot be rendered in greyed-out treatment. C5 · Interaction State Coverage
- All text content is hardcoded placeholder. Title "Buy Load Pre-seeded SKU Voucher Sample", description "This is the description of the voucher.", price "PHP 100.00", original price "PHP 150.00", and validity "Validity: Dec 25 2022 - Jan 5 2023" are all frozen strings inside the symbol. Booleans toggle visibility but not content. Consumers cannot render a real voucher without detaching. C2 · Variant & Property Naming
- Two asset sizes bundled in one symbol. The symbol contains both the large (153h) and the small (100h) Voucher Asset instances stacked;
largeAssetandsmallAssetbooleans turn them on/off. The default 465h render shows both. This is a single enum (assetSize: large | small) masquerading as two booleans with implied mutual exclusion. C2 · Variant & Property Naming - Badges are row-level, not array-level.
prop1stRowBadgesandprop2ndRowBadgestoggle rows of two hardcoded badges each ("Limited" + "Expiring" / "Hot" + "Discounted"). A real voucher with one "Limited" badge and nothing else cannot be rendered. Badges should be a composable array, not fixed rows. C2 · Variant & Property Naming - Layer structure is flat and unlabeled.
large asset,small asset,content,badges,badges(duplicate),price. Two layers namedbadges, no semantic names for the title/description/validity text nodes. Consumers inspecting the Dev Mode output see anonymous text layers. C1 · Layer Structure & Naming - Voucher Asset nested image is raster with hardcoded "35% off" Badge. Inherits all the issues of Voucher Asset (
5119:1664) — the discount amount is baked into the image-frame variant, not a property on the parent. A voucher offering "50% off" or "BUY1 TAKE1" cannot be rendered. C6 · Asset & Icon Quality - No native component maps to this shape. 8 booleans with hardcoded content do not map to any reasonable native API. A proper
EBVoucherCardtakes title, price, validity, badges array, and image as parameters — not eight visibility toggles. Code Connect has no 1:1 target. C4 · Native Mappability - Code Connect cannot link an 8-boolean symbol with frozen strings. Even if a mapping existed, swapping the "title" string or the badge labels would require detaching the component. Linkability requires real string/array properties first. C7 · Code Connect Linkability
Design Recommendations
- Merge the three voucher cards into a single Voucher Card component. Vertical Voucher + Horizontal Voucher + Voucher Card Horizontal become one component with
orientation: vertical | horizontal(swaps the layout axis) andstate: default | limited | expiring | used | expired(borrowed from Voucher Card Horizontal). Target shape: 2 orientations × 5 states = 10 variants instead of three separate components with divergent schemas. Family - Promote every text string to a property. Add
title: String,description: String,price: String,originalPrice: String?,validity: String?. Retire theheader/amount/description/validityPeriodbooleans — visibility falls out of whether the string is empty. Property - Replace the two asset-size booleans with one
assetSizeenum.largeAsset+smallAssetbecomeassetSize: large | small | none. Nothing currently prevents both being on simultaneously (which is the default render). A single enum makes the choice explicit and mutually exclusive. Property - Adopt a Figma Slot for the voucher image. Replace the hardcoded Voucher Asset nested instance with a Slot that accepts any Voucher Asset variant (or a partner brand illustration). The discount badge should be composed on top of the slot, not baked into the asset. Slot
- Replace fixed badge rows with a composable badges array. Drop
prop1stRowBadges/prop2ndRowBadges. Expose a badges Slot that accepts 0..n Badge instances, wraps when it runs out of width. Consumers choose which badges apply ("Limited" alone, "Hot" + "Discounted" + "New", etc.). Slot - Add the state axis missing from Vertical Voucher. Used and Expired vouchers render in greyed-out treatment with muted labels and a dim asset overlay — a pattern Voucher Card Horizontal already ships. Port the same 5-state treatment to the unified Voucher Card. State
- Rename duplicated
badgeslayers. The two badge-row frames are both namedbadges. After the consolidation above they should collapse into a singlebadges-slotlayer; until then, name thembadges-row-1/badges-row-2to disambiguate. Rename - Document that Voucher Card is the tap target. Vouchers are always tappable entry points to the voucher detail screen. The unified component should ship a pressed/focused state on the card frame; the handoff is an
onTapclosure, not an internal CTA button. Docs
Styles
Vertical Voucher
DES DEV
Legacy 162-wide vertical voucher tile. Migrate to <a href="/components/voucher-card-horizontal">Voucher Card Horizontal</a> with <code>orientation: vertical</code>.
Properties
Orientation vertical
Width 162
Colors
Surface bg #FFFFFF
Title #0A2757
Description #445C85
Amount #005CE5
Original price #90A8D0
Validity #6780A9
Layout
Width 162
Image area 162 × 153
Body padding 8 12 12 12
Corner radius 4
Border 1px solid #E6EAF2
Typography
Title Proxima Soft Bold · 14 / 18 · +0.25
Amount Proxima Soft Bold · 14 · +0.25
Original price Proxima Soft Semibold · 12 (strike)
Validity BarkAda Semibold · 10 / 15
Property Mapping
The current 8 booleans do not map cleanly to native. The table below shows the target shape after the family consolidation — each row captures what the proposed EBVoucherCard replaces from the current Vertical Voucher.
| Figma Property | SwiftUI | Compose |
|---|---|---|
| — | orientation | orientation: EBVoucherOrientation |
| — | state | state: EBVoucherState |
largeAsset + smallAsset | assetSize | assetSize: .large | .small | .none |
header (boolean, string frozen) | title (string) | title: String |
description (boolean, string frozen) | description (string) | description: String? |
amount (boolean, PHP 100 / PHP 150 frozen) | price + originalPrice | price: String, originalPrice: String? |
validityPeriod (boolean, string frozen) | validity (string) | validity: String? |
prop1stRowBadges + prop2ndRowBadges | badges Slot | badges: [EBBadge] |
| nested Voucher Asset | Image Slot | trailing closure |
| — | — | onTap: () -> Void |
Criteria Scorecard
| ID | Criterion | Status | Notes |
|---|---|---|---|
| C1 | Layer Structure & Naming | Requires Rework | Two frames both named badges. Text layers are unnamed. Asset frames large asset / small asset should be one frame with an assetSize property. |
| C2 | Variant & Property Naming | Requires Rework | 8 booleans where most should be strings (title, price, validity) or a Slot (badges). largeAsset + smallAsset should be one enum. All content is frozen placeholder. |
| C3 | Token Coverage | Ready | Background, title, description, amount, strikethrough amount, and metadata are all bound to main/vouchers/color/default/*. Typography uses named text styles (Primary/Multi-line Label/Base, Primary/Label/Small, Secondary/Default/Caption, Secondary/Default/Fine). |
| C4 | Native Mappability | Requires Rework | Parallel to 2 other voucher components with divergent schemas. Native has one EBVoucherCard, not three. 8 booleans with frozen strings have no native analog. |
| C5 | Interaction State Coverage | Requires Rework | No state axis at all. Voucher Card Horizontal ships Default/Limited/Expiring/Used/Expired; Vertical Voucher has none. No pressed/focused/disabled on the card frame either. |
| C6 | Asset & Icon Quality | Requires Rework | Inherits Voucher Asset's raster + hardcoded "35% off" badge. The discount amount is not a property on the parent Voucher. |
| C7 | Code Connect Linkability | Requires Rework | Cannot map. Frozen strings, row-level badge toggles, and two-boolean asset size do not have 1:1 native parameters. Linkability requires the family consolidation first. |
Variants Inventory (1 total)
Single symbol, no variant axes declared. All configurability is through 8 boolean property toggles on the lone instance.
| Node ID | Name | Dimensions | Property toggles |
|---|---|---|---|
5119:1635 | Vertical Voucher | 162 × 465 (with both assets + all content on) | amount, description, header, largeAsset, prop1stRowBadges, prop2ndRowBadges, smallAsset, validityPeriod — all boolean, all default true |
1.0.0 — April 2026Major
Initial Assessment · node 5119:1635
Assessed with Consolidate verdict. Single symbol with no variants, 8 boolean toggles, and entirely hardcoded content. Parallel to Horizontal Voucher (
Design Decision5121:4533) and Voucher Card Horizontal (5119:1786). OpenProposed family-level merge. Collapse the 3 voucher components into one
Design DecisionVoucher Card with orientation + state axes, text slots (title, description, price, originalPrice, validity), a badges array, and a voucher image Slot. Target: 2 × 5 = 10 variants instead of 3 divergent components. Open