Product LayerNot Applicable
Voucher Details Component link

A 336×704 single-instance screen rendering merchant header, voucher content, and optional terms-and-conditions sections.

Product Layer — ship as a screen recipe, not a component
A 336×704 single-instance symbol with no variants is not a DS primitive — it is a screen. DS primitives are reusable across many contexts with meaningful variant axes; Voucher Details exists exactly once and only toggles which optional child subtree renders. The DS should ship the primitives it composes from (EBLogo, EBBadge, EBAccordion, EBListItem) and publish this screen as a recipe in product documentation. The shared "amount + slashed original" row and the dashed strip divider are the only pieces worth extracting — and those belong in a product-layer VoucherAmountRow + TicketDivider, still outside the core DS.
Live Preview
Brand
All branches
Limited
Voucher Title
PHP 200.00
PHP 180.00
Validity: Mar 11 2023 - Mar 14 2023
For every 12 oz or larger beverage purchase, you'll receive an Eco Tumbler Voucher for a FREE Tall Drink when you bring your personal cup with you on your next visit.
Terms & Conditions
Valid from March 11 to 14, 2023. Dine in, Take out, or Drive-thru: 11am until closing, or until supplies last. The promo is not valid in conjunction with other promos or discounts. Metro Manila only.
See full promo mechanics.
Terms & Conditions
Valid from March 11 to 14, 2021
Dine in, Take out, or Drive-thru: 11am until closing, or until supplies last
The promo is not valid in conjunction with other promos or discounts.
Metro Manila only.
Single 336×704 symbol, no variants. Four optional-content booleans: accordion, badge, slashedAmount, tCWithTextLink — all shown on here with their defaults.
DS Health
Reusable
Fail
Not reusable — the component is the voucher-details screen. It has no abstraction; every text string ("Brand", "Voucher Title", "PHP 200.00", "Limited", "All branches", the 4 T&C rows) is baked in. Any consumer must detach to change anything.
Self-contained
Fail
Every meaningful piece — Logo, Badge, Accordion, List Item — is owned by another DS component. What's unique here (the amount row and strip divider) is custom layers, not tokens or logic. The component carries no DS-level behavior of its own.
Consistent
Fail
Schema is 4 booleans that flip child visibility — not states, not variants, not semantic props. Worse, two of them (tCWithTextLink, accordion) render overlapping content (plain-text T&C vs accordion T&C) in parallel. No real voucher turns both on.
Composable
Warn
The composition of primitives is clean — Logo 40px, Badge, Accordion, and List Item are all instance-swapped correctly and inherit their own tokens. That's exactly why this should be product code, not a DS atom.
Behavior
State iOS Android Figma Property Notes
Container N/A N/A Root frame Screen-level scroll, not a component
Merchant logo N/A N/A Instance of Logo 40px Canonical Logo primitive
"Limited" pill N/A N/A Instance of Badge String is hardcoded today
Amount row N/A N/A Local layer Current amount + slashed original — product-layer concern
Strip divider N/A N/A Raster image fill Should be a stroke, not a raster asset
T&C accordion N/A N/A Instance Canonical Accordion with ForEach of EBListItem
"See full promo mechanics" N/A N/A Inline colored span Needs a real link primitive or product-owned LinkText
Open Issues
  • Screen masquerading as a DS component. A 336×704 single-instance symbol with four optional-content booleans is a screen, not a primitive. DS primitives are reusable across many contexts with meaningful variant axes; this exists exactly once and only toggles which optional child renders. C1 · Layer Structure & Naming
  • Booleans are child-visibility switches, not states. accordion, badge, slashedAmount, tCWithTextLink each mean "render this optional subtree." They are not semantic props (e.g. hasLimitedOffer, hasOriginalPrice) and not behavioral states. 2^4 = 16 possible combinations of which only ~4 are legitimate in real product screens. C2 · Variant & Property Naming
  • Overlapping T&C display paths. tCWithTextLink renders a plain-text Terms & Conditions block with a "See full promo mechanics" link; accordion renders a full Terms & Conditions Accordion with 4 list rows. Both describe the same information and can be toggled on simultaneously. Real screens pick one. C2 · Variant & Property Naming
  • Native handoff is a View/Screen, not a Component. SwiftUI would model this as VoucherDetailsView — a scrollable parent that composes EBLogo, EBBadge, a product-owned amount row, EBAccordion, and EBListItem. There is no value in mapping the screen as a single-symbol Code Connect entry. C4 · Native Mappability
  • Missing interaction states. Voucher details is interactive on mobile — accordion expands/collapses, the "See full promo mechanics" link navigates, the voucher itself may have a primary "Use Voucher" CTA on the real screen. The symbol ships only one static frame and happens to use expanded=yes for the embedded accordion. C5 · Interaction State Coverage
  • Strip divider is a raster image fill. The dashed horizontal line between voucher content and description is rendered as an imported image (imgStrip), not a stroke-dasharray or a vector pattern. It will not scale with density, re-color, or adapt to dark mode. C6 · Asset & Icon Quality
  • Not linkable via Code Connect. A 4-boolean screen symbol cannot map 1:1 to a meaningful native API. Linkability belongs at the primitive level (Logo, Badge, Accordion, ListItem) — each of which already has its own Code Connect track. C7 · Code Connect Linkability
