KeepReady
Ad Space Component link

A container for ads, promos, and sponsored placements. Three versions — Receipt, Banner, and Promo — each built around one swappable asset area.

Keep — rebuilt on a clean three-version shape
All four DS Health traits pass. The old seven-size schema is gone: the component is now three versions on a single Variant setting, each built the same way — Container wrapping a ⤷ AssetSlot and an optional Content block. Layer names share one vocabulary across every version. Media flows through the slot, so no campaign artwork ships inside the design system. Code Connect stays unmapped because the native library doesn't exist yet — a dev-side dependency, not a design gap.
In Context

Each version has a home in the app: Receipt sits inside transaction and receipt flows, Banner runs inline in a feed or content column, and Promo is the dashboard tile that also fills the Ad Carousel rail.

Live Preview
Title
Asset
Header
Description Goes Here
Properties
Variant
Content
#title
#header
#description
DS Health
Reusable
Pass
One shape covers every ad placement — receipt inserts, in-feed banners, and dashboard promo tiles. The asset area is a real slot, so a product team drops in its own media without asking for a new component.
Self-contained
Pass
Ships its own container, text styles, corner radius, and slot placeholder. No campaign artwork lives inside the design system, and nothing about a specific surface is baked in.
Consistent
Pass
All three versions read the same way: Container⤷ AssetSlotContent. Text layers share one vocabulary — #title, #header, #description — so the same name means the same thing everywhere.
Composable
Pass
Drops into the Ad Carousel rail through ⤷ CarouselSlot, and stands alone inline. No sibling component per placement.
Behavior
State iOS Android Figma Property Notes
Variant=Receipt N/A N/A EBAdSpace(.receipt) 300 × 250. Asset only — no text.
Variant=Banner N/A N/A EBAdSpace(.banner) 320 × 262. Carries #title above the asset.
Variant=Promo N/A N/A EBAdSpace(.promo) 224 × 208. Fills the Ad Carousel rail.
⤷ AssetSlot N/A N/A content slot Swappable area for product-supplied media.
Issues
  • The setting holds versions, not sizes. The Size setting was renamed to Variant. Its values — Receipt, Banner, Promo — name where the ad goes, which is what they always described. Size is reserved for XS–XL under the naming guidelines. C2 · Variant & Property Naming
  • All three versions share one anatomy. Receipt used to hang its asset area straight off the root while the other two wrapped theirs. It now has the same Container, so every version reads Container⤷ AssetSlot. The slot was renamed to ⤷ AssetSlot in all three, matching the convention Tooltip uses. C1 · Layer Structure & Naming
  • Text layers no longer contradict their contents. A layer called #label held the text "Title", while a different layer called #title held "Header". They are now #title and #header — each name matches what it holds, in every version. C1 · Layer Structure & Naming
