ConsolidateRequires Rework
Horizontal Voucher Component link

A 336-wide voucher tile with a 144px hero image, status row, title, price, and validity period.

Replaced by Voucher Card Horizontal
This component is consolidated into Voucher Card Horizontal — the canonical sibling. Use Voucher Card with orientation: horizontal and the state axis instead. Once Figma usages migrate, this record will be deleted.
Live Preview
GrabFood35% off
LimitedExpiringHotDiscounted
Grab Food
This is the description of the voucher.
PHP 100.00
PHP 150.00
Validity: Dec 25 2022 - Jan 5 2023
Default (all props on)
GrabFood35% off
Grab Food
PHP 100.00
PHP 150.00
Validity: Dec 25 2022 - Jan 5 2023
Minimal — header + price + validity
Migration
DS Health
Reusable
Fail
All text content is hardcoded placeholder. Consumers cannot set a title ("Grab Food"), price (PHP 100.00), validity, or badge label without detaching. A "reusable" voucher component that can only render one frozen sample string is not reusable.
Self-contained
Warn
The symbol carries its own layout, spacing, and token-bound colors via main/vouchers/color/default/*. But it ships two stacked discount Badge instances ("10% off" + "35% off") at the same anchor, assuming one is invisible — nothing in the schema picks between them.
Consistent
Fail
Parallel to Vertical Voucher and Voucher Card Horizontal — three components for one concept. Voucher Card Horizontal ships a proper state axis (Default/Limited/Expiring/Used/Expired); Horizontal Voucher ships none. Property shape diverges across the family (6 booleans here vs 8 in Vertical vs 2 booleans + 4-state enum in Voucher Card Horizontal).
Composable
Warn
Nests Badge instances for the badge row (composition works). But the hero image is a raster asset baked into the frame, not a Voucher Asset instance — consumers cannot swap partner imagery without detaching. And since all voucher content is locked placeholder, a parent screen cannot compose real voucher data.
Behavior
State iOS Android Figma Property Notes
Hero image N/A N/A asset boolean (raster frozen) Currently a 336×144 raster with the "GrabFood" wordmark baked in. Should accept any Voucher Asset variant.
Discount amount N/A N/A Two stacked Badges ("10% off" + "35% off") Two Badge instances at the same anchor. Should be a single discount string property on the Voucher Asset, not two stacked layers.
Title N/A N/A header boolean (string hardcoded) "Grab Good" frozen in the symbol. Boolean only toggles visibility.
Description N/A N/A description boolean (string hardcoded) "This is the description of the voucher." frozen.
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 badges boolean (row of 4 hardcoded) Single row of 4 fixed badge labels ("Limited", "Expiring", "Hot", "Discounted"). Row-level visibility only.
State N/A N/A Not modelled Absent entirely. Voucher Card Horizontal has it; Horizontal 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 (text/color-text-inverse = white card surface), title (main/vouchers/color/default/label-title), description (label-description), amount (label-amount), strikethrough amount (rendered as #90a8d0, matches label-amount-original), and metadata (label-metadata) are all bound to the voucher component's variable collection. C3 · Token Coverage
  • Card elevation is tokenised. The card uses app/shadow/shadow-low (0px/0px/4px, elevation/app/shadow-low/color rgba(2,14,34,0.06)). No hardcoded shadow values on the parent frame. C3 · Token Coverage
Open Issues
  • Three parallel components for one concept. Horizontal Voucher, Vertical Voucher (5119:1635), and Voucher Card Horizontal (5119:1786) share the same anatomy — voucher 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. Horizontal Voucher has no state concept — a used or expired horizontal voucher cannot be rendered in greyed-out treatment. C5 · Interaction State Coverage
  • All text content is hardcoded placeholder. Title "Grab Food", 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 stacked discount Badges at the same anchor. The Voucher Asset image frame nests two Badge instances (I5121:4534;6983:110671 "10% off" and I5121:4534;6983:110685 "35% off") both absolutely positioned at the top-right. Only one is ever intended to be visible, but no property selects between them — both render on top of each other in the raw symbol. C1 · Layer Structure & Naming
  • Discount amount is baked into the image frame. The "35% off" / "10% off" label is a hardcoded Badge text inside the Voucher Asset, not a property on the parent Horizontal Voucher. A voucher offering "50% off" or "BUY1 TAKE1" cannot be rendered. Should be a discount: String? property on the image slot. C2 · Variant & Property Naming
  • Status badges are row-level, not array-level. The badges boolean toggles a single fixed row of 4 hardcoded Badge instances ("Limited" + "Expiring" + "Hot" + "Discounted") on or off. A real voucher with one "Limited" badge and nothing else cannot be rendered. Badges should be a composable array, not a fixed row. C2 · Variant & Property Naming
  • Hero image is a raster photograph with burned-in partner wordmark. Paste Image Here / imgPasteImageHere is a 336×144 raster asset with the "GrabFood" wordmark burned into the pixels. Partner branding and image content are frozen. Should be an Image Slot that accepts any Voucher Asset variant (GrabFood, Globe, Smart, Shopee, etc.). C6 · Asset & Icon Quality
  • No native component maps to this shape. 6 booleans with hardcoded content do not map to any reasonable native API. A proper EBVoucherCard takes title, price, validity, badges array, and image as parameters — not six visibility toggles over frozen strings. Code Connect has no 1:1 target. C4 · Native Mappability
  • Code Connect cannot link a 6-boolean symbol with frozen strings. Even if a mapping existed, swapping the "title" string, the hero image, or the badge labels would require detaching the component. Linkability requires real string/array properties and an image Slot first. C7 · Code Connect Linkability
Design Recommendations
  • Merge the three voucher cards into a single Voucher Card component. Horizontal Voucher + Vertical Voucher + Voucher Card Horizontal become one component with orientation: vertical | horizontal (swaps the layout axis) and state: default | limited | expiring | used | expired (borrowed from Voucher Card Horizontal — the canonical sibling since it already ships the state axis). 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 the header / amount / description / validityPeriod booleans — visibility falls out of whether the string is empty. Property
  • Replace the stacked discount Badges with one discount string on the image slot. Drop the duplicated "10% off" and "35% off" Badge instances inside the Voucher Asset frame. Expose discount: String? on the voucher-image Slot so any discount value ("10% off", "50% off", "BUY1 TAKE1") can be rendered without editing the symbol. Property
  • Adopt a Figma Slot for the hero image. Replace the raster Paste Image Here fill with a Slot that accepts a Voucher Asset instance (or any partner illustration component). The discount overlay and the raster wordmark both move into the swapped-in asset, not into the parent Voucher. Slot
  • Replace the fixed 4-badge row with a composable badges array. Drop the single badges boolean. Expose a badges Slot that accepts 0..n Badge instances and wraps when it runs out of width. Consumers choose which badges apply ("Limited" alone, "Hot" + "Discounted", "New" + "Featured", etc.). Slot
  • Add the state axis missing from Horizontal Voucher. Used and Expired vouchers render in greyed-out treatment with muted labels and a dimmed hero image — a pattern Voucher Card Horizontal already ships. Port the same 5-state treatment to the unified Voucher Card. State
  • Remove the dead 10% off Badge layer. The image frame carries both I5121:4534;6983:110671 ("10% off") and I5121:4534;6983:110685 ("35% off") at identical coordinates; after the discount property above is introduced, only one Badge instance should remain, with its text bound to the new property. Composition
  • 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 onTap closure, not an internal CTA button. Docs
Styles
Horizontal Voucher
DES DEV

Legacy 336-wide voucher tile. Same hex values + token paths as the canonical <a href="/components/voucher-card-horizontal">Voucher Card Horizontal</a>; migrate to that component when you can.

GrabFood35% off
LimitedExpiringHotDiscounted
Grab Food
This is the description of the voucher.
PHP 100.00
PHP 150.00
Validity: Dec 25 2022 - Jan 5 2023
Properties
Orientation horizontal
Width 336
Colors
Surface bg #FFFFFF
Title #0A2757
Description #445C85
Amount #005CE5
Original price #90A8D0
Validity #6780A9
Layout
Width 336
Image area 336 × 144
Body padding 8 12 12 12
Corner radius 4
Border 1px solid #E6EAF2
Typography
Title Proxima Soft Bold · 16 / 20 · +0.25
Amount Proxima Soft Bold · 14 / 14 · +0.25
Original price Proxima Soft Semibold · 14 (strike)
Validity BarkAda Semibold · 10 / 15
Property Mapping

The current 6 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 Horizontal Voucher.

Figma PropertySwiftUICompose
orientation orientation: EBVoucherOrientation
state state: EBVoucherState
asset (boolean, raster frozen) Image Slot trailing closure
"10% off" + "35% off" Badges discount on Voucher Asset EBVoucherImageFrame(discount: "35% off")
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?
badges (boolean, row of 4 hardcoded) badges Slot badges: [EBBadge]
onTap: () -> Void
Criteria Scorecard
ID Criterion Status Notes
C1 Layer Structure & Naming Requires Rework Two discount Badge instances ("10% off" + "35% off") stacked at the same anchor inside the Voucher Asset frame. Text layers are unnamed. Paste Image Here is a generic placeholder layer name.
C2 Variant & Property Naming Requires Rework 6 booleans where most should be strings (title, price, validity) or a Slot (badges, image). badges boolean toggles a fixed row of 4 hardcoded badges. All content is frozen placeholder.
C3 Token Coverage Ready Title, description, amount, strikethrough amount, and metadata are all bound to main/vouchers/color/default/*. Card elevation uses app/shadow/shadow-low. 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. 6 booleans with frozen strings and a raster hero have no native analog.
C5 Interaction State Coverage Requires Rework No state axis at all. Voucher Card Horizontal ships Default/Limited/Expiring/Used/Expired; Horizontal Voucher has none. No pressed/focused/disabled on the card frame either.
C6 Asset & Icon Quality Requires Rework Hero image is a raster photograph with the "GrabFood" wordmark burned into the pixels. Discount amount is baked into stacked Badge instances, not a property.
C7 Code Connect Linkability Requires Rework Cannot map. Frozen strings, row-level badge toggle, stacked discount badges, and raster hero 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 6 boolean property toggles on the lone instance.

Node IDNameDimensionsProperty toggles
5121:4533Horizontal Voucher336 × 265 (with all properties on)amount, asset, badges, description, header, validityPeriod — all boolean, all default true
1.0.0 — April 2026Major
Initial Assessment · node 5121:4533
Assessed with Consolidate verdict. Single symbol with no variants, 6 boolean toggles, hardcoded content, raster hero image, and two stacked discount Badges. Parallel to Vertical Voucher (5119:1635) and Voucher Card Horizontal (5119:1786). Open
Design Decision
Proposed family-level merge. Collapse the 3 voucher components into one Voucher 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
Design Decision