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 ProHow 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.