Skip to content
Black FridayBlack Friday launch price: Lifetime $149 until 30 Nov. Regular price $299 from 1 Dec.ends in 15d 03:13:36Get Lifetime →
loopkit
proNew170 lines · framer-motion

Bars Wave

An equalizer loader that rides its own sine wave. A full-width showcase section for an equalizer-style loader: a row of bars rises and falls on a looping sine wave, each bar phase-shifted from the next, with a real Play/Pause toggle under the showcase.

Use it for
Demoing a processing, syncing or voice/audio-activity state on a status page, changelog or component docs page.
Themes
Light + dark
License
Commercial use
Live
Status

A loader that never skips a beat

A row of bars rides a looping sine wave, so people can feel work happening instead of staring at a frozen spinner.

tsx
"use client";

import * as React from "react";
import { useInView, useReducedMotion } from "framer-motion";
import { cn } from "@/lib/utils";

function useReducedMotionSafe() {
  const prefersReduced = useReducedMotion();
  const [mounted, setMounted] = React.useState(false);
  React.useEffect(() => setMounted(true), []);
  return mounted ? !!prefersReduced : false;
}

/**
 * Full-width showcase section for an equalizer-style loader: a row of bars rides a
 * looping sine wave (CSS @keyframes, one bar per phase offset via animation-delay),
 * with a real Play/Pause toggle, a scroll/tab-aware pause, and reduced-motion support.
 */

export type LoaderBarsWaveColor = "signal" | "info" | "lime" | "ok";

export interface LoaderBarsWaveProps {

The rest is in Pro.

Full source, the rebuild prompt and registry install unlock with Pro or Lifetime.

Get Pro

How it behaves

  • →A CSS @keyframes animation scales each bar vertically from a shared curve; every bar gets a negative animation-delay proportional to its index, so the row reads as one travelling sine wave instead of bars bouncing in sync.
  • →barCount sets how many bars render (5-9); speed scales the shared animation duration; height sets the max bar height in px.
  • →color picks the design token (signal/info/lime/ok) used for the bar gradient, glow and the eyebrow dot, applied via a --lk-accent CSS variable so both themes stay correct.
  • →A real Play/Pause button (aria-pressed) toggles animation-play-state on every bar; pausing freezes each bar at its current phase, which already looks like a snapshot of the wave.
  • →The row also pauses when the section scrolls offscreen (useInView) or the tab is hidden (visibilitychange), independent of the Play/Pause state.
  • →prefers-reduced-motion starts the row paused on a settled frame instead of auto-looping; the Play button still works on demand.

Accessibility

  • ✓The bar row carries `role="img"` with an `aria-label` reporting whether the animation is playing or paused; individual bars are `aria-hidden`.
  • ✓The Play/Pause control is a real `<button>` with `aria-pressed` reflecting state, reachable and operable by keyboard with a visible focus ring.
  • ✓Headline and description are real text in a heading/paragraph, unaffected by the decorative animation.
  • ✓Honours prefers-reduced-motion.