Design System
Components

Alert

An inline status message — a tinted box with a status tile, a title, body text and an optional button.

Figma description · alert-messageOpen in Figma ↗

A static, prominent page-level message that communicates the status or outcome of an action, setting, or app condition. It stays in the page/container flow and does not overlay the interface.

Use for: Status tied to nearby content or a whole section — account information, page updates, plan eligibility, applied settings, and action outcomes.

Not for: Transient confirmations or short-lived feedback — use snack-bar instead. Snack-bar is a temporary overlay; alert-message is static and part of the container.

Choosing: Use Stack=no for a single message. Use Stack=yes when two or more alerts apply to the same location at the same time — they share one slot, and the step-count indicator shows how many there are and which one is in view. Set State by meaning: Success for positive activity or change, Warning for caution or attention needed, Alert for a critical issue worth checking, Info for a neutral outcome, Info Midnight for a neutral message that needs more emphasis on a dark surface.

Rules: Place directly in the main page/container flow, adjacent to the content it refers to. Never place inside a section, card, or panel. Show a CTA only when a clear follow-up action is required — one per alert. Do not use Stack for a single message; keep the indicator dot count equal to the number of stacked alerts.

You’re all set
Your request was completed and everything is updated.
Props
import SwiftUI
import EandTokens

// alert-message: padding 8, gap 12, r16 on the status-indicator tint. Mark = 32pt r12
// tile (padding 6) on the status colour with a 16pt white filled glyph. Title title/xs and
// body body/md, both default ink. The action is a primary / sm / inverse button.
struct AlertMessage: View {
  let title: String; let message: String
  var action: String? = nil
  var body: some View {
    HStack(alignment: .center, spacing: EandSpacing.md) {
      Image(systemName: "checkmark.circle.fill").font(.system(size: EandIcon.md))
        .foregroundColor(EandColor.textDefaultInverse)
        .frame(width: EandScale.scale32, height: EandScale.scale32)
        .background(EandColor.statusPositive, in: RoundedRectangle(cornerRadius: EandRadius.radius4))
      VStack(alignment: .leading, spacing: 0) {
        Text(title).font(.system(size: EandTypography.titleXs.size, weight: EandTypography.titleXs.weight))
        Text(message).font(.system(size: EandTypography.bodyMd.size))
      }
      .foregroundColor(EandColor.textDefaultDefault)
      Spacer(minLength: 0)
      if let action { InverseButton(title: action, size: .sm) {} }
    }
    .padding(EandSpacing.sm)
    .background(EandColor.statusIndicatorSurfacePositive)
    .clipShape(RoundedRectangle(cornerRadius: EandRadius.radius6))
  }
}

When to use

  • Use for status that belongs to a place in the page and stays there: a plan about to expire, a payment that failed, a note about a service. One call to action per alert.
  • Don't use for a passing confirmation (use Snackbar), for the outcome of a flow (use PageTitle or AlertModal), or for form validation (use the Input error state).

Choosing a status

statusSurfaceUse for
successstatus-indicator/surface/positiveSomething completed
alertstatus-indicator/surface/warning (amber)Needs attention soon
warningstatus-indicator/surface/danger (orange)A problem to resolve
info (default)status-indicator/surface/neutralNeutral information
info-midnightalert-message/surface/midnightInformation on dark screens

Figma's alert is the amber step and its warning the orange one. V1.2 has no red alert.

Anatomy

  • Tile — a 32px tile in the status colour, holding a 16px white filled glyph.
  • Text — title in title/xs and children in body/md. Both use the default ink on every status except info-midnight, which is white.
  • Action — action renders a primary sm inverse Button that calls onAction. actionPlacement="below" moves it under the text, for a body that runs to several lines.
  • Stack — when several alerts share one slot, stack (the count) and stackIndex (the one in view, from 0) draw a vertical step counter beside the box.
<Alert status="alert" title="Your plan renews in 3 days" action="Review" onAction={review}>
  AED 250 will be charged to your card.
</Alert>

<Alert status="info" stack={3} stackIndex={0}>Roaming is on for this trip.</Alert>

Deprecated

tone is now status: positive becomes success, warning becomes alert, danger becomes warning and default becomes info.

Props

PropTypeDefaultDescription
action?ReactNode—Label of the primary / sm / inverse button. One CTA per alert.
actionPlacement?'end' | 'below'endDefault end. Use below when the body runs to several lines.
onAction?(() => void)—
stack?number—Figma Stack=yes: how many alerts share this slot (2+ draws the step counter).
stackIndex?number0Which stacked alert is in view, 0-based.
status?'alert' | 'success' | 'warning' | 'info' | 'info-midnight'—Figma State axis. Takes precedence over tone.
title?ReactNode—
tone?'default' | 'warning' | 'positive' | 'danger'—Deprecated. Use status; warning maps to alert and danger to warning.

Design

Figma source: alert-message — etisalat Consumer App DSL V1.2

  • Box: padding 8 (spacing/sm), gap 12 (spacing/md), 16px radius (border-radius/6).
  • Tile: 32px at a 12px radius (border-radius/4), padding 6, on status/positive, status/warning, status/danger or status/default; info-midnight uses surface/glass/white/md.
  • Text: title/xs and body/md in text/default/default, or text/default/inverse on info-midnight. The ink no longer follows the status.
  • Step counter: 5px dots on midnight/400, 4px apart; the dot in view is 5 × 12 with a midnight head.

On this page