Design Recommendations
  • Retire from the sticker sheet; publish as a product-screen recipe. Move Voucher Details out of the DS file and into a product documentation page titled "Voucher Details Screen". The recipe shows how to compose EBLogo, EBBadge, the amount row, the strip divider, and EBAccordion with a ForEach of EBListItem. The DS owns primitives; product owns screens. Docs
  • Extract the shared amount row into a product-layer component. Current amount + slashed original amount is a genuinely reusable product pattern (appears in every voucher variant and on other commerce screens). Lift it into a VoucherAmountRow(current: "PHP 200.00", original: "PHP 180.00") living in the product library — not the core DS. Composition
  • Replace the raster strip divider with a stroke pattern. The dashed horizontal rule between voucher content and description is rendered as a raster image. Replace it with a stroke-based divider (stroke-dasharray in SVG, Canvas on native) so it scales, retints, and adapts to dark mode without a new asset. Asset
  • Collapse the dual Terms & Conditions paths into one. The symbol ships both a plain-text T&C section and a full accordion T&C section as independent booleans. Pick one pattern for the product — recommendation: keep the accordion (collapsible saves vertical space on small screens) and drop tCWithTextLink entirely, moving the "See full promo mechanics" link into the accordion body or next to the CTA. Composition
  • Promote user-facing strings to properties (if this symbol survives as a product component). If the design team keeps Voucher Details as a product-layer component, hoist "Brand", "All branches", "Voucher Title", "PHP 200.00", "PHP 180.00", validity range, description, and the badge label into named text props so product teams do not detach to change copy. Property
  • Native mapping lives at the primitive level. Document that Code Connect mappings for Voucher Details are not added at the screen level. Each composed primitive — EBLogo, EBBadge, EBAccordion, EBListItem — carries its own mapping. The screen itself ships as a SwiftUI View / Compose screen-level composable inside product code. Docs
Property Mapping

No 1:1 Code Connect mapping — the screen is not a primitive. Each composed primitive maps via its own component. The current Figma booleans correspond to product-level state on the Voucher model, not to component props.

Figma PropertySwiftUICompose
badge voucher.limitedLabel: String? Conditional EBBadge render
slashedAmount voucher.originalAmount: Money? Conditional strikethrough text
tCWithTextLink Drop
accordion voucher.rules: [Rule] EBAccordion + ForEach EBListItem
Criteria Scorecard
ID Criterion Status Notes
C1 Layer Structure & Naming Not Applicable Screen, not a component — layer-naming discipline applies per primitive, not here.
C2 Variant & Property Naming Not Applicable Four boolean visibility switches, no variant axis. Not a schema worth normalising.
C3 Token Coverage Ready Every color resolves to main/vouchers/*, main/badge/*, main/accordion/*, or main/list-item/* tokens from composed primitives.
C4 Native Mappability Not Applicable Maps to a product-layer View/Screen, not a component. No 1:1 DS-to-native handoff.
C5 Interaction State Coverage Not Applicable Interaction lives on primitives (Accordion expand/collapse, link tap). Screen-level state is product concern.
C6 Asset & Icon Quality Requires Rework Strip divider is a raster image fill — should be a stroke pattern.
C7 Code Connect Linkability Not Applicable Not linkable as a unit. Primitives carry their own mappings.
Variants Inventory (1 total)

Single symbol, no variant axes. Four boolean toggles (accordion, badge, slashedAmount, tCWithTextLink) drive optional child subtrees but do not generate variants in the component set.

Node IDDimensionsDefault booleans
5119:5368336 × 704accordion=true, badge=true, slashedAmount=true, tCWithTextLink=true
1.0.0 — April 2026Major
Initial Assessment · node 5119:5368
Assessed as Product Layer. 336×704 single-symbol screen composition with four optional-content booleans — not a DS primitive. Composes canonical Logo 40px, Badge, Accordion, and List Item. Open
Design Decision
Recommendation: retire from the DS file. Ship as a product-screen recipe. Extract the shared amount row + strip divider into product-layer VoucherAmountRow and TicketDivider. Replace the raster strip with a stroke pattern. Drop the tCWithTextLink path to eliminate overlap with the embedded accordion. Open
Design Decision