Visual representation of audio amplitude.
<div class="wave wave--rounded" style="--accent:#E8A020;--gap:3px;" role="img" aria-label="Audio waveform, 40% played">
<div class="wave__track">
<span class="wave__bar"></span><span class="wave__bar"></span><span class="wave__bar"></span><span class="wave__bar"></span><span class="wave__bar"></span><span class="wave__bar"></span><span class="wave__bar"></span><span class="wave__bar"></span><span class="wave__bar"></span><span class="wave__bar"></span><span class="wave__bar"></span><span class="wave__bar"></span><span class="wave__bar"></span><span class="wave__bar"></span><span class="wave__bar"></span><span class="wave__bar"></span><span class="wave__bar"></span><span class="wave__bar"></span><span class="wave__bar"></span><span class="wave__bar"></span>
</div>
<div class="wave__played" style="clip-path:inset(0 calc(100% - 40%) 0 0);" aria-hidden="true">
<span class="wave__bar wave__bar--played"></span><span class="wave__bar wave__bar--played"></span><span class="wave__bar wave__bar--played"></span><span class="wave__bar wave__bar--played"></span><span class="wave__bar wave__bar--played"></span><span class="wave__bar wave__bar--played"></span><span class="wave__bar wave__bar--played"></span><span class="wave__bar wave__bar--played"></span><span class="wave__bar wave__bar--played"></span><span class="wave__bar wave__bar--played"></span><span class="wave__bar wave__bar--played"></span><span class="wave__bar wave__bar--played"></span><span class="wave__bar wave__bar--played"></span><span class="wave__bar wave__bar--played"></span><span class="wave__bar wave__bar--played"></span><span class="wave__bar wave__bar--played"></span><span class="wave__bar wave__bar--played"></span><span class="wave__bar wave__bar--played"></span><span class="wave__bar wave__bar--played"></span><span class="wave__bar wave__bar--played"></span>
</div>
</div>
<style>
.wave { position: relative; height: 48px; width: 100%; max-width: 340px; padding: 4px 0; }
.wave__track, .wave__played { position: absolute; inset: 0; display: flex; align-items: flex-end; gap: var(--gap); }
.wave__bar { flex: 1; background: #24143026; border-radius: 2px; }
.wave__bar--played { background: var(--accent); }
.wave--rounded .wave__bar { border-radius: 999px; }
.wave__bar:nth-child(4n+1) { height: 40%; }
.wave__bar:nth-child(4n+2) { height: 85%; }
.wave__bar:nth-child(4n+3) { height: 60%; }
.wave__bar:nth-child(4n) { height: 100%; }
.wave__bar:nth-child(3n) { height: 30%; }
</style><div class="wave-tw wave-tw--rounded relative h-12 max-w-[340px] py-1" style="--accent:#E8A020;--gap:3px;" role="img" aria-label="Audio waveform, 40% played">
<div class="wave-tw__track absolute inset-0 flex items-end" style="gap:var(--gap);">
<span class="wave-tw__bar"></span><span class="wave-tw__bar"></span><span class="wave-tw__bar"></span><span class="wave-tw__bar"></span><span class="wave-tw__bar"></span><span class="wave-tw__bar"></span><span class="wave-tw__bar"></span><span class="wave-tw__bar"></span><span class="wave-tw__bar"></span><span class="wave-tw__bar"></span><span class="wave-tw__bar"></span><span class="wave-tw__bar"></span><span class="wave-tw__bar"></span><span class="wave-tw__bar"></span><span class="wave-tw__bar"></span><span class="wave-tw__bar"></span><span class="wave-tw__bar"></span><span class="wave-tw__bar"></span><span class="wave-tw__bar"></span><span class="wave-tw__bar"></span>
</div>
<div class="absolute inset-0 flex items-end" style="gap:var(--gap);clip-path:inset(0 calc(100% - 40%) 0 0);" aria-hidden="true">
<span class="wave-tw__bar wave-tw__bar--played"></span><span class="wave-tw__bar wave-tw__bar--played"></span><span class="wave-tw__bar wave-tw__bar--played"></span><span class="wave-tw__bar wave-tw__bar--played"></span><span class="wave-tw__bar wave-tw__bar--played"></span><span class="wave-tw__bar wave-tw__bar--played"></span><span class="wave-tw__bar wave-tw__bar--played"></span><span class="wave-tw__bar wave-tw__bar--played"></span><span class="wave-tw__bar wave-tw__bar--played"></span><span class="wave-tw__bar wave-tw__bar--played"></span><span class="wave-tw__bar wave-tw__bar--played"></span><span class="wave-tw__bar wave-tw__bar--played"></span><span class="wave-tw__bar wave-tw__bar--played"></span><span class="wave-tw__bar wave-tw__bar--played"></span><span class="wave-tw__bar wave-tw__bar--played"></span><span class="wave-tw__bar wave-tw__bar--played"></span><span class="wave-tw__bar wave-tw__bar--played"></span><span class="wave-tw__bar wave-tw__bar--played"></span><span class="wave-tw__bar wave-tw__bar--played"></span><span class="wave-tw__bar wave-tw__bar--played"></span>
</div>
</div>
<style>
.wave-tw__bar { flex: 1; background: #24143026; border-radius: 2px; }
.wave-tw__bar--played { background: var(--accent); }
.wave-tw--rounded .wave-tw__bar { border-radius: 999px; }
.wave-tw__bar:nth-child(4n+1) { height: 40%; }
.wave-tw__bar:nth-child(4n+2) { height: 85%; }
.wave-tw__bar:nth-child(4n+3) { height: 60%; }
.wave-tw__bar:nth-child(4n) { height: 100%; }
.wave-tw__bar:nth-child(3n) { height: 30%; }
</style>export function Waveform({
accent = "#E8A020",
gap = 3,
playedPercent = 40,
rounded = true,
}) {
const heights = [40, 85, 60, 100, 30, 40, 85, 60, 100, 30, 40, 85, 60, 100, 30, 40, 85, 60, 100, 30];
const barStyle = (played) => ({
flex: 1,
background: played ? accent : "#24143026",
borderRadius: rounded ? 999 : 2,
});
return (
<div style={{ position: "relative", height: 48, maxWidth: 340, padding: "4px 0" }}
role="img" aria-label={`Audio waveform, ${playedPercent}% played`}>
<div style={{ position: "absolute", inset: 0, display: "flex", alignItems: "flex-end", gap }}>
{heights.map((h, i) => (
<span key={`track-${i}`} style={{ ...barStyle(false), height: `${h}%` }} />
))}
</div>
<div style={{ position: "absolute", inset: 0, display: "flex", alignItems: "flex-end", gap,
clipPath: `inset(0 calc(100% - ${playedPercent}%) 0 0)` }} aria-hidden="true">
{heights.map((h, i) => (
<span key={`played-${i}`} style={{ ...barStyle(true), height: `${h}%` }} />
))}
</div>
</div>
);
}