Design System
Components

Snackbar

A transient midnight pill that confirms an action — a status tile, a message with an optional amount, and an optional button.

Figma description · Snack-barOpen in Figma ↗

A transient, non-blocking overlay that confirms a user action. It appears near the bottom of the viewport, above the current interface, without taking space in the page/container flow.

Use for: Immediate confirmation of a completed action or low-priority outcome — saved, copied, added, removed, settings updated, or an amount applied.

Not for: Persistent, critical, or detailed status, or messages that need a follow-up action — use alert-message instead.

Choosing: Use back-ground=no when the snack bar sits over a calm area of the screen. Use back-ground=yes when it overlays busy, scrolling, or dark content — it adds a blurred gradient scrim behind the pill to keep the message readable.

Rules: Keep copy to one clear outcome. Show one at a time; never stack snack bars. No CTA. Position above persistent bottom controls such as navbar or cta-bar and never overlap them. Never cause layout shift.

Freedom Live 200Renews 12 NovAED 200.00
Data roaming packGCC · 7 daysAED 49.00
Payment receivedAED 60.00
Props
import SwiftUI
import EandTokens

// Snack-bar: midnight pill, r16, min 48 tall, padding 2/8/2/2, gap 10. The mark is a
// 44pt r14 tile on the status tint holding a 24pt filled glyph. Message body/md in
// inverse ink; an optional primary/sm/inverse button sits at the end.
struct Snackbar: View {
  let message: String
  var action: String? = nil
  var body: some View {
    HStack(spacing: 10) {
      Image(systemName: "checkmark.circle.fill").font(.system(size: EandIcon.xl))
        .foregroundColor(EandColor.alertMessageTextInfo)
        .frame(width: 44, height: 44)
        .background(EandColor.statusIndicatorSurfacePositive,
                    in: RoundedRectangle(cornerRadius: EandRadius.radius5))
      Text(message).font(.system(size: EandTypography.bodyMd.size))
        .foregroundColor(EandColor.textDefaultInverse)
      Spacer(minLength: 0)
      if let action { InverseButton(title: action, size: .sm) {} }   // white fill, ink label
    }
    .padding(.vertical, EandSpacing.spacing2xs)
    .padding(.leading, EandSpacing.spacing2xs).padding(.trailing, EandSpacing.sm)
    .frame(minHeight: EandScale.scale48)
    .background(EandColor.surfaceBaseMidnight)
    .clipShape(RoundedRectangle(cornerRadius: EandRadius.radius6))
  }
}

When to use

  • Use to confirm, briefly and without blocking, the result of something the user just did: a payment received, an add-on activated. Use loader while a short process runs.
  • Don't use for status that must stay on the page (use Alert), or for an outcome that deserves its own screen (use AlertModal or PageTitle).

Choosing a status

statusTileGlyph
successstatus-indicator/surface/positivecheck-circle-filled
alertstatus-indicator/surface/warning (amber)warning-filled
warningstatus-indicator/surface/danger (orange)dismiss-filled
info (default)status-indicator/surface/neutralinfo-filled
loaderstatus-indicator/surface/neutralA spinning ring

Figma's alert is the amber step and its warning the orange one. Every V1.2 snack bar carries a status tile; with no status, it shows info.

Anatomy

  • Tile — a 44px status tile at the start.
  • Message — message in body/md, white. aed adds an amount, such as "AED 60.00", in SemiBold 14px right after it.
  • Action — action renders a primary sm inverse Button that calls onAction.
  • Backdrop — backdrop lays a soft gradient and blur behind the pill, so it reads over busy content.
<Snackbar status="success" message="Payment received" aed="AED 60.00" />
<Snackbar status="loader" message="Activating your add-on" />
<Snackbar status="alert" message="Your balance is low" action="Recharge" onAction={recharge} backdrop />

Deprecated

  • tone is now status: positive becomes success, warning becomes alert, danger becomes warning and loading becomes loader. tone="default" still renders the old bare, centred message.
  • subtitle and onDismiss have no V1.2 counterpart; the snack bar has one line and no dismiss control.

Props

PropTypeDefaultDescription
messageReactNode—
action?ReactNode—Label of the primary / sm / inverse button (Figma Show button).
aed?ReactNode—Figma aed-text — an amount after the message, e.g. "AED 60.00".
backdrop?boolean—Figma back-ground=yes: a blurred gradient scrim behind the pill, for busy content.
onAction?(() => void)—
onDismiss?(() => void)—Deprecated. The V1.2 snack bar has no dismiss control.
status?'alert' | 'success' | 'warning' | 'info' | 'loader'—Figma .icon-snackbar-status axis. Takes precedence over tone. Default info.
subtitle?ReactNode—Deprecated. The V1.2 snack bar has no second line.
tone?'default' | 'warning' | 'positive' | 'danger' | 'loading'—Deprecated. Use status. tone="default" still renders the old bare, centred message.

Design

Figma source: Snack-bar — etisalat Consumer App DSL V1.2

  • Pill: surface/base/midnight, 16px radius (border-radius/6), padding 2/8/2/2, at least 48px tall, with a 10px gap that Figma leaves unbound.
  • Tile: 44px at a 14px radius (border-radius/5), padding 6, holding a 24px filled glyph in alert-message/text/info.
  • Message: body/md in text/default/inverse; the amount sits 3px after it.
  • Backdrop: padding 0/16/32/16 and a 15% gradient from #3f3f3f to transparent, rising from the bottom. Figma's progressive blur (0 to 8) is approximated with a masked 8px blur.

On this page