RestructureRequires Rework
Toast Component link

A transient bottom-anchored message used for confirmations and inline alerts; auto-dismisses after a short delay.

Restructure — collapse the family and clean up the axes
Merge Toast + Toast - With Button into one component with an optional action slot. Split the overloaded theme axis into appearance = neutral | destructive | pending + theme = light | dark. Replace Large Label with size = small | base. Replace the Pending placeholder circle with a real spinner instance. Add a dismiss contract (swipe + auto-duration).
In Context

Toasts float over the app screen — not inline with content. Success toasts confirm completed actions ("Transfer sent"), pending toasts acknowledge background work ("Uploading…"), and error toasts surface failures that don't block the flow. They auto-dismiss after ~3 seconds unless swiped.

Live Preview

Add the popup message here

Properties
Type
Theme
With Icon
Large Label
DS Health
Reusable
Pass
Drops into any transient-feedback moment — transfers, uploads, validation errors. Not tied to a specific screen.
Self-contained
Warn
Owns its colors and typography, but the Pending type ships a 16/24 icon-placeholder gray circle instead of a real spinner — consumers can't drop in a live progress indicator without editing the master.
Consistent
Warn
The theme axis mixes appearance (light/dark surface) with semantic status — Error forces theme=default and loses the dark/light choice. Large Label is really a size axis phrased as a content flag.
Composable
Warn
No action slot — a sibling component (Toast - With Button) exists just to add one button. Action should be an optional slot on this component, not a separate family member.
Behavior
State iOS Android Figma Property Notes
Show / auto-dismiss Yes Yes Not modeled Toasts appear on a host overlay and auto-dismiss after a duration (~3s short, ~5s long). Host-screen concern — no visual state variant needed.
Swipe to dismiss N/A N/A Not annotated Standard gesture on both platforms. Not called out in the component spec.
Tap to dismiss N/A N/A Not annotated Pending variants already wrap the container in a button element in the Figma code — but no interaction callback is documented.
Pending spinner animation N/A N/A Gray circle Pending icon is a static gray circle (icon-placeholder) — should be an animated spinner (ProgressView / CircularProgressIndicator).
A11y announcement N/A N/A Not annotated Error toasts should announce as assertive; default/pending as polite. Not spec'd.
Open Issues
  • Two components model one primitive. Toast + Toast - With Button differ only in the presence of an action button. Action belongs on this component as an optional slot, not a separate family member. Doubling the surface area of every future change. C1 · Layer Structure & Naming
  • theme axis overloaded with status. Values are default | light | dark but default is only valid when type=error (it paints the destructive red surface). Real axes are appearance = neutral | destructive | pending × theme = light | dark. Current schema blocks light/dark error variants. C2 · Variant & Property Naming
  • Large Label is a size flag, not a content flag. The two values change padding, font size, and line-height — this is a size axis. Rename to size = small | base (or compact / regular) so the schema reads correctly. C2 · Variant & Property Naming
  • Booleans use yes/no strings. With Icon / Large Label — blocks direct Swift Bool / Kotlin Boolean mapping. C2 · Variant & Property Naming
  • Pending type uses a placeholder icon. 16 × 16 (small) and 24 × 24 (base) gray icon-placeholder circles instead of an animated spinner. No instance of a ProgressView / CircularProgressIndicator — native consumers can't wire up a real loading state. C6 · Asset & Icon Quality
  • No swipe-to-dismiss or auto-duration contract. Standard toast behaviors on both iOS and Android. Neither is annotated in the Figma component spec — engineers have to guess the duration budget and gesture handling. C5 · Interaction State Coverage
  • No native primitive mapping documented. SwiftUI has no first-party toast (pre-iOS 17); Compose uses SnackbarHost + Snackbar. The component doesn't call out either mapping — dev-handoff guessing game. C4 · Native Mappability
  • Code Connect mappings not registered. Blocked on family consolidation and axis cleanup. C7 · Code Connect Linkability
