Skip to content

Alert Card

Alert cards highlight items requiring attention. They appear on dashboard pages to surface warnings, errors, or action items that need human intervention.

3 barang stok rendah
Perlu reorder sebelum akhir minggu. Cek halaman stok untuk detail lengkap.
Lihat →

Anatomy

+--3px border--+-------------------------------------------+
|              | [Icon]  Title (14px, semibold)             |
|  (left       |         Description (13px, text-2)         |
|   border)    |                                            |
+--------------+-------------------------------------------+
  • Left border: 3px solid, color matches severity
  • Background: soft variant of the severity color
  • Icon: Lucide icon, 20px, severity color
  • Title: 14px, weight 600, text-1
  • Description: 13px, text-2
  • Padding: 12px 16px
  • Border radius: 8px

Severity Variants

SeverityBackgroundBorderIcon ColorIcon
Warning (amber)#FEF3C7#D4910A#92400EAlertTriangle
Error (red)#FCEAE8#C4463A#9B1C1CAlertCircle
Info (blue)#DBEAFE#2563EB#1E40AFInfo
Success (green)#E8F0EC#2D6B4A#166534CheckCircle

Usage

AppContext
store-adminAction items on dashboard (cash variance, missing deposits)
stock-app-webLow stock warnings, overdue opname reminders
ho-financeUnreconciled transactions, pending approvals

React Component

tsx
import { AlertTriangle, AlertCircle, Info, CheckCircle, type LucideIcon } from 'lucide-react'

type Severity = 'warning' | 'error' | 'info' | 'success'

const config: Record<Severity, { bg: string; border: string; icon: LucideIcon; iconColor: string }> = {
  warning: { bg: 'bg-amber-50', border: 'border-l-amber-500', icon: AlertTriangle, iconColor: 'text-amber-800' },
  error:   { bg: 'bg-red-50',   border: 'border-l-red-500',   icon: AlertCircle,   iconColor: 'text-red-800' },
  info:    { bg: 'bg-blue-50',  border: 'border-l-blue-500',  icon: Info,           iconColor: 'text-blue-800' },
  success: { bg: 'bg-green-50', border: 'border-l-green-700', icon: CheckCircle,    iconColor: 'text-green-800' },
}

interface AlertCardProps {
  severity: Severity
  title: string
  description?: string
  action?: { label: string; onClick: () => void }
}

export function AlertCard({ severity, title, description, action }: AlertCardProps) {
  const c = config[severity]
  const Icon = c.icon

  return (
    <div className={cn('flex items-start gap-3 p-3 rounded-lg border-l-[3px]', c.bg, c.border)}>
      <Icon className={cn('w-5 h-5 mt-0.5 shrink-0', c.iconColor)} />
      <div className="flex-1 min-w-0">
        <p className="text-sm font-semibold text-1">{title}</p>
        {description && <p className="text-[13px] text-2 mt-0.5">{description}</p>}
      </div>
      {action && (
        <button
          onClick={action.onClick}
          className="text-xs font-semibold text-brand hover:underline shrink-0"
        >
          {action.label}
        </button>
      )}
    </div>
  )
}

Stacking Multiple Alerts

When showing multiple alerts, stack them with 8px gap. Order by severity: error first, then warning, then info.

tsx
<div className="flex flex-col gap-2">
  <AlertCard severity="error" title="Selisih kas Rp 150.000" description="Shift sore kemarin belum ditutup." />
  <AlertCard severity="warning" title="3 barang stok rendah" description="Perlu reorder sebelum akhir minggu." />
</div>

Don't

  • Don't use alert cards for success confirmation after actions --- use toast notifications instead
  • Don't stack more than 4 alert cards --- summarize into a single card with a count
  • Don't use alert cards for informational content that doesn't require action

RetailOS - Sistem ERP Retail Modern untuk Indonesia