The done state for a finished agent run: a ring draws itself, fills, a check strokes in with a small burst of sparks, then Task complete and Opened PR #482 slide up beside it. Pure SVG strokes.
Also known as: success checkmark animation, task complete animation, ai done state.
<div class="aia-agent-task-complete" role="status" aria-label="Task complete">
<span class="aia-agent-task-complete-mark" aria-hidden="true">
<svg viewBox="0 0 48 48"><circle class="aia-agent-task-complete-ring" cx="24" cy="24" r="21" pathLength="100"/><circle class="aia-agent-task-complete-disc" cx="24" cy="24" r="21"/><path class="aia-agent-task-complete-tick" d="m15 24.5 6 6 12-13" pathLength="100"/></svg>
<i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i>
</span>
<span class="aia-agent-task-complete-text">
<b>Task complete</b>
<span>Opened PR #482, 4 files changed</span>
</span>
</div>.aia-agent-task-complete {
--c: var(--aia-color, #7c5cff);
font-size: var(--aia-size, 16px);
font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
line-height: 1.4;
--d: 5s;
display: flex;
align-items: center;
gap: 1em;
}
.aia-agent-task-complete-mark {
position: relative;
display: grid;
place-items: center;
width: 3.6em;
height: 3.6em;
}
.aia-agent-task-complete-mark svg {
width: 100%;
height: 100%;
overflow: visible;
}
.aia-agent-task-complete-ring {
fill: none;
stroke: var(--c);
stroke-width: 2.5;
stroke-linecap: round;
stroke-dasharray: 100;
transform: rotate(-90deg);
transform-origin: center;
animation: aia-agent-task-complete-ring var(--d) cubic-bezier(0.65, 0, 0.35, 1) infinite;
}
.aia-agent-task-complete-disc {
fill: var(--c);
transform-origin: center;
animation: aia-agent-task-complete-disc var(--d) cubic-bezier(0.34, 1.56, 0.64, 1) infinite;
}
.aia-agent-task-complete-tick {
fill: none;
stroke: #fff;
stroke-width: 4;
stroke-linecap: round;
stroke-linejoin: round;
stroke-dasharray: 100;
animation: aia-agent-task-complete-tick var(--d) cubic-bezier(0.65, 0, 0.35, 1) infinite;
}
.aia-agent-task-complete-mark i {
--r: 0deg;
position: absolute;
left: calc(50% - 0.12em);
top: calc(50% - 0.12em);
width: 0.24em;
height: 0.24em;
border-radius: 50%;
background: var(--c);
opacity: 0;
animation: aia-agent-task-complete-spark var(--d) cubic-bezier(0.2, 0.7, 0.3, 1) infinite;
}
.aia-agent-task-complete-mark i:nth-of-type(2) { --r: 45deg; }
.aia-agent-task-complete-mark i:nth-of-type(3) { --r: 90deg; }
.aia-agent-task-complete-mark i:nth-of-type(4) { --r: 135deg; }
.aia-agent-task-complete-mark i:nth-of-type(5) { --r: 180deg; }
.aia-agent-task-complete-mark i:nth-of-type(6) { --r: 225deg; }
.aia-agent-task-complete-mark i:nth-of-type(7) { --r: 270deg; }
.aia-agent-task-complete-mark i:nth-of-type(8) { --r: 315deg; }
.aia-agent-task-complete-mark i:nth-of-type(2n) { width: 0.17em; height: 0.17em; }
.aia-agent-task-complete-text {
display: grid;
gap: 0.15em;
}
.aia-agent-task-complete-text b {
font-size: 1.15em;
animation: aia-agent-task-complete-rise var(--d) cubic-bezier(0.2, 0.8, 0.2, 1) infinite;
}
.aia-agent-task-complete-text span {
color: color-mix(in srgb, currentColor 55%, transparent);
font-size: 0.85em;
animation: aia-agent-task-complete-rise var(--d) cubic-bezier(0.2, 0.8, 0.2, 1) infinite;
animation-delay: 0.12s;
}
@keyframes aia-agent-task-complete-ring {
0%, 4% { stroke-dashoffset: 100; opacity: 1; }
26%, 90% { stroke-dashoffset: 0; opacity: 1; }
96%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes aia-agent-task-complete-disc {
0%, 24% { transform: scale(0); opacity: 1; }
34%, 90% { transform: scale(1); opacity: 1; }
96%, 100% { transform: scale(0.9); opacity: 0; }
}
@keyframes aia-agent-task-complete-tick {
0%, 31% { stroke-dashoffset: 100; opacity: 1; }
42%, 90% { stroke-dashoffset: 0; opacity: 1; }
96%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes aia-agent-task-complete-spark {
0%, 31% { opacity: 0; transform: rotate(var(--r)) translateY(-1.2em) scale(1); }
33% { opacity: 1; }
48%, 100% { opacity: 0; transform: rotate(var(--r)) translateY(-2.6em) scale(0.3); }
}
@keyframes aia-agent-task-complete-rise {
0%, 36% { opacity: 0; transform: translateY(0.6em); }
48%, 90% { opacity: 1; transform: none; }
96%, 100% { opacity: 0; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
.aia-agent-task-complete *,
.aia-agent-task-complete-mark svg * {
animation-play-state: paused;
animation-delay: calc(var(--d) * -0.6);
}
}
@media (prefers-reduced-motion: reduce) {
.aia-agent-task-complete, .aia-agent-task-complete *, .aia-agent-task-complete::before, .aia-agent-task-complete::after, .aia-agent-task-complete *::before, .aia-agent-task-complete *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}--aia-color on the element or a parent.
Currently previewing #3b82f6.--aia-size. Every other dimension is in
em, so the whole thing scales together. Currently previewing 16px.transition or animation
shorthand. Staggered delays are relative, so they keep their rhythm.