+ {[...Array(8)].map((_, i) => (
+
+ ))}
+
+ )
+}
diff --git a/packages/design-system/lib/components/Spinner/index.ts b/packages/design-system/lib/components/Spinner/index.ts
new file mode 100644
index 000000000..fbf16c1fa
--- /dev/null
+++ b/packages/design-system/lib/components/Spinner/index.ts
@@ -0,0 +1 @@
+export { Spinner } from './Spinner'
diff --git a/packages/design-system/lib/components/Spinner/spinner.module.css b/packages/design-system/lib/components/Spinner/spinner.module.css
new file mode 100644
index 000000000..dd60a9f04
--- /dev/null
+++ b/packages/design-system/lib/components/Spinner/spinner.module.css
@@ -0,0 +1,92 @@
+.spinner {
+ display: inline-block;
+ position: relative;
+
+ --size: 20px;
+ --dot-size: 3px;
+
+ width: var(--size);
+ height: var(--size);
+}
+
+.size-small {
+ --size: 20px;
+}
+
+.size-medium {
+ --size: 30px;
+ --dot-size: 5px;
+}
+
+.size-large {
+ --size: 40px;
+ --dot-size: 6px;
+}
+
+.spinner .dot {
+ transform-origin: calc(var(--size) / 2) calc(var(--size) / 2);
+ animation: spinnerAnimation 0.8s linear infinite;
+}
+
+.spinner .dot::after {
+ content: ' ';
+ display: block;
+ position: absolute;
+ top: calc(var(--dot-size) / 2);
+ left: var(--dot-size);
+ width: var(--dot-size);
+ height: var(--dot-size);
+ border-radius: 50%;
+ background-color: currentColor;
+}
+
+.accent .dot::after {
+ background-color: var(--Icon-Interactive-Default);
+}
+
+.inverted .dot::after {
+ background-color: var(--Icon-Inverted);
+}
+
+.dot:nth-child(1) {
+ transform: rotate(0deg);
+ animation-delay: -0.7s;
+}
+
+.dot:nth-child(2) {
+ transform: rotate(45deg);
+ animation-delay: -0.6s;
+}
+.dot:nth-child(3) {
+ transform: rotate(90deg);
+ animation-delay: -0.5s;
+}
+.dot:nth-child(4) {
+ transform: rotate(135deg);
+ animation-delay: -0.4s;
+}
+.dot:nth-child(5) {
+ transform: rotate(180deg);
+ animation-delay: -0.3s;
+}
+.dot:nth-child(6) {
+ transform: rotate(225deg);
+ animation-delay: -0.2s;
+}
+.dot:nth-child(7) {
+ transform: rotate(270deg);
+ animation-delay: -0.1s;
+}
+.dot:nth-child(8) {
+ transform: rotate(315deg);
+ animation-delay: 0s;
+}
+
+@keyframes spinnerAnimation {
+ 0% {
+ opacity: 1;
+ }
+ 100% {
+ opacity: 0;
+ }
+}
diff --git a/packages/design-system/lib/components/Spinner/variants.ts b/packages/design-system/lib/components/Spinner/variants.ts
new file mode 100644
index 000000000..87e2764e5
--- /dev/null
+++ b/packages/design-system/lib/components/Spinner/variants.ts
@@ -0,0 +1,24 @@
+import { cva } from 'class-variance-authority'
+
+import styles from './spinner.module.css'
+
+export const config = {
+ variants: {
+ color: {
+ Accent: styles.accent,
+ Inverted: styles.inverted,
+ CurrentColor: 'currentColor',
+ },
+ size: {
+ Small: styles['size-small'],
+ Medium: styles['size-medium'],
+ Large: styles['size-large'],
+ },
+ },
+ defaultVariants: {
+ color: 'Accent',
+ size: 'Medium',
+ },
+} as const
+
+export const variants = cva(styles.spinner, config)