Approval Notification

Notification related to approval.

Priya Shah requested approval for Q3 travel expense report

Status: pending

Unread

html

<article class='approval approval--pending' data-read='false' style='border-left-color:#E8A020;'>
  <span class='approval__icon' aria-hidden='true'></span>
  <div class='approval__body'>
    <p class='approval__text'><strong>Priya Shah</strong> requested approval for <strong>Q3 travel expense report</strong></p>
    <p class='approval__status'>Status: <span class='approval__status-label'>pending</span></p>
    <time class='approval__time' datetime='2026-08-15T14:20:00'>2026-08-15T14:20:00</time>
  </div>
  
  <span class='approval__dot' aria-hidden='true'></span>
  <span class='sr-only'>Unread</span>
  
</article>
<style>
.approval { display: flex; align-items: flex-start; gap: 12px; max-width: 420px; padding: 14px 16px; background: #FAF7F2; color: #241430; border-left: 4px solid; border-radius: 10px; box-shadow: 0 6px 18px rgba(36,20,48,.12); font: 14px/1.5 system-ui, sans-serif; position: relative; box-sizing: border-box; }
.approval__icon { width: 22px; height: 22px; border-radius: 50%; flex-shrink: 0; position: relative; background: #24143014; }
.approval__icon::before { position: absolute; inset: 0; display: grid; place-items: center; font: 700 12px/1 system-ui, sans-serif; }
.approval--pending .approval__icon::before { content: '\2026'; color: #E8A020; }
.approval--approved .approval__icon::before { content: '\2713'; color: #1a7a4c; }
.approval--denied .approval__icon::before { content: '\2715'; color: #b0273e; }
.approval__body { flex: 1; }
.approval__text { margin: 0 0 4px; }
.approval__status { margin: 0 0 4px; font-size: 12px; color: #241430b3; }
.approval__status-label { text-transform: capitalize; font-weight: 600; }
.approval__time { display: block; font-size: 11px; color: #24143080; }
.approval__dot { position: absolute; top: 14px; right: 14px; width: 8px; height: 8px; border-radius: 50%; background: #b0273e; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
</style>

tailwind

<div class='approval-tw approval-tw--pending flex items-start gap-3 max-w-[420px] p-3.5 bg-[#FAF7F2] text-[#241430] border-l-4 rounded-lg shadow-md font-sans text-sm relative box-border' data-read='false' style='border-left-color:#E8A020'>
  <span class='approval-tw__icon w-[22px] h-[22px] rounded-full flex-shrink-0 bg-[#24143014] relative' aria-hidden='true'></span>
  <div class='flex-1'>
    <p class='m-0 mb-1'><strong>Priya Shah</strong> requested approval for <strong>Q3 travel expense report</strong></p>
    <p class='m-0 mb-1 text-xs text-[#241430]/70'>Status: <span class='capitalize font-semibold'>pending</span></p>
    <time class='block text-[11px] text-[#241430]/50' datetime='2026-08-15T14:20:00'>2026-08-15T14:20:00</time>
  </div>
  
  <span class='absolute top-3.5 right-3.5 w-2 h-2 rounded-full bg-[#b0273e]' aria-hidden='true'></span>
  <span class='sr-only'>Unread</span>
  
</div>
<style>
.approval-tw__icon::before { position: absolute; inset: 0; display: grid; place-items: center; font: 700 12px/1 system-ui, sans-serif; content: ''; }
.approval-tw--pending .approval-tw__icon::before { content: '\2026'; color: #E8A020; }
.approval-tw--approved .approval-tw__icon::before { content: '\2713'; color: #1a7a4c; }
.approval-tw--denied .approval-tw__icon::before { content: '\2715'; color: #b0273e; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
</style>

react

export function ApprovalNotification({
  requester = 'Priya Shah',
  item = 'Q3 travel expense report',
  status = 'pending',
  accent = '#E8A020',
  timestamp = '2026-08-15T14:20:00',
  read = false,
}) {
  const icon = { pending: '\u2026', approved: '\u2713', denied: '\u2715' }[status] ?? '\u2022';
  const iconColor = { pending: '#E8A020', approved: '#1a7a4c', denied: '#b0273e' }[status] ?? '#241430';
  const srOnly = { position: 'absolute', width: 1, height: 1, padding: 0, margin: -1, overflow: 'hidden', clip: 'rect(0,0,0,0)', whiteSpace: 'nowrap', border: 0 };
  return (
    <article style={{ display: 'flex', alignItems: 'flex-start', gap: 12, maxWidth: 420, padding: '14px 16px', background: '#FAF7F2', color: '#241430', borderLeft: `4px solid ${accent}`, borderRadius: 10, boxShadow: '0 6px 18px rgba(36,20,48,.12)', fontFamily: 'system-ui, sans-serif', fontSize: 14, position: 'relative' }}>
      <span aria-hidden='true' style={{ width: 22, height: 22, borderRadius: '50%', flexShrink: 0, background: '#24143014', display: 'grid', placeItems: 'center', fontWeight: 700, fontSize: 12, color: iconColor }}>{icon}</span>
      <div style={{ flex: 1 }}>
        <p style={{ margin: '0 0 4px' }}><strong>{requester}</strong> requested approval for <strong>{item}</strong></p>
        <p style={{ margin: '0 0 4px', fontSize: 12, color: '#241430b3' }}>Status: <span style={{ textTransform: 'capitalize', fontWeight: 600 }}>{status}</span></p>
        <time style={{ display: 'block', fontSize: 11, color: '#24143080' }} dateTime={timestamp}>{timestamp}</time>
      </div>
      {!read && (
        <>
          <span aria-hidden='true' style={{ position: 'absolute', top: 14, right: 14, width: 8, height: 8, borderRadius: '50%', background: '#b0273e' }} />
          <span style={srOnly}>Unread</span>
        </>
      )}
    </article>
  );
}