bigbullui logobigbullui
Componentfeedback

LoadingDots

Three dots bounce in sequence with keyframe animation; sizes sm/md/lg and tone prop.

Preview

Live Preview

Installation

Tokens guide →

Add to your project via CLI (zero dependencies, code you own):

npx bigbullui add loading-dots

Or install the full npm package:

npm install bigbullui

Usage

import { LoadingDots } from "@/components/ui/loading-dots"

<LoadingDots size="md" tone="default" />

Source code

loading-dots.tsx

Zero dependencies (only React + utils). Copy and paste directly into your project:

"use client";

import * as React from "react";
import { cn } from "./lib/utils";

const loadingDotsBounceKeyframes = `
  @keyframes loadingDotsBounce {
    0%, 80%, 100% { transform: translateY(0); }
    40% { transform: translateY(-8px); }
  }
`;

export type LoadingDotsProps = {
  size?: "sm" | "md" | "lg";
  tone?: "default" | "accent" | "destructive";
};

function getSizeClass(size: LoadingDotsProps["size"]): string {
  switch (size) {
    case "sm":
      return "w-2 h-2";
    case "lg":
      return "w-4 h-4";
    default:
      return "w-3 h-3";
  }
}

function getToneClass(tone: LoadingDotsProps["tone"]): string {
  switch (tone) {
    case "accent":
      return "text-accent";
    case "destructive":
      return "text-destructive";
    default:
      return "text-muted-foreground";
  }
}

export function LoadingDots({ size = "md", tone = "default" }: LoadingDotsProps) {
  const sizeClass = getSizeClass(size);
  const toneClass = getToneClass(tone);

  return (
    <div className={cn("flex items-center gap-2", "motion-reduce:animate-none")}>
      <style>{loadingDotsBounceKeyframes}</style>
      {[0, 1, 2].map((i) => (
        <div
          key={i}
          className={cn(sizeClass, "rounded-full bg-current", toneClass, "animate-[loadingDotsBounce_1.2s_ease-in-out_infinite]", "motion-reduce:animate-none")}
          style={{ animationDelay: `${i * 160}ms` }}
        />
      ))}
    </div>
  );
}

Props

PropTypeDescription
size"sm" | "md" | "lg"Size of the dots.
tone"default" | "accent" | "destructive"Color tone of the dots.