Transition

Movement from one state to another.

In review Approved
automatic on approval

html

<div class="transition" data-type="automatic" style="--accent:#E8A020;">
  <div class="transition__states">
    <span class="transition__state transition__state--from">In review</span>
    <svg class="transition__arrow" viewBox="0 0 44 16" aria-hidden="true"><path d="M0 8h34M28 2l8 6-8 6" fill="none" stroke="#E8A020" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
    <span class="transition__state transition__state--to">Approved</span>
  </div>
  <div class="transition__meta">
    <span class="transition__type">
      <svg class="transition__icon transition__icon--manual" viewBox="0 0 20 20" aria-hidden="true"><path d="M7 11V4a1.5 1.5 0 013 0v5m0-4a1.5 1.5 0 013 0v4m0-2a1.5 1.5 0 013 0v4c0 3-2 6-6 6-3 0-4.5-1.5-6-4l-1.6-2.8a1.4 1.4 0 012.4-1.4L7 13" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg>
      <svg class="transition__icon transition__icon--automatic" viewBox="0 0 20 20" aria-hidden="true"><path d="M10 2l2 3.4 3.8-.8-.8 3.8L18.4 10l-3.4 2 .8 3.8-3.8-.8L10 18l-2-3.4-3.8.8.8-3.8L1.6 10l3.4-2-.8-3.8 3.8.8L10 2z" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round"/><circle cx="10" cy="10" r="2.4" fill="none" stroke="currentColor" stroke-width="1.2"/></svg>
      <svg class="transition__icon transition__icon--conditional" viewBox="0 0 20 20" aria-hidden="true"><path d="M10 2l8 8-8 8-8-8 8-8z" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linejoin="round"/></svg>
      automatic
    </span>
    <span class="transition__trigger">on approval</span>
  </div>