Design Recommendations
  • Consolidate Toast + Toast - With Button. Target schema: EBToast(message, appearance = .neutral | .destructive | .pending, theme = .light | .dark, size = .small | .base, leadingIcon?: Icon, action?: EBToastAction). Remove the With Button component from the family. Family
  • Split theme into appearance + theme. appearance = neutral | destructive | pending controls semantic status + surface palette; theme = light | dark controls the neutral-surface contrast mode. Unlocks light/dark destructive variants and matches every other DS component's mental model. Property
  • Rename Large Label to size = small | base. Matches the actual axis (padding, font size, spacing) and mirrors Button / Alert sizing. Rename
  • Normalize booleans to true/false. With Icon and any remaining flags. Then rename With Icon to leadingIcon once promoted to a Slot. Rename
  • Replace Pending placeholder with a real spinner. Instance-swap a ProgressView / CircularProgressIndicator (or the DS Spinner component when it ships) into the leading-icon slot for appearance=pending. Same slot covers the checkmark for appearance=neutral and the X for appearance=destructive. Asset
  • Promote the leading icon to a swappable Slot. Adopt Figma Slots so consumers can drop in any Icon from the DS icon library. Default slot content per appearance: checkmark / spinner / error glyph. Slot
  • Add an optional action slot. action?: EBToastAction — takes label + callback. Covers the "Undo", "Retry", "View" use cases and replaces the need for Toast - With Button entirely. Slot
  • Document duration + dismiss behavior. Annotate default duration (3s short / 5s long), swipe-to-dismiss, tap-to-dismiss, and the onDismiss callback contract in the component spec. Not a visual variant — a usage note. Docs
  • Document the A11y live-region mapping. Error toasts announce as assertive (UIAccessibility .high / LiveRegionMode.Assertive); default + pending as polite. Spell this out so engineers wire the right roles. A11y
Types
Default
DES DEV

Confirms a completed action — transfer sent, settings saved, upload finished. Default theme places a checkmark glyph on a dark navy surface.

Add the popup message here

Properties
Theme
With Icon
Large Label
Properties
Theme dark
With Icon yes
Large Label yes
Colors
Background #0A2757
Label #FFFFFF
Icon #FFFFFF
Layout
Width 312
Padding 12 × 12
Corner radius 8
Icon size 24 × 24
Typography
Font Proxima Soft Semibold
Style Primary/Label/Light/Small
Size 14 / 14 · +0.25
Default — Colors by Theme

Information toast. Theme axis flips surface + label between Dark (navy) and Light (white).

Role Token Theme · DarkTheme · Light
Surface bg main/toast/default/{theme}/bg #0A2757 #FFFFFF
Border main/toast/default/{theme}/border #E5EBF4 #E5EBF4
Label main/toast/default/{theme}/label #FFFFFF #0A2757
Icon main/toast/default/{theme}/icon #FFFFFF #0A2757
Error
DES DEV

Surfaces a failure that needs the user's attention — failed transfer, invalid input, expired session. Red surface with a leading X glyph.

Add the popup message here

Properties
Theme
With Icon
Large Label
Properties
Theme default
With Icon yes
Large Label yes
Colors
Background #D61B2C
Label #FFFFFF
Icon #FFFFFF
Layout
Width 312
Padding 12 × 12
Corner radius 8
Icon size 24 × 24
Typography
Font Proxima Soft Semibold
Style Primary/Label/Light/Small
Size 14 / 14 · +0.25
Error — Colors

Critical/error toast. Single appearance regardless of theme.

Role Token Default
Surface bg main/toast/error/bg #D61B2C
Border main/toast/error/border #F4C7C9
Label main/toast/error/label #FFFFFF
Icon main/toast/error/icon #FFFFFF
Pending
DES DEV

Acknowledges in-flight work the user kicked off — submitting a form, syncing a balance, processing a payment. A spinner glyph signals the action is still running.

Add the popup message here

Properties
Theme
With Icon
Large Label
Properties
Theme dark
With Icon yes
Large Label yes
Colors
Background #0A2757
Label #FFFFFF
Icon #FFC857
Layout
Width 312
Padding 12 × 12
Corner radius 8
Icon size 24 × 24
Typography
Font Proxima Soft Semibold
Style Primary/Label/Light/Small
Size 14 / 14 · +0.25
Pending — Colors by Theme

In-progress / loading state toast. Same surface palette as Default; spinner replaces the static icon.

