FixNeeds Refinement
Visual Popup Component link

An illustrated centered popup used for promos, success moments, and notable announcements.

Open issues remain
Variant naming mixes paradigms — Default / 2 CTA / Version 2 (C2). Hero image is a raster placeholder with "Replace me" overlay instead of a swappable image slot (C6). No destructive/error/loading state coverage (C5). Code Connect mappings not registered (C7).
In Context

Contexts are illustrative. Final screens will reference actual GCash patterns. Visual Popup overlays the app surface to confirm critical actions or onboard users to a new feature.

Hero image Okay
Live Preview
Put the title hereAdd description here.Add description here.Okay
Properties
Type
DS Health
Reusable
Pass
Three layouts cover info modals, confirmation prompts (single + dual CTA), and onboarding popups (Version 2). Fixed 320 / 312 px width fits standard mobile dialog patterns.
Self-contained
Pass
Carries its own bg (main/modal-popup/color/bg), Shadow/Depth 0, radius/radius-2, and 24px padding. Composes Button instances rather than redefining button styles.
Consistent
Warn
Variant naming mixes three paradigms: Default (generic), 2 CTA (count), Version 2 (version). Native enums need a single semantic axis — e.g. single-cta / dual-cta / dismissible. C2
Composable
Pass
All CTAs are real Button instances. Close icon (V2) is a vector instance. Hero image is the only non-component child — see C6.
Behavior
State iOS Android Figma Property Notes
Single CTA Yes Yes Type=Default Hero (180px) + title + description + primary CTA. Use for info or single-action confirm.
Dual CTA Yes Yes Type=2 CTA Adds a secondary outline + tertiary text button below primary. Use for cancel/confirm pairs.
Dismissible (V2) Yes Yes Type=Version 2 Preamble label + title with close icon + content-first layout. Use for onboarding/tutorial popups.
Destructive / Error / Loading N/A N/A No variants for destructive confirms or async/loading states. C5
Open Issues
  • Variant naming mixes paradigms. Default (generic), 2 CTA (count), and Version 2 (version) can't coexist as one enum. Collapse to a single semantic axis: single-cta / dual-cta / dismissible. C2 · Variant & Property Naming
  • No destructive / error / loading state coverage. Engineers must improvise these for "Cancel transaction?", error confirms, and async submit flows. C5 · Interaction State Coverage
  • Hero image is a raster placeholder with "Replace me" overlay. Should be a swappable Image slot (component instance) so product teams override per-popup without editing the master. C6 · Asset & Icon Quality
  • Code Connect mappings not registered. Blocked until the variant naming and asset-slot issues above are resolved. C7 · Code Connect Linkability
Design Recommendations
  • Collapse Type to one semantic enum. Values: single-cta, dual-cta, dismissible. Eliminates the version/count/default mix and maps cleanly to an EBVisualPopupKind enum. Property
  • Replace the raster Modals Asset with a swappable Image slot. A component placeholder that product teams can instance-swap with their illustration — matches the pattern Avatar uses for its image type. Slot
  • Add a destructive mode. Whether as a boolean or a kind=destructive variant — lets destructive confirms (Cancel / Logout / Delete) use red CTAs without bespoke overrides. State
  • Add a loading state for the primary CTA. Async submits in popups currently have no documented affordance — reuse the planned Button loading state rather than invent a new pattern. State
Styles
Default — single primary CTA
DES DEV

Hero image (320 × 180, 16:9) + title + 2-line description + single primary CTA. Use for informational modals or single-action confirms ("Okay").

Properties
CTA label
Properties
Variant Default — single primary CTA
Style Centered illustration popup
CTA label Okay
Colors
Surface #FFFFFF
Title #0A2757
Description #6780A9
Preamble #90A8D0
Close icon #6780A9
Primary CTA bg #005CE5
Layout
Width 320px
Padding 24 horizontal · 24 vertical
Border radius radius/radius-2 (6px)
Illustration height 160px
Typography
Title style Primary/Headlines/Section
Title font Proxima Soft Bold · 22 / 26
Colors by Variant

