.pds-spinner {
--spinner-color: var(--pds-color-foreground-default);
align-items: center;
display: flex;
flex-direction: column;
text-align: center;
}
.pds-spinner--inline {
align-self: center;
display: inline-flex;
}
.pds-spinner__icon {
height: var(--spinner-size);
overflow: visible;
width: var(--spinner-size);
}
.pds-spinner__with-avatar {
display: inline-flex;
position: relative;
}
/* The avatar sits in the middle of the ring. */
.pds-spinner__avatar {
align-items: center;
display: flex;
inset: 0;
justify-content: center;
position: absolute;
}
/* The Zappy bolt in the plain foreground color (not the gradient), masked to
the bolt shape (alpha only, so the mask color is irrelevant). Half the ring
tall. */
.pds-spinner__bolt {
--spinner-bolt-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 374 512'%3E%3Cpath d='M0 291.5748L240.7741 0L212.7775 227.4007H373.76L131.586 512L166.5823 291.5748H0Z' fill='black'/%3E%3C/svg%3E");
aspect-ratio: 374 / 512;
background-color: var(--pds-color-foreground-default);
height: calc(var(--spinner-size) * 0.5);
mask: var(--spinner-bolt-mask) center / contain no-repeat;
}
.pds-spinner__track {
fill: none;
stroke: var(--spinner-color);
stroke-opacity: 0.3;
stroke-width: 2.5;
}
.pds-spinner__rotator {
animation: spinner-rotate 1s linear infinite;
transform-origin: 12px 12px;
}
.pds-spinner__arc {
fill: none;
stroke: var(--spinner-color);
/* Circumference of the r=10.5 circle (2 * pi * 10.5 = 65.97) is larger
than the dash so only one arc segment ever shows. */
stroke-dasharray: 18.7 66;
stroke-linecap: round;
stroke-width: 2.5;
}
/* Agentic: --pds-gradient-ai-active is a CSS gradient, which an SVG stroke
cannot use. Instead the gradient is the background of a box that is masked
to the same ring / arc shapes (alpha only, so the mask colour is
irrelevant). The arc box rotates; its gradient layer counter-rotates so
the gradient stays fixed while the arc spins, like the ring in the
default spinner. */
.pds-spinner--agentic {
--spinner-arc-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='10.5' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-dasharray='18.7 66'/%3E%3C/svg%3E");
--spinner-ring-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='10.5' fill='none' stroke='black' stroke-width='2.5'/%3E%3C/svg%3E");
}
.pds-spinner--agentic .pds-spinner__icon {
display: block;
position: relative;
}
.pds-spinner__gradient-track,
.pds-spinner__gradient-rotator,
.pds-spinner__gradient-arc {
inset: 0;
position: absolute;
}
.pds-spinner__gradient-track {
background: var(--pds-gradient-ai-active);
mask: var(--spinner-ring-mask) center / 100% 100% no-repeat;
opacity: 0.3;
}
.pds-spinner__gradient-rotator {
animation: spinner-rotate 1s linear infinite;
}
.pds-spinner__gradient-arc {
mask: var(--spinner-arc-mask) center / 100% 100% no-repeat;
}
.pds-spinner__gradient-arc::before {
animation: spinner-rotate 1s linear infinite reverse;
background: var(--pds-gradient-ai-active);
content: '';
inset: 0;
position: absolute;
}
@keyframes spinner-rotate {
to {
transform: rotate(360deg);
}
}
.pds-spinner__label {
font-family: var(--pds-typography-ff-default);
font-weight: var(--pds-typography-fw-medium);
line-height: var(--pds-typography-lh-m);
max-width: calc(var(--spinner-size) * 6);
}
@media (prefers-reduced-motion: reduce) {
.pds-spinner__rotator,
.pds-spinner__gradient-rotator,
.pds-spinner__gradient-arc::before {
animation: none;
}
}
Spinner: agentic color variant
Extend the existing PDS v2 Spinner (not a new component).
Extends a PDS componentOpen in Storybook