Approval

Explicit authorisation step.

Requested by Dev Patel

Expense report #4021

pending

Awaiting approval from Priya Shah

html

<div class="approval" data-decision="pending" style="--accent:#E8A020;">
  <p class="approval__meta">Requested by Dev Patel</p>
  <h3 class="approval__title">Expense report #4021</h3>
  <div class="approval__status">
    <span class="approval__icon approval__icon--pending"><svg viewBox="0 0 16 16" width="16" height="16" fill="none" aria-hidden="true"><circle cx="8" cy="8" r="6.25" stroke="currentColor" stroke-width="1.5"/><path d="M8 4.5V8l2.5 1.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
    <span class="approval__icon approval__icon--approved"><svg viewBox="0 0 16 16" width="16" height="16" fill="none" aria-hidden="true"><path d="M3 8.5l3 3 7-7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
    <span class="approval__icon approval__icon--rejected"><svg viewBox="0 0 16 16" width="16" height="16" fill="none" aria-hidden="true"><path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg></span>
    <span class="approval__text">pending</span>
  </div>
  <p class="approval__who">Awaiting approval from <strong>Priya Shah</strong></p>
</div>
<style>
.approval { font: 15px/1.5 system-ui, sans-serif; max-width: 340px; padding: 20px; background: #FAF7F2; color: #241430; border: 1.5px solid #24143020; border-radius: 14px; border-left: 4px solid var(--accent); }
.approval__meta { margin: 0 0 4px; font-size: 12px; color: #24143099; text-transform: uppercase; letter-spacing: .04em; }
.approval__title { margin: 0 0 12px; font-size: 17px; font-weight: 600; }
.approval__status { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px 4px 8px; border-radius: 999px; background: #24143010; margin-bottom: 10px; }
.approval__icon { display: none; color: #241430; }
.approval[data-decision="pending"] .approval__icon--pending { display: inline-flex; color: var(--accent); }
.approval[data-decision="approved"] .approval__icon--approved { display: inline-flex; color: #2f8a52; }
.approval[data-decision="rejected"] .approval__icon--rejected { display: inline-flex; color: #b23b3b; }
.approval__text { font-weight: 600; font-size: 13px; text-transform: capitalize; }
.approval__who { margin: 0; font-size: 14px; }
</style>

tailwind

<div class="approval-tw font-sans max-w-[340px] p-5 bg-[#FAF7F2] text-[#241430] border-[1.5px] border-[#24143020] rounded-2xl border-l-4" data-decision="pending" style="border-left-color:#E8A020;">
  <p class="m-0 mb-1 text-xs uppercase tracking-wide text-[#241430]/60">Requested by Dev Patel</p>
  <h3 class="m-0 mb-3 text-[17px] font-semibold">Expense report #4021</h3>
  <div class="approval-tw__status inline-flex items-center gap-1.5 py-1 pl-2 pr-2.5 rounded-full bg-[#24143010] mb-2.5">
    <span class="approval-tw__icon approval-tw__icon--pending" style="color:#E8A020"><svg viewBox="0 0 16 16" width="16" height="16" fill="none" aria-hidden="true"><circle cx="8" cy="8" r="6.25" stroke="currentColor" stroke-width="1.5"/><path d="M8 4.5V8l2.5 1.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
    <span class="approval-tw__icon approval-tw__icon--approved" style="color:#2f8a52"><svg viewBox="0 0 16 16" width="16" height="16" fill="none" aria-hidden="true"><path d="M3 8.5l3 3 7-7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
    <span class="approval-tw__icon approval-tw__icon--rejected" style="color:#b23b3b"><svg viewBox="0 0 16 16" width="16" height="16" fill="none" aria-hidden="true"><path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg></span>
    <span class="font-semibold text-[13px] capitalize">pending</span>
  </div>
  <p class="m-0 text-sm">Awaiting approval from <strong>Priya Shah</strong></p>
</div>
<style>
.approval-tw__icon { display: none; }
.approval-tw[data-decision="pending"] .approval-tw__icon--pending { display: inline-flex; }
.approval-tw[data-decision="approved"] .approval-tw__icon--approved { display: inline-flex; }
.approval-tw[data-decision="rejected"] .approval-tw__icon--rejected { display: inline-flex; }
</style>

react

export function Approval({
  itemTitle = "Expense report #4021",
  requester = "Dev Patel",
  approver = "Priya Shah",
  decision = "pending",
  accent = "#E8A020",
}) {
  const icons = {
    pending: { svg: "<svg viewBox=\"0 0 16 16\" width=\"16\" height=\"16\" fill=\"none\" aria-hidden=\"true\"><circle cx=\"8\" cy=\"8\" r=\"6.25\" stroke=\"currentColor\" stroke-width=\"1.5\"/><path d=\"M8 4.5V8l2.5 1.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>", color: accent },
    approved: { svg: "<svg viewBox=\"0 0 16 16\" width=\"16\" height=\"16\" fill=\"none\" aria-hidden=\"true\"><path d=\"M3 8.5l3 3 7-7\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>", color: "#2f8a52" },
    rejected: { svg: "<svg viewBox=\"0 0 16 16\" width=\"16\" height=\"16\" fill=\"none\" aria-hidden=\"true\"><path d=\"M4 4l8 8M12 4l-8 8\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/></svg>", color: "#b23b3b" },
  };
  const active = icons[decision] ?? icons.pending;
  return (
    <div style={{ fontFamily: "system-ui, sans-serif", maxWidth: 340, padding: 20, background: "#FAF7F2",
      color: "#241430", border: "1.5px solid #24143020", borderRadius: 14, borderLeft: `4px solid ${accent}` }}>
      <p style={{ margin: "0 0 4px", fontSize: 12, color: "#24143099", textTransform: "uppercase", letterSpacing: ".04em" }}>Requested by {requester}</p>
      <h3 style={{ margin: "0 0 12px", fontSize: 17, fontWeight: 600 }}>{itemTitle}</h3>
      <div style={{ display: "inline-flex", alignItems: "center", gap: 6, padding: "4px 10px 4px 8px", borderRadius: 999, background: "#24143010", marginBottom: 10 }}>
        <span style={{ color: active.color, display: "inline-flex" }} dangerouslySetInnerHTML={{ __html: active.svg }} />
        <span style={{ fontWeight: 600, fontSize: 13, textTransform: "capitalize" }}>{decision}</span>
      </div>
      <p style={{ margin: 0, fontSize: 14 }}>Awaiting approval from <strong>{approver}</strong></p>
    </div>
  );
}