Modal popup ships display-only color tokens — no pressed/disabled states (the popup itself doesn't have interaction states; CTAs handle that via Button tokens).

Role Token Value
Modal background main/modal-popup/color/bg #FFFFFF
Title label main/modal-popup/color/label #0A2757
Description label main/modal-popup/color/label-primary #6780A9
Preamble (V2) main/modal-popup/color/label-preamble #90A8D0
Close icon (V2) main/modal-popup/color/icon-close #6780A9
V2 inner container bg/color-bg #F6F9FD
2 CTA — primary outline + tertiary text
DES DEV

Same hero + title + description as Default, then a secondary outline button on top of a tertiary text button. Use for confirm/cancel pairs.

Properties
CTA label
Properties
Variant 2 CTA — primary outline + tertiary text
Style Centered illustration popup
CTA label Okay
Colors
Surface #FFFFFF
Title #0A2757
Description #6780A9
Preamble #90A8D0
Close icon #6780A9
Primary CTA bg #005CE5
Layout
Width 320px
Padding 24 horizontal · 24 vertical
Border radius radius/radius-2 (6px)
Illustration height 160px
Typography
Title style Primary/Headlines/Section
Title font Proxima Soft Bold · 22 / 26
Layout
Role Token Value
Default / 2 CTA width 320px
Version 2 width 312px
Hero image (Default / 2 CTA) 320 × 180 (16:9)
Hero image (V2) 280 × 180, 10px radius
Body padding space/space-24 24px
CTA group padding (vertical) space/space-24 24px
2 CTA gap between buttons space/space-8 8px
V2 inner container padding space/space-16 16px h, 16t / 24b
Corner radius radius/radius-2 6px
Shadow Shadow/Depth 0 0 0 4px #E8EEF2C9
Close icon (V2) 24 × 24
Version 2 — preamble + close icon, content-first
DES DEV

Onboarding/tutorial layout. The popup itself is a single light-gray (<code>bg/color-bg</code>) container — preamble label, title with close icon, description, a 280×180 hero image with 10px radius, then primary CTA. (The outer white frame has zero padding, so only the gray container is visible.)

Properties
CTA label
Properties
Variant Version 2 — preamble + close icon, content-first
Style Centered illustration popup
CTA label Okay
Colors
Surface #FFFFFF
Title #0A2757
Description #6780A9
Preamble #90A8D0
Close icon #6780A9
Primary CTA bg #005CE5
Layout
Width 320px
Padding 24 horizontal · 24 vertical
Border radius radius/radius-2 (6px)
Illustration height 160px
Typography
Title style Primary/Headlines/Section
Title font Proxima Soft Bold · 22 / 26
Typography
Role Token Spec
Title Primary/Headlines/Section Proxima Soft Bold · 22 / 26
Description Secondary/Default/Base BarkAda Medium · 14 / 20
Preamble (V2) Primary/Label/Tiny Proxima Soft Bold · 10 / 10 · +0.25
CTA label Primary/Label/Large Proxima Soft Bold · 18 / 18 · +0.25
Installation Planned API

iOS — Swift Package Manager

// In Xcode: File → Add Package Dependencies
"https://github.com/AY-Org/eb-ds-ios"

Android — Gradle (Kotlin DSL)

dependencies {
    implementation("com.eastblue.ds:visual-popup:1.0.0")
}
Property Mapping
Figma PropertySwiftUICompose
Type=Default .ebKind(.singleCTA) kind = EBVisualPopupKind.SingleCTA
Type=2 CTA .ebKind(.dualCTA) kind = EBVisualPopupKind.DualCTA
Type=Version 2 .ebKind(.dismissible) kind = EBVisualPopupKind.Dismissible
Hero image (raster) heroImage: Image heroImage: Painter
CTA buttons primary / secondary / tertiary: EBButton primary / secondary / tertiary: @Composable
SwiftUI
ios/Components/VisualPopup/EBVisualPopup.swift
Jetpack Compose
android/components/visualpopup/EBVisualPopup.kt
Usage Snippets Planned API
Usage
// Default — single CTA
EBVisualPopup(
    title: "Cash In Successful",
    description: "₱500.00 added to your wallet.",
    heroImage: Image("cash-in-success"),
    primary: EBButton("Okay") { /* dismiss */ }
)
.ebKind(.singleCTA)

// 2 CTA — confirm/cancel
EBVisualPopup(
    title: "Cancel transaction?",
    description: "This cannot be undone.",
    heroImage: Image("warning-illustration"),
    primary: EBOutlinedButton("Confirm") { /* confirm */ },
    secondary: EBTextButton("Go Back") { /* dismiss */ }
)
.ebKind(.dualCTA)

// Version 2 — onboarding with close icon
EBVisualPopup(
    preamble: "NEW",
    title: "Save your receipts",
    description: "Tap any transaction to save its receipt.",
    heroImage: Image("receipt-tutorial"),
    primary: EBButton("Got it") { /* dismiss */ },
    onClose: { /* dismiss */ }
)
.ebKind(.dismissible)
// Default — single CTA
EBVisualPopup(
    kind = EBVisualPopupKind.SingleCTA,
    title = "Cash In Successful",
    description = "₱500.00 added to your wallet.",
    heroImage = painterResource(R.drawable.cash_in_success),
    primary = { EBButton("Okay", onClick = { /* dismiss */ }) }
)

// 2 CTA — confirm/cancel
EBVisualPopup(
    kind = EBVisualPopupKind.DualCTA,
    title = "Cancel transaction?",
    description = "This cannot be undone.",
    heroImage = painterResource(R.drawable.warning),
    primary = { EBOutlinedButton("Confirm", onClick = { /* confirm */ }) },
    secondary = { EBTextButton("Go Back", onClick = { /* dismiss */ }) }
)

// Version 2 — onboarding with close icon
EBVisualPopup(
    kind = EBVisualPopupKind.Dismissible,
    preamble = "NEW",
    title = "Save your receipts",
    description = "Tap any transaction to save its receipt.",
    heroImage = painterResource(R.drawable.receipt_tutorial),
    primary = { EBButton("Got it", onClick = { /* dismiss */ }) },
    onClose = { /* dismiss */ }
)
Accessibility
RequirementiOSAndroid
Modal trait / role Present via .sheet or .alert — VoiceOver announces as modal Dialog announces as modal; TalkBack focus trapped inside
Focus trap Automatic with .sheet Automatic with Dialog — set dismissOnClickOutside = false for confirm popups
Close button label (V2) .accessibilityLabel("Close") contentDescription = "Close"
Hero image If decorative: .accessibilityHidden(true). If informative: provide a label. Same — contentDescription = null for decorative, otherwise describe
Tap targets CTAs use Button which meets HIG 44pt CTAs meet Material 48dp
Destructive role Currently undefined — needs role: .destructive when state lands Currently undefined — needs Button destructive colors when state lands
Usage Guidelines

Do

Use Visual Popup for critical confirms, success states with celebration, and onboarding moments — places where the hero image adds emotional weight.

Don't

Use for inline form errors or transient notifications — those belong in Toast, Banner, or inline error patterns, not a blocking modal.

Do

Use the Default variant when the popup has one obvious next step (Okay, Got it, Continue).

Don't

Use 2 CTA when one button is clearly more important than the other — that's still a Default with the secondary action elsewhere.

Do

Use Version 2 (with close icon) only for onboarding/tutorial popups where the user can dismiss without taking action.

Don't

Add a close icon to confirm/destructive popups — forces the user to consciously choose the CTA.

Criteria Scorecard
ID Criterion Status Notes
C1 Layer Structure & Naming Ready Semantic names: Modals Asset, body, header, CTA - Base Button Group, Close.
C2 Variant & Property Naming Requires Rework Property values mix paradigms: Default / 2 CTA / Version 2. Should be one semantic axis.
C3 Token Coverage Ready All colors, spacing, radii, shadow, and typography bound to tokens.
C4 Native Mappability Ready Maps to .sheet / .alert on iOS and Dialog / AlertDialog on Android.
C5 Interaction State Coverage Requires Rework No destructive, error, or loading variants. Close affordance only on Version 2.
C6 Asset & Icon Quality Requires Rework Hero is a flat raster placeholder with "Replace me" overlay. Should be a swappable Image slot.
C7 Code Connect Linkability Needs Refinement No CLI mappings registered yet.
Variants Inventory (3 total)

TypeWidthHeroCTAsNode ID
Default320px320 × 180 (raster)1 primary18477:23789
2 CTA320px320 × 180 (raster)1 outline + 1 text18477:23797
Version 2312px280 × 180 (raster, in container)1 primary + close icon18477:23806
1.0.0 — April 2026Major
Initial Assessment · node 18477:23788
Component assessed — 3 variants (Default / 2 CTA / Version 2). Hero image, title, description, CTA(s). Used for confirms, success states, and onboarding popups. Documented
Initial
Variant naming mixes paradigmsDefault (generic), 2 CTA (count), Version 2 (version). Should be a single semantic axis (single-cta / dual-cta / dismissible). Open
C2 Open
No destructive/error/loading state — Engineers must improvise these for cancel/delete confirms and async submits. Open
C5 Open
Hero image is a raster placeholder — "Replace me" overlay on a flat Modals Asset image. Should be a swappable Image slot via instance swap. Open
C6 Open
Code Connect mappings — No CLI mappings registered yet. Open
C7 Open