Retry

Reattempt failed operation.

retrying

Upload to S3 bucket

Network timeout

Attempt 2 of 3

html

<div class="retry" data-status="retrying" style="--accent:#E8A020;">
  <div class="retry__status">
    <span class="retry__icon retry__icon--failed"><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="retry__icon retry__icon--retrying"><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="retry__icon retry__icon--exhausted"><svg viewBox="0 0 16 16" width="16" height="16" fill="none" aria-hidden="true"><path d="M5 1.5h6L14.5 5v6L11 14.5H5L1.5 11V5z" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/><path d="M5.5 5.5l5 5M10.5 5.5l-5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></span>
    <span class="retry__text">retrying</span>
  </div>
  <h3 class="retry__title">Upload to S3 bucket</h3>
  <p class="retry__reason">Network timeout</p>
  <p class="retry__attempt">Attempt 2 of 3</p>
  <button type="button" class="retry__action"><svg viewBox="0 0 16 16" width="14" height="14" fill="none" aria-hidden="true"><path d="M13 8A5 5 0 1 1 11.5 4.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><path d="M13 2v3.5H9.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg> Retry now</button>
</div>
<style>
.retry { font: 15px/1.5 system-ui, sans-serif; max-width: 340px; padding: 20px; background: #FAF7F2; color: #241430; border-radius: 14px; border: 1.5px solid #24143020; }
.retry__status { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: 999px; background: #24143010; margin-bottom: 12px; }
.retry__icon { display: none; }
.retry[data-status="failed"] .retry__icon--failed { display: inline-flex; color: #b23b3b; }
.retry[data-status="retrying"] .retry__icon--retrying { display: inline-flex; color: var(--accent); }
.retry[data-status="exhausted"] .retry__icon--exhausted { display: inline-flex; color: #241430; }
.retry__text { font-weight: 600; font-size: 13px; text-transform: capitalize; }
.retry__title { margin: 0 0 6px; font-size: 17px; font-weight: 600; }
.retry__reason { margin: 0 0 4px; font-size: 14px; color: #241430cc; }
.retry__attempt { margin: 0 0 14px; font-size: 13px; color: #24143099; }
.retry__action { display: inline-flex; align-items: center; gap: 6px; border: none; background: var(--accent); color: #241430; font: 600 13px system-ui, sans-serif; padding: 8px 14px; border-radius: 8px; cursor: pointer; }
.retry[data-status="exhausted"] .retry__action { opacity: .5; pointer-events: none; }
.retry__action:focus-visible { outline: 2px solid #241430; outline-offset: 2px; }
</style>

tailwind

<div class="retry-tw font-sans max-w-[340px] p-5 bg-[#FAF7F2] text-[#241430] rounded-2xl border-[1.5px] border-[#24143020]" data-status="retrying">
  <div class="inline-flex items-center gap-1.5 py-1 px-2.5 rounded-full bg-[#24143010] mb-3">
    <span class="retry-tw__icon retry-tw__icon--failed" 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="retry-tw__icon retry-tw__icon--retrying" 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="retry-tw__icon retry-tw__icon--exhausted" style="color:#241430"><svg viewBox="0 0 16 16" width="16" height="16" fill="none" aria-hidden="true"><path d="M5 1.5h6L14.5 5v6L11 14.5H5L1.5 11V5z" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/><path d="M5.5 5.5l5 5M10.5 5.5l-5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></span>
    <span class="font-semibold text-[13px] capitalize">retrying</span>
  </div>
  <h3 class="m-0 mb-1.5 text-[17px] font-semibold">Upload to S3 bucket</h3>
  <p class="m-0 mb-1 text-sm text-[#241430]/80">Network timeout</p>
  <p class="m-0 mb-3.5 text-[13px] text-[#241430]/60">Attempt 2 of 3</p>
  <button type="button" class="retry-tw__action inline-flex items-center gap-1.5 border-0 font-semibold text-[13px] py-2 px-3.5 rounded-lg cursor-pointer" style="background:#E8A020"><svg viewBox="0 0 16 16" width="14" height="14" fill="none" aria-hidden="true"><path d="M13 8A5 5 0 1 1 11.5 4.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><path d="M13 2v3.5H9.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg> Retry now</button>
</div>
<style>
.retry-tw__icon { display: none; }
.retry-tw[data-status="failed"] .retry-tw__icon--failed { display: inline-flex; }
.retry-tw[data-status="retrying"] .retry-tw__icon--retrying { display: inline-flex; }
.retry-tw[data-status="exhausted"] .retry-tw__icon--exhausted { display: inline-flex; }
.retry-tw[data-status="exhausted"] .retry-tw__action { opacity: .5; pointer-events: none; }
</style>

react

export function Retry({
  taskTitle = "Upload to S3 bucket",
  reason = "Network timeout",
  attempt = 2,
  maxAttempts = 3,
  status = "retrying",
  accent = "#E8A020",
}) {
  const icons = {
    failed: { 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" },
    retrying: { 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 },
    exhausted: { svg: "<svg viewBox=\"0 0 16 16\" width=\"16\" height=\"16\" fill=\"none\" aria-hidden=\"true\"><path d=\"M5 1.5h6L14.5 5v6L11 14.5H5L1.5 11V5z\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linejoin=\"round\"/><path d=\"M5.5 5.5l5 5M10.5 5.5l-5 5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/></svg>", color: "#241430" },
  };
  const active = icons[status] ?? icons.failed;
  const exhausted = status === "exhausted";
  return (
    <div style={{ fontFamily: "system-ui, sans-serif", maxWidth: 340, padding: 20, background: "#FAF7F2",
      color: "#241430", borderRadius: 14, border: "1.5px solid #24143020" }}>
      <div style={{ display: "inline-flex", alignItems: "center", gap: 6, padding: "4px 10px", borderRadius: 999, background: "#24143010", marginBottom: 12 }}>
        <span style={{ color: active.color, display: "inline-flex" }} dangerouslySetInnerHTML={{ __html: active.svg }} />
        <span style={{ fontWeight: 600, fontSize: 13, textTransform: "capitalize" }}>{status}</span>
      </div>
      <h3 style={{ margin: "0 0 6px", fontSize: 17, fontWeight: 600 }}>{taskTitle}</h3>
      <p style={{ margin: "0 0 4px", fontSize: 14, color: "#241430cc" }}>{reason}</p>
      <p style={{ margin: "0 0 14px", fontSize: 13, color: "#24143099" }}>Attempt {attempt} of {maxAttempts}</p>
      <button type="button" disabled={exhausted} style={{ display: "inline-flex", alignItems: "center", gap: 6, border: "none",
        background: accent, color: "#241430", fontWeight: 600, fontSize: 13, padding: "8px 14px", borderRadius: 8,
        cursor: exhausted ? "default" : "pointer", opacity: exhausted ? 0.5 : 1 }}>
        <span dangerouslySetInnerHTML={{ __html: "<svg viewBox=\"0 0 16 16\" width=\"14\" height=\"14\" fill=\"none\" aria-hidden=\"true\"><path d=\"M13 8A5 5 0 1 1 11.5 4.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/><path d=\"M13 2v3.5H9.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>" }} /> Retry now
      </button>
    </div>
  );
}