# Bouncing dots

> Three dots hopping one after another, with the familiar rhythm of “someone is typing”.

- Category: [Loaders](https://library.aimran.es/components/loaders)
- Built with: React + Motion
- Live editor: https://library.aimran.es/blocks/bouncing-dots
- Library: AIMRAN Library (https://library.aimran.es), free, no sign-up, by Aimran Oukham

## Where to use it

Three bouncing dots are the universal sign that someone is typing. Drop them into the chat bubble of a support widget, the reply area of an AI assistant or a messaging app while the other person writes. As a typing indicator it feels warmer than a spinner, because it hints at a person on the other side.

Keep the dots small, around the size of your body text, and use the same color as the text in the chat bubble. Slowing the speed a little makes it feel calmer; too fast and it looks like the app is panicking.

## Code

### React (Motion)

```tsx
import { motion } from "framer-motion";

interface BouncingDotsProps {
  color?: string;
  size?: number;
  /** Duración de un rebote en segundos. */
  speed?: number;
}

export default function BouncingDots({
  color = "#0071e3",
  size = 14,
  speed = 0.9,
}: BouncingDotsProps) {
  return (
    <div role="status" aria-label="Loading" className="flex items-center gap-2">
      {[0, 1, 2].map((i) => (
        <motion.div
          key={i}
          className="rounded-full"
          style={{ width: size, height: size, backgroundColor: color }}
          animate={{ y: [0, -size, 0] }}
          transition={{
            duration: speed,
            repeat: Infinity,
            delay: i * (speed / 6),
            ease: "easeInOut",
          }}
        />
      ))}
    </div>
  );
}
```

## Prompt for AI assistants

Paste this into ChatGPT, Claude, Cursor, v0 or Lovable to adapt the block to your stack (Tailwind, Vue, Svelte…):

````text
I want to add the “Bouncing dots” block (Loaders) from AIMRAN Library to my project.

## What it is
Three dots hopping one after another, with the familiar rhythm of “someone is typing”.

## Chosen settings
- Color: #0071e3
- Size: 14px (from 6 to 28px)
- Speed: 0.9s (from 0.4 to 2s)

## What I need
1. Add it to my project with the same look and animation as the reference code: same sizes, colours, radii, shadows, timings and easing.
2. It is built with React + TypeScript, with framer-motion for the animation and lucide-react for the icons. If my project uses something else (Vue, Svelte, Astro, plain HTML…), translate it without losing any behaviour. If I use Tailwind, turn the styles into classes; if not, keep the CSS in its own file.
3. Expose the settings above as props (or CSS variables) with those values as defaults.
4. Make it work well on phones: nothing that depends only on hover, touch targets of at least 44 px and no overflow on 320 px screens.
5. Make it look right in light and dark mode.
6. Keep it accessible: semantic HTML, roles and aria-* where needed, visible focus and keyboard support.
7. Respect prefers-reduced-motion: with reduced motion, no big animations but the same end result.

## Reference code
```tsx
import { motion } from "framer-motion";

interface BouncingDotsProps {
  color?: string;
  size?: number;
  /** Duración de un rebote en segundos. */
  speed?: number;
}

export default function BouncingDots({
  color = "#0071e3",
  size = 14,
  speed = 0.9,
}: BouncingDotsProps) {
  return (
    <div role="status" aria-label="Loading" className="flex items-center gap-2">
      {[0, 1, 2].map((i) => (
        <motion.div
          key={i}
          className="rounded-full"
          style={{ width: size, height: size, backgroundColor: color }}
          animate={{ y: [0, -size, 0] }}
          transition={{
            duration: speed,
            repeat: Infinity,
            delay: i * (speed / 6),
            ease: "easeInOut",
          }}
        />
      ))}
    </div>
  );
}
```

Give me the complete final code, ready to paste, and tell me in one line where to put it in my project.
````