Recommendations
  • Retire the old component in Sticker Sheets v2. This assessment now points at 6507:74166 in the 2026 Working File. The previous component at 18563:9789 is deprecated. Swap the remaining Figma usages, then delete it along with the Placeholder Banner and Promo Cards Images asset libraries once zero usage is confirmed. Family
  • Ship imagery as product assets, not design system assets. Product teams export their own 1×/2×/3× images and pass them into ⤷ AssetSlot. The design system ships the container, type styles, radius, and slot placeholder — never the artwork. Asset
  • Revisit whether the carousel container should stay ad-specific. Ad Carousel is a title, an optional button, and a rail of cards — nothing in it is about ads. Swap Ad Space for a Carousel Card and it becomes the dashboard rail. Keeping it ad-specific was a deliberate call this pass, to avoid a name collision with Carousel Card and Carousel Item. Worth revisiting when the Carousel family is reviewed. Family
  • Propose a main/ad-space/color/* token namespace. Ship main/ad-space/color/surface, main/ad-space/color/title, main/ad-space/color/header, and main/ad-space/color/description. A dedicated namespace makes dark mode and partner-branded surfaces tractable instead of inheriting generic background tokens. Token
  • Bake impression and tap tracking into the native component. The iOS view and Android composable should emit onImpression (50% visible for at least one second) and onTap. Document the contract in the Code tab so every consumer team wires analytics the same way. Docs
  • Treat ads as labeled buttons, not decorative images. Every Ad Space is tappable and leads somewhere, so the whole surface should expose one accessibility label built from #header and #description, plus an "Advertisement" trait to meet App Store and Play Store disclosure norms. A11y
  • Watch the Banner title override inside the carousel. Banner carries #title above the asset, Promo has only #header and #description, and Receipt has no text. Inside Ad Carousel the Banner title is switched off on each copy so it doesn't repeat the rail heading. That is a per-copy override rather than a property, so a designer who swaps the copy gets the title back. A hasTitle boolean would remove the risk if it proves annoying in practice. Slot
  • See siblings: Ad Carousel wraps this component in a scrolling rail. Keep the asset slot and placeholder treatment aligned with Carousel Card as the Carousel family is reviewed. Family
Versions
Receipt
DES DEV

Asset only, no text. Sits inside transaction and receipt flows where the surrounding screen already supplies the context.

Asset
Properties
⤷ AssetSlot
Properties
Variant Receipt
⤷ AssetSlot Slot Block placeholder
#title
#header / #description
Colors
Surface #FFFFFF
Slot placeholder #9F3DFB
Layout
Dimensions 300 × 250
⤷ AssetSlot 300 × 250
Corner radius 4
Padding 0 — asset fills the container
Typography
Text layers none
Receipt — Colors

Asset only. The purple slot placeholder is an authoring aid and never renders in product.

Role Token Default
Surface bg/color-bg-main #FFFFFF
Banner
DES DEV

The widest version. Carries #title above the asset and a #header + #description block beneath. Inside the Ad Carousel rail the title is switched off so it doesn't repeat the rail heading.

Title
Asset
Header
Description Goes Here
Properties
⤷ AssetSlot
Properties
Variant Banner
⤷ AssetSlot Slot Block placeholder
#title Title
#header Header
#description Description Goes Here
Colors
Surface #FFFFFF
#title #072592
#header #005CE5
#description #445C85
Layout
Dimensions 320 × 262
#title row 320 × 16
Title to Container 16
⤷ AssetSlot 320 × 174
Asset to Content 16
Content block 320 × 40
Corner radius 4
Typography
#title style Primary/Bold/Heading
#title font Proxima Soft Bold · 18 / 18 · +0.25
#header font Proxima Soft Bold · 18 / 18 · +0.25
#description font BarkAda SemiBold · 12 / 18 · 0
Banner — Colors

Three text roles. #title and #header share a size and weight but not a colour.

Role Token Default
Surface bg/color-bg-main #FFFFFF
#title text/color-text-heading #072592
#header text/color-text-link #005CE5
#description text/color-text-body #445C85
Promo
DES DEV

The dashboard tile, and the default card inside the Ad Carousel rail. Same Content block as Banner, without the title above the asset.

Asset
Header
Description Goes Here
Properties
⤷ AssetSlot
Properties
Variant Promo
⤷ AssetSlot Slot Block placeholder
#title
#header Header
#description Description Goes Here
Colors
Surface #FFFFFF
#header #005CE5
#description #445C85
Layout
Dimensions 224 × 208
⤷ AssetSlot 224 × 152
Asset to Content 16
Content block 224 × 40
Corner radius 4
Peek inside Ad Carousel 96 of the next card
Typography
#header style Primary/Bold/Heading
#header font Proxima Soft Bold · 18 / 18 · +0.25
#description font BarkAda SemiBold · 12 / 18 · 0
Promo — Colors

Same palette as Banner, minus the title role.

Role Token Default
Surface bg/color-bg-main #FFFFFF
#header text/color-text-link #005CE5
#description text/color-text-body #445C85
Installation Planned API

Swift Package Manager

.package(url: "https://github.com/gcash/east-blue-ios", from: "1.0.0")

Gradle

implementation("com.gcash.eastblue:components:1.0.0")

Planned API — the native library does not exist yet. Snippets show the intended shape, not shipped code.

Property Mapping

Figma properties mapped to the intended native parameters.

Figma PropertySwiftUICompose
Variant AdSpaceVariant (.receipt / .banner / .promo) variant: AdSpaceVariant
⤷ AssetSlot @ViewBuilder content: () -> Content content: @Composable BoxScope.() -> Unit
#title title: String? (Banner only) title: String? (Banner only)
#header header: String? header: String?
#description description: String? description: String?
Usage Snippets Planned API
Receipt — asset only
EBAdSpace(.receipt) {
    Image(ad.creative).resizable()
}
EBAdSpace(variant = AdSpaceVariant.Receipt) {
    AsyncImage(model = ad.creative, contentDescription = null)
}
Banner — title above, text beneath
EBAdSpace(
    .banner,
    title: "Sponsored",
    header: ad.headline,
    description: ad.blurb
) { Image(ad.creative).resizable() }
EBAdSpace(
    variant = AdSpaceVariant.Banner,
    title = "Sponsored",
    header = ad.headline,
    description = ad.blurb
) { AsyncImage(ad.creative, null) }
Promo — inside an Ad Carousel rail
EBAdCarousel(title: "Sponsored") {
    ForEach(ads) { ad in
        EBAdSpace(.promo, header: ad.headline) { Image(ad.creative) }
    }
}
EBAdCarousel(title = "Sponsored") {
    ads.forEach { ad ->
        EBAdSpace(AdSpaceVariant.Promo, header = ad.headline) { AsyncImage(ad.creative, null) }
    }
}
Accessibility
RequirementiOSAndroid
The whole card is one tappable element .accessibilityElement(children: .combine) with a single .isButton trait Modifier.clickable on the container, children marked clearAndSetSemantics
Disclosed as advertising .accessibilityHint("Advertisement") contentDescription prefixed with "Advertisement"
Label built from the text layers #header then #description, joined Same order in contentDescription
Asset is not announced separately .accessibilityHidden(true) on the image contentDescription = null on the image
Usage Guidelines

Do

Pass campaign artwork into ⤷ AssetSlot from the product's own asset pipeline.

Don't

Don't add campaign images to the design system library.

Do

Use Promo inside an Ad Carousel when the rail should read as scrollable.

Don't

Don't expect a peek from Banner in a rail; at 320 wide it fills the shell by design.

Do

Let Receipt carry no text where the surrounding screen already gives context.

Don't

Don't force a header onto Receipt by detaching the copy.

Criteria Scorecard
ID Criterion Status Notes
C1 Layer Structure & Naming Ready All three versions read Container⤷ AssetSlot. Text layers renamed so each name matches its contents.
C2 Variant & Property Naming Ready Size renamed to Variant; values name the placement, which is what they always described.
C3 Token Coverage Needs Refinement Colours are attested as token-bound but were not verifiable with read-only tools. A main/ad-space/color/* namespace is proposed.
C4 Native Mappability Ready A container with an image slot and two optional text rows maps directly to both platforms.
C5 Interaction State Coverage Not Applicable Display-only surface — confirmed by design. Tap handling belongs to the host.
C6 Asset & Icon Quality Ready No raster ships inside the component. The Slot Block placeholder is the standard authoring aid.
C7 Code Connect Linkability Not Mapped Blocked — the native library does not exist yet.
Code Connect
Aspect Status Notes
Property naming Ready Variant (3 values), ⤷ AssetSlot (slot), and three text layers map one to one.
Token coverage Needs Refinement Text colours need a Dev Mode check before mapping.
Registration Not Mapped Blocked until the native library exists.
Variants Inventory (3 total)

1 Variant setting × 3 values = 3 versions. Content is supplied through the slot and the text layers, not through extra versions.

VariantSizeText layersNode
Receipt300 × 250none6518:74485
Banner320 × 262#title · #header · #description5703:38546
Promo224 × 208#header · #description6528:77243
2.0.0 — August 2026Major
Rebuilt in the 2026 Working File — node 6507:74166
Seven sizes became three versions. The banner-smhero-md enum is gone. The component is now Variant = Receipt | Banner | Promo on a new node in the 2026 Working File. The previous component at 18563:9789 in Sticker Sheets v2 is deprecated. Rebuilt
Family
C2 — Size renamed to Variant. The values name where the ad goes rather than how big it is, so Size is freed for its XS–XL meaning under the naming guidelines. Resolved
C2 resolved
C1 — one anatomy across all three versions. Receipt gained the Container wrapper the other two already had, and the slot was renamed ⤷ AssetSlot everywhere. Resolved
C1 resolved
C1 — text layers renamed. #label (holding "Title") became #title, and the old #title (holding "Header") became #header, in every version. Resolved
C1 resolved
isLoading and the caption removed. Neither exists on the rebuilt component. The skeleton treatment and the optional caption string documented against the old seven-size schema no longer apply. Removed
Property
C3 — token binding attested, not verified. Text colours are reported as bound to colour styles, but the read-only tools used for this assessment return raw hex without exposing bindings. Needs a Dev Mode confirmation.
C3 partial
New sibling: Ad Carousel. The rail that wraps this component is now assessed as its own page under the Ad Space group.
Family
1.0.0 — April 2026Major
Canonical consolidation — node 18563:9789
Consolidates Ads On Receipt, Ad Space - Group - Large, Dashboard Promo Cards — 3 source components (5 total with the Placeholder Banner and Promo Cards Images asset libraries) collapse into a single Ad Space with a 7-value size enum grouped into three families: banner (IAB / AdMob), promo (dashboard tile), hero (full-width). Initial
Family
C1 — Component splintering resolved — Ads On Receipt (18563:9789), Ad Space - Group - Large (18563:9808), and Dashboard Promo Cards (18563:9917) merged into one component. Legacy components marked for deletion post-adoption. Resolved
C1
C2 — hifi/midfi fidelity axis retired — Legacy type=hifi | midfi was a placeholder-authoring crutch, not a runtime variant. Replaced with an orthogonal isLoading boolean. Content flows through the content slot regardless of state. Resolved
C2
C4 — carousel=yes pseudo-variant retired — The legacy "carousel preview" variant was a static 3-card Figma layout, not a runtime carousel. Multi-ad rails are now authored by composing multiple AdSpace size="hero-md" instances inside the DS EBCarousel. Resolved
C4
C6 — Placeholder asset libraries retired — Placeholder Banner (18563:9937, 8 variants) and Promo Cards Images (18563:9928) no longer ship. Media flows through the content slot; product teams provide imagery from their own asset pipeline. Resolved
C6
C7 — 1:1 native mappingbanner-* sizes map to GADBannerView / AdView. promo-* / hero-* map to a single EBAdSpace view/composable. Clean enum, boolean, string, slot signatures ready for Code Connect CLI registration. Resolved
C7
Token namespace proposedmain/ad-space/color/surface, main/ad-space/color/caption, main/ad-space/color/loading-skeleton. Replaces ad-hoc use of generic surface tokens across the legacy trio. Initial
Tokens
Telemetry contract added — Native component exposes onImpression (50% visible ≥1s) and onTap. AdMob-backed banner-* inherits the SDK's tracking; product-owned promo-* / hero-* wire consumer analytics via the callbacks. Initial
API