Indication of intermediate state or transition from one state to another.
<div class="spinner " role="status" aria-live="polite" aria-label="Loading">
<svg class="spinner__circle" viewBox="25 25 50 50" aria-hidden="true" focusable="false">
<circle class="spinner__path" cx="50" cy="50" r="22" fill="none"></circle>
</svg>
</div>
<div class="spinner {{ class }}" role="status" aria-live="polite" aria-label="{{ data.label|default('Loading') }}">
<svg class="spinner__circle" viewBox="25 25 50 50" aria-hidden="true" focusable="false">
<circle class="spinner__path" cx="50" cy="50" r="22" fill="none"></circle>
</svg>
</div>
{
"language": "en-US",
"data": {
"label": "Loading"
}
}
.spinner {
width: 1em;
height: 1em;
}
.spinner__circle {
height: 100%;
width: 100%;
transform-origin: center center;
animation: spinnerRotate 2000ms linear infinite;
}
.spinner__path {
stroke-dasharray: 89, 200;
stroke-dashoffset: 0;
stroke-linecap: round;
stroke-width: 5px;
stroke-miterlimit: 10;
stroke: currentColor;
animation: spinnerDash 1500ms ease-in-out infinite;
}
@keyframes spinnerRotate {
100% {
transform: rotate(360deg);
}
}
@keyframes spinnerDash {
0% {
stroke-dasharray: 1, 200;
stroke-dashoffset: 0;
}
50% {
stroke-dasharray: 89, 200;
stroke-dashoffset: -35;
}
100% {
stroke-dasharray: 89, 200;
stroke-dashoffset: -136;
}
}
import './spinner.scss';
export interface ISpinner {
label?: string;
}
export interface ISpinnerProps {
data?: ISpinner;
className?: string;
}
export default class Spinner {
static render(props?: ISpinnerProps): string {
const { data = {}, className }: ISpinnerProps = props;
const { label = 'Loading' }: ISpinner = data;
const classArray: string[] = ['spinner'];
if (className) {
classArray.push(className);
}
return '<div class="' + classArray.join(' ') + '" aria-label="' + label + '"><svg class="spinner__circle" viewBox="25 25 50 50"><circle class="spinner__path" cx="50" cy="50" r="22" fill="none"></circle></svg></div>';
}
}