</div>
<style>
.transition { width: 320px; padding: 16px; background: #FAF7F2; color: #241430; font: 14px/1.4 system-ui, sans-serif; border-radius: 14px; box-shadow: 0 8px 24px rgba(36,20,48,.12); box-sizing: border-box; }
.transition__states { display: flex; align-items: center; gap: 10px; }
.transition__state { font-weight: 700; font-size: 14px; padding: 4px 10px; border-radius: 8px; background: #24143008; }
.transition__arrow { width: 44px; height: 16px; flex-shrink: 0; }
.transition__meta { display: flex; align-items: center; justify-content: space-between; margin-top: 12px; gap: 8px; }
.transition__type { display: inline-flex; align-items: center; gap: 5px; padding: 3px 10px; border-radius: 999px; font-weight: 700; font-size: 12px; text-transform: capitalize; background: var(--accent); color: #241430; }
.transition__icon { width: 12px; height: 12px; display: none; }
.transition[data-type="manual"] .transition__icon--manual { display: block; }
.transition[data-type="automatic"] .transition__icon--automatic { display: block; }
.transition[data-type="conditional"] .transition__icon--conditional { display: block; }
.transition__trigger { font-size: 12.5px; color: #241430b3; font-style: italic; }
</style>

tailwind

<div class="txn-tw w-80 p-4 bg-[#FAF7F2] text-[#241430] font-sans text-sm rounded-2xl shadow-lg box-border" data-type="automatic" style="--accent:#E8A020;">
  <div class="flex items-center gap-2.5">
    <span class="font-bold text-sm px-2.5 py-1 rounded-lg bg-[#24143008]">In review</span>
    <svg class="w-11 h-4 flex-shrink-0" viewBox="0 0 44 16" aria-hidden="true"><path d="M0 8h34M28 2l8 6-8 6" fill="none" stroke="#E8A020" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
    <span class="font-bold text-sm px-2.5 py-1 rounded-lg bg-[#24143008]">Approved</span>
  </div>
  <div class="flex items-center justify-between gap-2 mt-3">
    <span class="txn-tw__type inline-flex items-center gap-1 px-2.5 py-0.5 rounded-full font-bold text-xs capitalize" style="background:#E8A020;color:#241430;">
      <svg class="txn-tw__icon txn-tw__icon--manual w-3 h-3" viewBox="0 0 20 20" aria-hidden="true"><path d="M7 11V4a1.5 1.5 0 013 0v5m0-4a1.5 1.5 0 013 0v4m0-2a1.5 1.5 0 013 0v4c0 3-2 6-6 6-3 0-4.5-1.5-6-4l-1.6-2.8a1.4 1.4 0 012.4-1.4L7 13" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg>
      <svg class="txn-tw__icon txn-tw__icon--automatic w-3 h-3" viewBox="0 0 20 20" aria-hidden="true"><path d="M10 2l2 3.4 3.8-.8-.8 3.8L18.4 10l-3.4 2 .8 3.8-3.8-.8L10 18l-2-3.4-3.8.8.8-3.8L1.6 10l3.4-2-.8-3.8 3.8.8L10 2z" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round"/><circle cx="10" cy="10" r="2.4" fill="none" stroke="currentColor" stroke-width="1.2"/></svg>
      <svg class="txn-tw__icon txn-tw__icon--conditional w-3 h-3" viewBox="0 0 20 20" aria-hidden="true"><path d="M10 2l8 8-8 8-8-8 8-8z" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linejoin="round"/></svg>
      automatic
    </span>
    <span class="text-[12.5px] italic text-[#241430]/70">on approval</span>
  </div>
</div>
<style>
.txn-tw__icon { display: none; }
.txn-tw[data-type="manual"] .txn-tw__icon--manual { display: block; }
.txn-tw[data-type="automatic"] .txn-tw__icon--automatic { display: block; }
.txn-tw[data-type="conditional"] .txn-tw__icon--conditional { display: block; }
</style>

react

export function Transition({
  fromState = "In review",
  toState = "Approved",
  type = "automatic",
  triggeredBy = "on approval",
  accent = "#E8A020",
}) {
  return (
    <div style={{ width: 320, padding: 16, background: "#FAF7F2", color: "#241430", fontFamily: "system-ui, sans-serif",
      fontSize: 14, borderRadius: 14, boxShadow: "0 8px 24px rgba(36,20,48,.12)", boxSizing: "border-box" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
        <span style={{ fontWeight: 700, fontSize: 14, padding: "4px 10px", borderRadius: 8, background: "#24143008" }}>{fromState}</span>
        <svg width="44" height="16" viewBox="0 0 44 16" aria-hidden="true" style={{ flexShrink: 0 }}>
          <path d="M0 8h34M28 2l8 6-8 6" fill="none" stroke={accent} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
        </svg>
        <span style={{ fontWeight: 700, fontSize: 14, padding: "4px 10px", borderRadius: 8, background: "#24143008" }}>{toState}</span>
      </div>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8, marginTop: 12 }}>
        <span style={{ display: "inline-flex", alignItems: "center", gap: 5, padding: "3px 10px", borderRadius: 999,
          fontWeight: 700, fontSize: 12, textTransform: "capitalize", background: accent, color: "#241430" }}>
          {type === "manual" && (
            <svg width="12" height="12" viewBox="0 0 20 20" aria-hidden="true"><path d="M7 11V4a1.5 1.5 0 013 0v5m0-4a1.5 1.5 0 013 0v4m0-2a1.5 1.5 0 013 0v4c0 3-2 6-6 6-3 0-4.5-1.5-6-4l-1.6-2.8a1.4 1.4 0 012.4-1.4L7 13" fill="none" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round" strokeLinejoin="round" /></svg>
          )}
          {type === "automatic" && (
            <svg width="12" height="12" viewBox="0 0 20 20" aria-hidden="true"><path d="M10 2l2 3.4 3.8-.8-.8 3.8L18.4 10l-3.4 2 .8 3.8-3.8-.8L10 18l-2-3.4-3.8.8.8-3.8L1.6 10l3.4-2-.8-3.8 3.8.8L10 2z" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinejoin="round" /><circle cx="10" cy="10" r="2.4" fill="none" stroke="currentColor" strokeWidth="1.2" /></svg>
          )}
          {type === "conditional" && (
            <svg width="12" height="12" viewBox="0 0 20 20" aria-hidden="true"><path d="M10 2l8 8-8 8-8-8 8-8z" fill="none" stroke="currentColor" strokeWidth="1.3" strokeLinejoin="round" /></svg>
          )}
          {type}
        </span>
        <span style={{ fontSize: 12.5, fontStyle: "italic", color: "#241430b3" }}>{triggeredBy}</span>
      </div>
    </div>
  );
}