GitHub

Bobbing dots

Motion-driven dots that bounce in phase—playful loading for creative tools, media, and lighthearted flows.

Loading
import { BobbingDots } from "@/components/loading-ui/bobbing-dots";

export function BobbingDotsDemo() {

Installation

pnpm dlx shadcn@latest add @loading-ui/bobbing-dots

The registry entry pulls in Motion (motion); the CLI step should install it alongside the component.

Usage

import { BobbingDots } from "@/components/loading-ui/bobbing-dots";
<BobbingDots />

Customization

BobbingDots mirrors Dots layout: percentage gap, grow dots, and bg-current (inherited foreground). Vertical motion is handled by Motion with a staggered delay per index. Use duration (seconds, default 1) to speed up or slow the bounce without touching the keyframes.

Size

Scale the row with width utilities; larger widths give each dot more room to travel visually.

LoadingLoadingLoadingLoading
import { BobbingDots } from "@/components/loading-ui/bobbing-dots";

export function BobbingDotsSize() {

Color

Three vivid hex swatches—same idea as the blinking Dots showcase.

LoadingLoadingLoading
import { BobbingDots } from "@/components/loading-ui/bobbing-dots";

export function BobbingDotsColor() {

Duration

Pass duration as a number of seconds. Lower values feel snappier; higher values feel floatier.

LoadingLoadingLoading
import { BobbingDots } from "@/components/loading-ui/bobbing-dots";

export function BobbingDotsDuration() {

Dot count

More dots add rhythm; keep widths generous so the bounce does not feel cramped.

LoadingLoadingLoading
import { BobbingDots } from "@/components/loading-ui/bobbing-dots";

export function BobbingDotsCount() {

Examples

Mix surfaces so the motion never feels copy-pasted: dashed alerts, sheets with breathing room, tabs with soft gradients, and popovers for micro-delights.

Button

Spacing the label with gap-2 keeps the bounce from colliding with button text.

import { Button } from "@/components/ui/button";
import { BobbingDots } from "@/components/loading-ui/bobbing-dots";

Badge

Gradient-backed badges sell “play mode” energy without extra illustration.

LoadingPlay modeLoadingBouncy beta
import { Badge } from "@/components/ui/badge";
import { BobbingDots } from "@/components/loading-ui/bobbing-dots";

Sheet

Centered motion plus a sentence of context helps mobile-friendly workflows feel guided.

import { Button } from "@/components/ui/button";
import {
  Sheet,

Tabs

Let one tab hold the hero preview while the other stays lightweight—users can switch without losing the playful loop.

Loading

Rendering motion study

Tab away—the bounce keeps looping so the panel feels alive.

import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { BobbingDots } from "@/components/loading-ui/bobbing-dots";

Popover

Keep copy short; the dots are the star of this transient surface.

import { Button } from "@/components/ui/button";
import {
  Popover,