Canary
CSSA secondary canary progress bar fills alongside the main production stream before successfully verifying and merging.
- Tier
- CSS
- Dependencies
- None
- Duration
- 3.6 s, loops
- Categories
- Icons and micro-interactions, Data and progress
- Use cases
- Determinate progress, Workflow and approvals
- Industries
- SaaS and software, Cross-industry
- Style
- Technical · light stroke
- Set
- deploy
- Tags
- loopprogresslineui
Companion assets
The same artwork, not animated. Derived from the entry’s own resting state, so it matches exactly.
Code
animation.svg
<svg xmlns="http://www.w3.org/2000/svg" aria-labelledby="deploy-canary-title" class="pulsar pulsar-deploy-canary" data-pulsar="deploy-canary" role="img" viewBox="0 0 160 96"><title id="deploy-canary-title">Canary deployment track metering test traffic before merging into primary production stream</title><g fill="none" stroke="currentColor" stroke-linecap="square" stroke-width=".75" opacity=".3"><path id="deploy-canary-datum" d="M20 20h8m-8 0v8m120-8h-8m8 0v8M20 76h8m-8 0v-8m120 8h-8m8 0v-8"></path><line id="deploy-canary-axis" x1="24" x2="136" y1="48" y2="48" stroke-dasharray="2 4"></line></g><g fill="none" stroke="currentColor" stroke-linecap="square" stroke-width="1.25"><line id="deploy-canary-main-rail" x1="28" x2="112" y1="40" y2="40" opacity=".4"></line><path id="deploy-canary-sub-rail" stroke-dasharray="2 3" d="m40 40 14 18h42l14-18" opacity=".5"></path><line id="deploy-canary-out-rail" x1="112" x2="132" y1="40" y2="40" opacity=".4"></line></g><g fill="none" stroke="currentColor" stroke-linecap="square" stroke-width="1.2"><line x1="54" x2="54" y1="55" y2="61" opacity=".6"></line><line x1="96" x2="96" y1="55" y2="61" opacity=".6"></line></g><line id="deploy-canary-main-flow" x1="28" x2="112" y1="40" y2="40" fill="none" stroke="currentColor" stroke-dasharray="12 18" stroke-width="1.5"></line><path id="deploy-canary-sub-fill" fill="none" stroke="currentColor" stroke-dasharray="78" stroke-dashoffset="78" stroke-width="1.75" d="m40 40 14 18h42l14-18"></path><circle id="deploy-canary-sensor-node" cx="75" cy="58" r="2.5" fill="currentColor"></circle><circle id="deploy-canary-sensor-ring" cx="75" cy="58" r="6" fill="none" stroke="currentColor" stroke-width="1" opacity="0"></circle><polygon id="deploy-canary-merge-pip" fill="currentColor" points="112,37 116,40 112,43 108,40"></polygon><line id="deploy-canary-out-flow" x1="112" x2="132" y1="40" y2="40" fill="none" stroke="currentColor" stroke-dasharray="20" stroke-dashoffset="20" stroke-width="2"></line></svg>
animation.css
.pulsar-deploy-canary {
--pulsar-accent: currentColor;
}
.pulsar-deploy-canary #deploy-canary-sub-fill,
.pulsar-deploy-canary #deploy-canary-sensor-ring,
.pulsar-deploy-canary #deploy-canary-out-flow {
stroke: var(--pulsar-accent, currentColor);
}
.pulsar-deploy-canary #deploy-canary-sensor-node,
.pulsar-deploy-canary #deploy-canary-merge-pip {
fill: var(--pulsar-accent, currentColor);
}
.pulsar-deploy-canary #deploy-canary-main-flow {
animation: deploy-canary-flow-main 3600ms linear infinite;
}
.pulsar-deploy-canary #deploy-canary-sub-fill {
animation: deploy-canary-fill-sub 3600ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
}
.pulsar-deploy-canary #deploy-canary-sensor-node {
animation: deploy-canary-sensor-pop 3600ms cubic-bezier(0.16, 1, 0.3, 1) infinite;
transform-origin: 75px 58px;
}
.pulsar-deploy-canary #deploy-canary-sensor-ring {
animation: deploy-canary-sensor-wave 3600ms cubic-bezier(0.16, 1, 0.3, 1) infinite;
transform-origin: 75px 58px;
}
.pulsar-deploy-canary #deploy-canary-merge-pip {
animation: deploy-canary-merge-flash 3600ms cubic-bezier(0.16, 1, 0.3, 1) infinite;
transform-origin: 112px 40px;
}
.pulsar-deploy-canary #deploy-canary-out-flow {
animation: deploy-canary-release 3600ms cubic-bezier(0.16, 1, 0.3, 1) infinite;
}
@keyframes deploy-canary-flow-main {
0% {
stroke-dashoffset: 0;
}
100% {
stroke-dashoffset: -60;
}
}
@keyframes deploy-canary-fill-sub {
0%,
10% {
stroke-dashoffset: 78;
opacity: 0.3;
}
45% {
stroke-dashoffset: 35;
opacity: 1;
}
65%,
88% {
stroke-dashoffset: 0;
opacity: 1;
}
96%,
100% {
stroke-dashoffset: 0;
opacity: 0.2;
}
}
@keyframes deploy-canary-sensor-pop {
0%,
35% {
transform: scale(0.8);
opacity: 0.5;
}
48%,
85% {
transform: scale(1.3);
opacity: 1;
}
95%,
100% {
transform: scale(0.8);
opacity: 0.5;
}
}
@keyframes deploy-canary-sensor-wave {
0%,
42% {
opacity: 0;
transform: scale(0.5);
}
48% {
opacity: 0.9;
}
62% {
opacity: 0;
transform: scale(2.2);
}
100% {
opacity: 0;
transform: scale(2.2);
}
}
@keyframes deploy-canary-merge-flash {
0%,
60% {
transform: scale(0.8);
opacity: 0.4;
}
68%,
88% {
transform: scale(1.4);
opacity: 1;
}
96%,
100% {
transform: scale(0.8);
opacity: 0.4;
}
}
@keyframes deploy-canary-release {
0%,
64% {
stroke-dashoffset: 20;
opacity: 0;
}
72%,
88% {
stroke-dashoffset: 0;
opacity: 1;
}
98%,
100% {
stroke-dashoffset: -20;
opacity: 0;
}
}
@media (prefers-reduced-motion: reduce) {
.pulsar-deploy-canary * {
animation: none !important;
transform: none;
}
.pulsar-deploy-canary #deploy-canary-sub-fill,
.pulsar-deploy-canary #deploy-canary-out-flow {
stroke-dashoffset: 0;
opacity: 1;
}
.pulsar-deploy-canary #deploy-canary-sensor-node,
.pulsar-deploy-canary #deploy-canary-merge-pip {
opacity: 1;
}
}