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,