@gfazioli/mantine-audio
A Mantine-native audio player for React with waveform visualization and live spectrum analyzer, built on Web Audio API. Compound component API + headless useAudio hook.
Installation
After installation import package styles at the root of your application:
You can import styles within a layer @layer mantine-audio by importing @gfazioli/mantine-audio/styles.layer.css.
Overview
@gfazioli/mantine-audio is a Mantine-native audio player for React with waveform visualisation and a live spectrum analyser, built on the Web Audio API. It ships as three layers in one package:
- A polished default
<Audio />component with four built-in variants (overlay,minimal,floating,bordered) - A composable compound API — ten sub-components you can reorder, replace or restyle:
Audio.Controls,Audio.PlayButton,Audio.SkipButton,Audio.Timeline,Audio.TimeDisplay,Audio.MuteButton,Audio.VolumeSlider,Audio.SpeedControl,Audio.Waveform,Audio.Spectrum - A fully headless
useAudiohook that returns state, actions, the decoded peaks and theAnalyserNodefor building 100% custom UIs
Usage
Drop a single line and you have a styled, accessible audio player wired to the native <audio> element:
0:00 / 0:00
Configurator
Explore the available props in isolation:
0:00 / 0:00
Sizes
The size prop scales the entire player — padding, icon size, play button, timeline thumb, time display width, volume slider width, and font size. Available presets: xs, sm, md (default), lg, xl. Pair it with variant for fine layout control.
size = xs
0:00 / 0:00
size = sm
0:00 / 0:00
size = md
0:00 / 0:00
size = lg
0:00 / 0:00
size = xl
0:00 / 0:00
Compound API
The default control bar is <Audio.Controls>. Replace it with any combination of sub-components — they all read state from the shared context provided by the parent <Audio>:
Custom layout
The default <Audio.Controls /> is just a horizontal row. Because every sub-component is a free-standing piece reading state from the shared context, you can drop the default control bar (controls={false}) and arrange the parts however you want — reorder, group, stack vertically, mix with any layout primitive from @mantine/core. No new prop required.
1. Default
0:00 / 0:00
2. Two-row (waveform on top, controls below)
0:00 / 0:00
3. Vertical (manual layout with Stack + Group)
0:00 / 0:00
Waveform
Audio.Waveform renders the audio file's peaks on a <canvas>. The peaks are decoded once via fetch + decodeAudioData and downsampled to waveformSamples (default 512). Click or drag on the waveform to seek. The played/unplayed boundary tracks the playhead at 60fps via requestAnimationFrame, not at the slower timeupdate cadence.
0:00 / 0:00
Remote files must be served with permissive CORS headers (
Access-Control-Allow-Origin) for the decode to succeed. When the decode fails the waveform degrades to an empty bar — the rest of the player keeps working.
Play with the available props live:
0:00 / 0:00
Spectrum
Audio.Spectrum is a live frequency-domain visualiser driven by Web Audio's AnalyserNode. The AudioContext is lazy-initialised on the first play to comply with browsers' autoplay policies. Hit play and the bars react to the music in real time.
0:00 / 0:00
Set fftSize on the parent <Audio> to tune resolution (must be a power of two between 32 and 32768; default 256). Set colorMode="gradient" for a vertical gradient from --audio-spectrum-bar-color (top) to --audio-spectrum-bar-color-fade (bottom, default transparent). Set mirror to render the bars symmetrically around the vertical center for a classic equalizer look.
0:00 / 0:00
Volume & Speed
Audio.VolumeSlider is a 0–100% Mantine Slider bound to volume. Audio.SpeedControl opens a menu with the configured preset speeds (default [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]).
asBackground
Use the same player as an ambient background track in a hero section:
In this mode the controls and shortcuts are disabled by default and a small floating mute toggle is rendered in the bottom-right corner (disable it with backgroundMuteButton={false}).
Multiple sources
For cross-browser compatibility, adaptive bitrate, or media-query-driven switching, use the sources prop instead of src. The browser picks the first entry whose type it can play via canPlayType():
Adaptive bitrate via HLS (Safari native, others via hls.js attached to src):
Media-query-based switching (e.g. lower bitrate on mobile):
src and sources are mutually exclusive — if both are set, sources wins and a dev-mode warning is logged.
Runtime fallback
If every entry in src / sources fails to load at runtime (the <audio> element fires its error event — typically a 404 or decode error), the component swaps to fallbackSrc. This mirrors the equivalent prop on Mantine Image.
Note on waveform with sources
Audio.Waveform decodes peaks from the URL the browser actually picked (audioRef.currentSrc, available after loadedmetadata). For HLS / DASH streams, the decode bypasses the streaming layer and may not work — the rest of the player keeps working.
Headless usage
When the default layout doesn't fit, drop the compound layer entirely and drive your own UI from useAudio:
The hook exposes 16 state values (playing, currentTime, duration, volume, muted, playbackRate, peaks, analyser, …) and 12 action functions (play, pause, toggle, seek, seekBy, setVolume, mute, unmute, toggleMute, setPlaybackRate, …).
Keyboard shortcuts
When shortcuts is true (default) and the player is focused:
| Key | Action |
|---|---|
| Space / K | Play / pause |
| J / ← | Seek backward (10s / 5s) |
| L / → | Seek forward (10s / 5s) |
| ↑ / ↓ | Volume +/− 5% |
| M | Toggle mute |
| > / . | Speed +0.25× |
| < / , | Speed −0.25× |
Styles API
Audio supports the Mantine Styles API. You can target every part of the compound (root, controls, controlBar, playButton, timeline, waveform, spectrum, …) with classNames and styles props, or override CSS variables with vars.
0:00 / 0:00
Component Styles API
Hover over selectors to highlight corresponding elements
Use cases
Real-world layouts assembled from size + variant + compound sub-components:
1. Inline message (chat / voice note)
0:00 / 0:00
2. Podcast card (cover + waveform)
The Mantine Show — Episode #42
Custom components without losing your mind
0:00 / 0:00
3. Mini sticky bar (variant=minimal)
0:00 / 0:00
4. Studio scrub (large waveform + scrubSound)
0:00 / 0:00