Human-in-the-loop

Workflow requiring human participation.

Publish blog post waiting

A person must review this step before the workflow continues.

html

<div class="hitl-step hitl-step--waiting" style="--accent:#BFD9F2;" role="status" aria-live="polite">
  <div class="hitl-step__row">
    <span class="hitl-step__marker" aria-hidden="true"></span>
    <span class="hitl-step__label">Publish blog post</span>
    <span class="hitl-step__badge">waiting</span>
  </div>
  
  <p class="hitl-step__note">A person must review this step before the workflow continues.</p>
  
</div>
<style>
.hitl-step { max-width: 420px; padding: 14px 16px; border-radius: 12px; background: #FAF7F2; color: #241430; border: 1px solid #24143020; box-sizing: border-box; font: 15px/1.5 system-ui, sans-serif; }
.hitl-step__row { display: flex; align-items: center; gap: 10px; }
.hitl-step__marker { width: 10px; height: 10px; border-radius: 50%; flex: none; background: #24143030; }
.hitl-step--waiting .hitl-step__marker { background: var(--accent); box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 30%, transparent); }
.hitl-step--reviewed .hitl-step__marker { background: #2f8f5b; }
.hitl-step--skipped .hitl-step__marker { background: #24143030; }
.hitl-step__label { flex: 1; font-weight: 600; }
.hitl-step__badge { font-size: 11px; font-weight: 700; text-transform: capitalize; padding: 3px 9px; border-radius: 999px; background: #24143012; }
.hitl-step--waiting .hitl-step__badge { color: #241430; background: color-mix(in srgb, var(--accent) 40%, #FAF7F2); }
.hitl-step--reviewed .hitl-step__badge { color: #1c5c3a; background: #A8E6C140; }
.hitl-step--skipped .hitl-step__badge { color: #24143080; text-decoration: line-through; }
.hitl-step__note { margin: 10px 0 0; font-size: 13px; color: #24143099; padding-left: 20px; }
</style>

tailwind

<div class="hitl-tw hitl-tw--waiting max-w-md p-3.5 rounded-xl bg-[#FAF7F2] text-[#241430] border border-[#24143020] box-border font-sans text-[15px]" style="--accent:#BFD9F2;" role="status" aria-live="polite">
  <div class="flex items-center gap-2.5">
    <span class="hitl-tw__marker w-2.5 h-2.5 rounded-full flex-none" aria-hidden="true"></span>
    <span class="flex-1 font-semibold">Publish blog post</span>
    <span class="hitl-tw__badge text-[11px] font-bold capitalize px-2.5 py-0.5 rounded-full">waiting</span>
  </div>
  
  <p class="mt-2.5 mb-0 text-[13px] text-[#24143099] pl-5">A person must review this step before the workflow continues.</p>
  
</div>
<style>
.hitl-tw__marker { background: #24143030; }
.hitl-tw--waiting .hitl-tw__marker { background: var(--accent); box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 30%, transparent); }
.hitl-tw--reviewed .hitl-tw__marker { background: #2f8f5b; }
.hitl-tw--skipped .hitl-tw__marker { background: #24143030; }
.hitl-tw__badge { background: #24143012; }
.hitl-tw--waiting .hitl-tw__badge { color: #241430; background: color-mix(in srgb, var(--accent) 40%, #FAF7F2); }
.hitl-tw--reviewed .hitl-tw__badge { color: #1c5c3a; background: #A8E6C140; }
.hitl-tw--skipped .hitl-tw__badge { color: #24143080; text-decoration: line-through; }
</style>

react

export function HumanInTheLoop({
  stepLabel = "Publish blog post",
  status = "waiting",
  accent = "#BFD9F2",
  showNote = true,
}) {
  const isWaiting = status === "waiting";
  const marker = { waiting: accent, reviewed: "#2f8f5b", skipped: "#24143030" }[status] ?? "#24143030";
  const badge = {
    waiting: { color: "#241430", background: `color-mix(in srgb, ${accent} 40%, #FAF7F2)` },
    reviewed: { color: "#1c5c3a", background: "#A8E6C140" },
    skipped: { color: "#24143080", background: "#24143012", textDecoration: "line-through" },
  }[status] ?? { color: "#241430", background: "#24143012" };
  return (
    <div role="status" aria-live="polite" style={{ maxWidth: 420, padding: "14px 16px", borderRadius: 12, background: "#FAF7F2", color: "#241430", border: "1px solid #24143020", boxSizing: "border-box", font: "15px/1.5 system-ui, sans-serif" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
        <span aria-hidden="true" style={{ width: 10, height: 10, borderRadius: "50%", flex: "none", background: marker, boxShadow: isWaiting ? `0 0 0 4px color-mix(in srgb, ${accent} 30%, transparent)` : "none" }} />
        <span style={{ flex: 1, fontWeight: 600 }}>{stepLabel}</span>
        <span style={{ fontSize: 11, fontWeight: 700, textTransform: "capitalize", padding: "3px 9px", borderRadius: 999, ...badge }}>{status}</span>
      </div>
      {showNote && (
        <p style={{ margin: "10px 0 0", fontSize: 13, color: "#24143099", paddingLeft: 20 }}>A person must review this step before the workflow continues.</p>
      )}
    </div>
  );
}