Indeterminate loading indicator.
<div class="spinner-wrap" role="status" aria-live="polite">
<span class="spinner spinner--normal" style="width:28px;height:28px;border-top-color:#8A6FBF;" aria-hidden="true"></span>
<span class="spinner-wrap__srtext">Loading</span>
</div>
<style>
.spinner-wrap { display: inline-block; }
.spinner-wrap__srtext { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
.spinner { display: inline-block; border-radius: 50%; border: 3px solid #24143022; border-top-color: currentColor; }
@keyframes spinner-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: no-preference) {
.spinner--slow { animation: spinner-spin 1.6s linear infinite; }
.spinner--normal { animation: spinner-spin .9s linear infinite; }
.spinner--fast { animation: spinner-spin .5s linear infinite; }
}
</style><div role="status" aria-live="polite" class="inline-block">
<span aria-hidden="true" class="spinner-tw spinner-tw--normal inline-block rounded-full border-[3px] border-[#24143022]" style="width:28px;height:28px;border-top-color:#8A6FBF;"></span>
<span class="sr-only">Loading</span>
</div>
<style>
@keyframes spinner-tw-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: no-preference) {
.spinner-tw--slow { animation: spinner-tw-spin 1.6s linear infinite; }
.spinner-tw--normal { animation: spinner-tw-spin .9s linear infinite; }
.spinner-tw--fast { animation: spinner-tw-spin .5s linear infinite; }
}
</style>export function Spinner({
label = "Loading",
size = 28,
color = "#8A6FBF",
speed = "normal",
}) {
const duration = { slow: "1.6s", normal: "0.9s", fast: "0.5s" }[speed] ?? "0.9s";
return (
<div role="status" aria-live="polite" style={{ display: "inline-block" }}>
<span aria-hidden="true" className="spinner-ring" style={{ display: "inline-block", width: size, height: size, borderRadius: "50%",
border: "3px solid #24143022", borderTopColor: color }} />
<span style={{ position: "absolute", width: 1, height: 1, overflow: "hidden", clip: "rect(0 0 0 0)" }}>{label}</span>
<style>{`
@media (prefers-reduced-motion: no-preference) {
.spinner-ring { animation: spinner-react-spin ${duration} linear infinite; }
@keyframes spinner-react-spin { to { transform: rotate(360deg); } }
}
`}</style>
</div>
);
}