A full-frame empty-state pattern — illustration or icon, title, description, and optional CTA.
color=white/grey blue → style=default/subtle to match token naming. Replace icon and asset placeholders with Figma Slots. Resulting prop set: style, title, description, optional slots for icon / asset / action.Contexts are illustrative. Final screens will reference actual GCash patterns. Empty State fills a surface where content would normally sit — empty transaction lists, no search results, first-run tabs.
color="white" / color="grey blue" (space in value) doesn't match token namespace default / subtle. Two booleans header + header1 are impossible to distinguish. Duplicate top/bottom header surfaces add structural complexity. C2| State | iOS | Android | Figma Property | Notes |
|---|---|---|---|---|
| Default (white) | Yes | Yes | color=white | White bg — use when sitting on a light-blue surface |
| Subtle (grey blue) | Yes | Yes | color=grey blue | Light-blue bg — use when sitting on a white surface |
| Pressed / Disabled | N/A | N/A | — | Display surface — interactivity lives on the child Button. |
- Property values don't match token namespace —
color="white"/color="grey blue"(with space) should bestyle=default/style=subtlematchingmain/empty-state/color/default/*andmain/empty-state/color/subtle/*. C2 - Duplicate
header/header1booleans — unreadable in the Figma property panel. And the underlying structure (top heading+description, then bottom heading+description) is unusual — most empty states have one title+description. C2 - 7 boolean props = 256 prop combinations — many are semantically invalid (e.g.
hasIcon=true+hasAsset=truetogether is redundant). Collapse into meaningful configurations. C2 - Icon is a hardcoded gray circle placeholder — should be a Figma Slot so consumers can drop in any 64 × 64 icon. C6
- Asset is a flat colored rectangle — should be a Figma Slot for the real illustration. C6
- Code Connect CLI mappings not registered. C7
- Collapse to one title + description. Drop the top-heading/bottom-heading duplication — most empty states have a single title/description pair. The
header/header1/topHeading/topDescriptionbooleans all go away. Docs - Rename
color→stylewith valuesdefault/subtleto match token namespace. Clean enum values, no space characters. Rename - Adopt Figma Slots for
icon,asset, andactionIcon slot accepts 64 × 64 icons. Asset slot accepts any 360 × 230 illustration. Action slot accepts any Button configuration (not just primary). Maps cleanly to@ViewBuilder/@Composableslots. Docs - Document "icon vs asset" — both appear to serve the same purpose (visual anchor above the headline). Pick one convention: either icon (compact 64px) OR illustration (full-width 230px), not both simultaneously. Docs
White background — use when the surface behind is dark or tinted. Asset placeholder uses <code>#EEF2F9</code>.
| Role | Token | Token | Value |
|---|---|---|---|
| Default (white) | bg | main/empty-state/color/default/bg | #FFFFFF |
| — | title | main/empty-state/color/default/label-title | #0A2757 |
| — | description | main/empty-state/color/default/description | #6780A9 |
| — | asset placeholder | main/empty-state/color/default/placeholder | #EEF2F9 |
| Subtle (grey blue) | bg | main/empty-state/color/subtle/bg | #F6F9FD |
| — | title | main/empty-state/color/subtle/label-title | #0A2757 |
| — | description | main/empty-state/color/subtle/description | #6780A9 |
| — | asset placeholder | main/empty-state/color/subtle/placeholder | #D7E0EF |
Light blue-grey background (<code>#F6F9FD</code>) — use when the surface behind is white. Asset placeholder uses <code>#D7E0EF</code>.
| Role | Token | Value |
|---|---|---|
| Container width | — | 360px |
| Top padding | — | 16px |
| Bottom padding | space/space-24 | 24px |
| Top header padding | space/space-16 + space/space-24 | 24h / 16b |
| Content padding | space/space-24 | 24h / 16t |
| Content gap (title ↔ description) | — | 10px |
| Button top padding | space/space-24 | 24px |
| Icon slot size | — | 64 × 64 |
| Asset size | — | 360 × 230 |
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:empty-state:1.0.0") }
| Figma Property | SwiftUI | Compose |
|---|---|---|
| color=white/grey blue | style: EBEmptyStateStyle | .ebStyle(.default/.subtle) |
| header1 / topHeading | title: String | title: String |
| topDescription / description | description: String? | description: String? |
| hasIcon + icon placeholder | Figma Slot → ViewBuilder | @ViewBuilder icon |
| hasAsset + asset placeholder | Figma Slot → ViewBuilder | @ViewBuilder asset |
| hasButton + buttonInstance | Figma Slot → ViewBuilder | @ViewBuilder action |
// Empty transaction list — icon + title + description + action EBEmptyState( title: "No transactions yet", description: "Your transactions will show up here.", icon: { Image(systemName: "tray") }, action: { EBButton("Cash In") { /* ... */ } } ) .ebStyle(.default) // Full illustration — asset slot instead of icon EBEmptyState( title: "No favorites added", description: "Tap the heart on any contact to save them here.", asset: { Image("empty-favorites").resizable().scaledToFit() } ) .ebStyle(.subtle)
// Empty transaction list — icon + title + description + action EBEmptyState( title = "No transactions yet", description = "Your transactions will show up here.", style = EBEmptyStateStyle.Default, icon = { Icon(painterResource(R.drawable.tray), contentDescription = null) }, action = { EBButton("Cash In", onClick = { /* ... */ }) } ) // Full illustration — asset slot instead of icon EBEmptyState( title = "No favorites added", description = "Tap the heart on any contact to save them here.", style = EBEmptyStateStyle.Subtle, asset = { Image(painterResource(R.drawable.empty_favorites), contentDescription = null) } )
| Requirement | iOS | Android |
|---|---|---|
| Role | Group as a single accessibility element with combined label | mergeDescendants = true on the container |
| Decorative icon / asset | .accessibilityHidden(true) | contentDescription = null |
| Action button | Separate accessibility element with its own label | Standard Button semantics |
| Live region | Announce when empty state appears (e.g. after filtering returns 0 results) | liveRegion = LiveRegionMode.Polite |
Do
Use for first-run, no-results, and "nothing here yet" surfaces. Always include a primary action when the user can take a step to fill the empty state.
Don't
Use as an error surface — use Inline Message (error type) or a Toast. Empty State assumes the absence of content is expected, not a failure.
Do
Pick either icon or illustration. Don't stack both — the duplication adds visual noise without adding meaning.
Don't
Leave the description blank — a one-line context sentence ("Your transactions will show up here") teaches the user what the feature does.
| ID | Criterion | Status | Notes |
|---|---|---|---|
| C1 | Layer Structure & Naming | Ready | Semantic: header, content, asset-container, button-container, Icon-Slot. |
| C2 | Variant & Property Naming | Requires Rework | Color values don't match tokens; duplicate header/header1; 7 booleans = 256 combos. |
| C3 | Token Coverage | Ready | All colors bound — just mismatched in the property names. |
| C4 | Native Mappability | Ready | VStack / Column with slots — straightforward native builds. |
| C5 | Interaction State Coverage | Ready | Display-only surface. |
| C6 | Asset & Icon Quality | Requires Rework | Icon + asset are placeholders. Should be slots. |
| C7 | Code Connect Linkability | Needs Refinement | Blocked by C2 restructure. |
Boolean props (hasIcon, hasAsset, hasButton, header, header1, topDescription, topHeading) multiply the effective prop combinations to 256. After restructure to slot-based API, this collapses to 2 style variants × optional slots — unlimited configurations without variant explosion.
| color (current) | Proposed style | Node ID |
|---|---|---|
white | default | 27:169326 |
grey blue | subtle | 27:169339 |
color values don't match token namespace (default/subtle). Openheader/header1 booleans + duplicate top/bottom heading surfaces. Open