WebberUI

Karaoke Text

Lyric lines colored character by character along a timeline, with the current line scaled up in focus.

Multiple lyric lines play along a timeline: the current line scales up in focus, a gradient sweeps its characters from left to right, sung lines fade out and drift up, and the whole sheet scrolls automatically to keep the current line centered. Play, pause, and restart controls are built in, and playing can also be fully controlled — well suited to music product pages, lyric showcases, and rhythmic taglines.

Loading preview…
npx shadcn@latest add https://webberui.com/r/karaoke-text.json

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

2400
1.12
240
<KaraokeText />

Installation

npx shadcn@latest add https://webberui.com/r/karaoke-text.json

Or, once registries are configured in components.json, install it as @webberui/karaoke-text.

Usage

import { KaraokeText } from "@/components/ui/karaoke-text";

<KaraokeText
  lines={[
    { text: "The first line of the lyrics", duration: 2400 },
    { text: "The second line of the lyrics", duration: 2600 },
    { text: "The third line of the lyrics" },
  ]}
  height={220}
  className="text-xl font-semibold"
/>

Props

PropTypeDefaultDescription
linesKaraokeLine[]Array of lyric lines, where KaraokeLine is { text: string; duration?: number } (milliseconds)
playingbooleanControlled playback state; when omitted, the component manages it internally
onPlayingChange(playing: boolean) => voidcallback for playback state changes (fired on control clicks and when playback ends)
autoPlaybooleantrueWhether playback starts automatically in uncontrolled mode
loopbooleantrueWhether to loop back to the start after the last line
showControlsbooleantrueWhether to show the built-in play / pause / restart control bar
heightnumber240Height of the lyric viewport (px); the current line auto-scrolls to the center
defaultDurationnumber2400Default duration for lines with no duration (milliseconds)
activeScalenumber1.12Scale factor of the current line
baseClassNamestringgreyscale text colorClass for the color of text not yet sung
fillClassNamestringamber → rose → fuchsia gradientClass for the gradient fill of sung text (colored via bg-clip-text)
onLineChange(index: number) => voidcallback fired when the current line index changes
classNamestringforwarded to the outermost container; font size and weight are inherited by the lyric lines

Accessibility

  • When the user has "reduce motion" enabled at the system level, there is no per-character sweep, scaling, or blur — the current line is simply highlighted with the full fill, and lines still advance along the timeline
  • The underlying lyrics are real text that the screen reader can announce; the gradient fill layer is a decorative copy marked aria-hidden
  • The play, pause, and restart buttons all carry an aria-label, and the current line number is shown (for example 03 / 06) as a visual confirmation
  • rAF pauses automatically when the tab goes to the background, and resumes with a clamped time delta on return, so it never jumps lines

On this page