Role Token Theme · DarkTheme · Light
Surface bg main/toast/pending/{theme}/bg #0A2757 #FFFFFF
Border main/toast/pending/{theme}/border #E5EBF4 #E5EBF4
Label main/toast/pending/{theme}/label #FFFFFF #0A2757
Spinner main/toast/pending/{theme}/spinner #FFFFFF #0A2757
Property Mapping

The proposed schema collapses Toast + Toast - With Button into one API. Action becomes an optional slot, theme splits into appearance + theme, and Large Label becomes size.

Figma PropertySwiftUICompose
Type: default | pending | error appearance: neutral | pending | destructive appearance: EBToastAppearance
Theme: default | light | dark (overloaded) theme: light | dark (neutral + pending only) .ebToastTheme(.dark)
Large Label: yes | no size: small | base .controlSize(.small / .regular)
With Icon: yes | no leadingIcon?: Icon (slot) leadingIcon: Image?
(implicit) message: String message: String
(separate component) action?: ToastAction action: EBToastAction?
(not modeled) duration: short | long duration: EBToastDuration
(not modeled) onDismiss?: () -> Void onDismiss: (() -> Void)?
Accessibility
RequirementiOSAndroid
Live region — error Post UIAccessibility.Notification.announcement with .high priority on present. Modifier.semantics { liveRegion = LiveRegionMode.Assertive } on the Snackbar container.
Live region — neutral / pending Post announcement with default priority. LiveRegionMode.Polite.
Minimum duration Short ≥ 3s, long ≥ 5s; extend for longer messages per iOS HIG. SnackbarDuration.Short / Long (Material 3 defaults).
Action button label Action slot owns its own accessibilityLabel. Action slot owns its own contentDescription.
Dismiss gesture Swipe horizontally to dismiss; respect reduce-motion for the slide-out animation. Swipe to dismiss built into Snackbar; honor TalkBackUserTouchExplorationEnabled to extend duration.
Criteria Scorecard
ID Criterion Status Notes
C1 Layer Structure & Naming Requires Rework Two components for one primitive — consolidate with Toast - With Button.
C2 Variant & Property Naming Requires Rework theme overloaded with status; Large Label is a size flag; booleans on yes/no.
C3 Token Coverage Ready All colors bound to main/toast/color/{mode}/*. Spacing + typography fully tokenized.
C4 Native Mappability Requires Rework No SwiftUI first-party primitive; Compose has Snackbar. Needs documented mapping + ToastManager pattern.
C5 Interaction State Coverage Requires Rework No auto-duration, swipe, or tap-to-dismiss contract; pending has no animation.
C6 Asset & Icon Quality Requires Rework Pending uses icon-placeholder gray circle instead of a real spinner.
C7 Code Connect Linkability Not Mapped Blocked on family consolidation and axis cleanup.
Variants Inventory (16 total)

Effective axes today: Type (3) × Theme (3, coupled to Type) × With Icon (2) × Large Label (2). Built variants collapse the illegal combinations — Error only pairs with theme=default; Pending only pairs with theme=dark | light + with icon=yes. = 16 built variants.

GroupCountAxes
Default / Dark4withIcon=yes/no × largeLabel=yes/no
Default / Light4withIcon=yes/no × largeLabel=yes/no
Error / Default4withIcon=yes/no × largeLabel=yes/no
Pending / Dark2withIcon=yes (forced) × largeLabel=yes/no
Pending / Light2withIcon=yes (forced) × largeLabel=yes/no
1.0.0 — April 2026Major
Initial Assessment · node 27:53135
Verdict: Restructure — Consolidate with Toast - With Button, split the overloaded theme axis, rename Large Label to size, and replace the Pending placeholder with a real spinner. Open
Schema
C1 — Family duplication — Toast + Toast - With Button model one primitive; merge via optional action slot. Open
C1
C2 — Axis overloadtheme mixes appearance + status; Large Label is a size flag; booleans on yes/no. Open
C2
C6 — Pending placeholder — 16/24 gray icon-placeholder circle; adopt a real spinner instance. Open
C6
C5 — Dismiss + duration — No auto-dismiss, swipe, or tap-to-dismiss documented. Open
C5
C4 — Native mapping — Document ToastManager overlay (iOS) + SnackbarHost wrapper (Android). Open
C4
C7 — Code Connect — Blocked on family consolidation + schema cleanup. Open
C7