A persistent status surface with intent, title, description, and an optional action — in Card or Banner style. 30 variants across Type (Neutral / Information / Warning / Error / Success) × Style (Card / Banner) × Content (Default / Header Only / Description Only), with a Leading Container icon slot and a Dismiss Container slot.
Style=Card / Banner is now an explicit axis (was hidden behind a Full Width boolean), the yes/no booleans collapsed into a clean Type × Style × Content matrix, Type=Default became Neutral, the left icon is a swappable Leading Container slot, and a dismiss slot plus a real action-button instance shipped. v2.1 finished the naming — #text → #description across all 20 description nodes, and Trailing Element → Dismiss Container across all 30 variants. Only the A11y live-region docs and Code Connect remain.Alerts sit inline in forms, payment flows, and detail screens to communicate status, validation, or supplementary guidance. The accent-card style is often used for onboarding tips; the banner style is used for transient validation.
Type × Style × Content — a complete 30-variant matrix, and Type=Default renamed Neutral. Internal naming now matches: the description node is #description, and the paired slots read Leading Container / Dismiss Container.Leading Container icon slot in both styles, a Dismiss Container holding a Content slot, and an action-button instance — consumers compose an icon, an action, and a dismiss without editing the master.| State | iOS | Android | Figma Property | Notes |
|---|---|---|---|---|
| Intent | Yes | Yes | Type=Neutral / Information / Warning / Error / Success | Five intents drive background, border/accent, and icon color. Neutral is the no-charge appearance (renamed from the old Default). |
| Card style | Yes | Yes | Style=Card | Bordered rounded card (radius 4) with a leading icon slot, action button, and trailing dismiss slot. |
| Banner style | Yes | Yes | Style=Banner | Flat inline surface with a 6px Left Border Accent instead of a full border. |
| Content composition | Yes | Yes | Content=Default / Header Only / Description Only | Default shows title + description; the other two drop one. Composes with every Type and Style. |
| Action tap | Yes | Yes | Button instance | The "Learn more" action is a real button instance with its own states, plus a chevron slot — no longer drawn in-place. |
| Dismiss | Yes | Yes | Dismiss Container (Content slot) | The trailing slot carries the dismiss / close affordance. |
| A11y announcement | N/A | N/A | Not annotated | Error alerts should announce as role="alert" / LiveRegion.Assertive, informational as role="status" / LiveRegion.Polite. Still to document. |
- A11y live-region mapping not documented. Error alerts should announce assertively, informational alerts politely. Not yet annotated on the component, so engineers have no spec for the correct roles. C7 · Code Connect Linkability
- Code Connect mappings not registered. Structure and naming are settled enough to register. Blocked only on the SwiftUI / Compose mappings being wired and the native component existing — snippets remain a Planned API. C7 · Code Connect Linkability
- v2.0: Boolean properties eliminated — the old yes/no
Full Width/Left Icon/Right Icon/Descriptionbooleans (with theNo/nocasing bug) collapsed into a cleanType×Style×Contentenum matrix. (C2) - v2.0: The Card-vs-Banner distinction is now an explicit
Styleaxis rather than being hidden behind aFull Widthboolean — Card is the bordered accent surface, Banner the flat inline strip with a left accent. (C1) - v2.0:
Type=DefaultrenamedNeutral— no longer conflated with "the default/unset value", and consistent with the semantic siblings. (C2) - v2.0: Left-icon placeholder replaced with a real
Leading ContainerSLOT (32 × 32) in both Card and Banner, so consumers swap in any DS icon. (C6) - v2.0: Dismiss contract added — a
Trailing Elementwrapping aContentslot carries the close affordance, covering the previously-missing dismissable pattern. (C5) - v2.0: The "Learn more" action is now a real button instance (with a chevron slot) rather than drawn text + chevron, so it carries its own states and its copy is swappable. (C5)
- v2.1: Description text node renamed
#text→#descriptionacross all 20 variants that carry one — Card and Banner, Default and Description Only. Verified by a full text-node rescan with zero#textremaining. (C2) - v2.1: Trailing dismiss wrapper renamed
Trailing Element→Dismiss Containeracross all 30 variants, pairing cleanly withLeading Container.Dismisswas chosen overTrailing Containerdeliberately: the nestedButton_Newalready exposes its ownTrailing Containerslot, so reusing that name would have put two identically-named layers in one variant. (C2) - v2.1: Component moved into the Sticker Sheets v2 library; the assessment now points at the canonical node rather than the 2026 Working File. (C1)
- v2.1: The
Button_Newaction instance is intentional — reviewed and confirmed. It is a real Button component slotted into the Alert, not a placeholder or copy-paste artifact, so its name belongs to that component rather than to Alert. Not an Alert defect. (C1)
- Document the A11y live-region mapping. Spell out assertive for error, polite for informational, so engineers wire
role="alert"/role="status"correctly. A11y - Register Code Connect mapping to
EBAlert. WireType,Style, andContentto the SwiftUI / Compose API, and map theLeading Containerand trailing dismiss slots to native content slots. Docs
- Normalize boolean values and casing. v2.0: Applied — the yes/no booleans are gone entirely, replaced by three Title Case enums. The
No/nocasing bug no longer exists. Rename - Expose
style = banner | card. v2.0: Applied —Style=Card / Banneris a real axis; the layout difference is no longer hidden behind width. Property - Rename
Type=DefaulttoNeutral. v2.0: Applied. Rename - Replace the left-icon placeholder with a swappable Icon slot. v2.0: Applied —
Leading ContainerSLOT in both styles. Slot - Add a dismissable variant. v2.0: Applied — the
Trailing Element/Contentslot carries the dismiss affordance. State - Promote the Learn More action to a button instance. v2.0: Applied — it is now a real button instance with its own states, rather than drawn in-place. (Naming cleanup pending — see the
Button_Newopen issue.) Composition - Rename
#text→#description. v2.1: Applied — all 20 description nodes, verified by rescan. Rename - Align the paired slot names. v2.1: Applied as
Leading Container/Dismiss Container— avoiding a collision with the Button's own nestedTrailing Containerslot. Rename - Give the action button a semantic name. v2.1: Reviewed and closed as not needed —
Button_Newis a real Button component slotted into the Alert, so the name is owned by that component. Rename
Flat inline banner. 360 wide, 12 × 16 padding, 4px radius, soft shadow. Optional left icon, right icon, and description.
Each type ships its own bg, title, description, and icon tokens. Accent-card style adds a border-accent token matching the icon color.
| Role | Token | Token | Value |
|---|---|---|---|
| Information | bg | main/alert/color/information/bg | #E5F1FF |
| — | title | main/alert/color/information/label-title | #072592 |
| — | description | main/alert/color/information/description | #072592 @ 80% |
| — | icon / accent | main/alert/color/information/icon | #2340A9 |
| Warning | bg | main/alert/color/warning/bg | #FFF9EB |
| — | title | main/alert/color/warning/label-title | #6C5009 |
| — | description | main/alert/color/warning/description | #6C5009 @ 80% |
| — | icon / accent | main/alert/color/warning/icon | #966F0B |
| Error | bg | main/alert/color/error/bg | #FEECEB |
| — | title | main/alert/color/error/label-title | #5F1410 |
| — | description | main/alert/color/error/description | #5F1410 @ 80% |
| — | icon / accent | main/alert/color/error/icon | #B0231C |
| Success | bg | main/alert/color/success/bg | #E4F7ED |
| — | title | main/alert/color/success/label-title | #0B3E23 |
| — | description | main/alert/color/success/description | #0B3E23 @ 80% |
| — | icon / accent | main/alert/color/success/icon | #188A47 |
| Neutral | bg | main/alert/color/neutral/bg | #F4F6FA |
| — | title | main/alert/color/neutral/label-title | #0A2757 |
| — | description | main/alert/color/neutral/description | #0A2757 @ 80% |
| — | icon / accent | main/alert/color/neutral/icon | #6780A9 |
Card with a 6px left-border accent. Always ships a right icon + Learn More action + description. Title is larger (18 / 23) than the banner.
| Figma Property | SwiftUI | Compose |
|---|---|---|
Type: Default | Information | Warning | Error | Success | type: neutral | information | warning | error | success | type: EBAlertType |
Full Width: yes | No | style: banner | card | .ebAlertStyle(.banner) modifier |
Left Icon: yes | no | leadingIcon?: Icon (slot) | leadingIcon: Image? |
Right Icon: yes | no | trailingIcon?: Icon (slot, auto for semantic types) | trailingIcon: Image? |
Description: yes | no | description?: String | description: String? |
| (implicit) | title: String | title: String |
| (not modeled) | action?: TextButton (card only) | action: EBTextButton? |
| (not modeled) | onDismiss?: () -> Void | onDismiss: (() -> Void)? |
| Requirement | iOS | Android |
|---|---|---|
| Live region — error | Post UIAccessibility.Notification.announcement with .high priority on mount. | Modifier.semantics { liveRegion = LiveRegionMode.Assertive } on the container. |
| Live region — info / success | Post announcement with default priority. | LiveRegionMode.Polite on the container. |
| Action label | Text Button inside action slot owns its own label + hint. | Text Button inside action slot owns its own contentDescription. |
| Dismiss button | Icon Button with accessibilityLabel: "Dismiss". | Icon Button with contentDescription = "Dismiss". |
| Color contrast | All title/description colors on their type-surface tested to ≥4.5:1. Verified in variable defs. | Same ratios apply. |
| ID | Criterion | Status | Notes |
|---|---|---|---|
| C1 | Layer Structure & Naming | Needs Refinement | Two layouts (banner + card) hidden behind Full Width — rename to style or split. |
| C2 | Variant & Property Naming | Requires Rework | Booleans yes/no with inconsistent casing; Type=Default mixes with semantic types. |
| C3 | Token Coverage | Ready | All 5 types fully tokenized under main/alert/color/*. |
| C4 | Native Mappability | Needs Refinement | Maps cleanly to a custom EBAlert view / composable once schema cleans up. |
| C5 | Interaction State Coverage | Needs Refinement | No dismiss state; Learn More isn't a real button — no pressed coverage. |
| C6 | Asset & Icon Quality | Needs Refinement | Left-icon slot is a placeholder circle — adopt a Figma Slot. |
| C7 | Code Connect Linkability | Not Mapped | Blocked until schema cleanup + slot adoption land. |
Type (5) × layout combos = 20 built variants out of 24 × 5 = 80 theoretical combinations.
| Group | Count | Axes |
|---|---|---|
| Accent card | 4 | fullWidth=No, L=no, R=yes, desc=yes · Information / Warning / Error / Success |
| Banner — right icon, desc | 5 | fullWidth=yes, L=no, R=yes, desc=yes · all 5 types |
| Banner — left icon, desc | 5 | fullWidth=yes, L=yes, R=no, desc=yes · all 5 types |
| Banner — left icon, no desc | 5 | fullWidth=yes, L=yes, R=no, desc=no · all 5 types |
| Default — full width, no icons, with desc | 1 | fullWidth=yes, L=no, R=no, desc=yes · Default only |
yes/no with inconsistent casing; Type=Default mixes with semantic types. OpenfullWidth. Rename to style or split. Openicon-placeholder circle; adopt Figma Slots. Open