← All components
Motion / effect

Voice Glow

Light, dots and wireframe landscapes give sound a physical presence. Four complete contexts, one full voice engine.

Live preview
Preparing preview…

Take it with you.

SOURCE ACCESS

Preview freely. Unlock the files.

Enter the shared password to copy the complete source, download every file, and install components in your app.

Access lasts 24 hours. Your preview settings stay with you.

Component notes

  • Three complete looks retain the full engine: Glow uses eight palettes and typed custom lobe/band colors; Dots and Lines share the perspective, gravity and surface model. The palette control applies only to Glow.
  • Composer, Recording pill, Phone and Processing are original portable contexts. Primitive usage includes a sized host. For your own content, import VoiceBeam and supply a child; type selects tuned defaults, and explicit geometry props override those defaults.
  • Simulation and manual input require no permission. Use microphone is an explicit local action in the Complete audio contexts; capture is neither recorded, uploaded nor persisted. Processing never requests devices. Stop, signal-mode/scene change and unmount dispose owned tracks, including late grants.
  • Controlled source accepts caller-owned streams, number or getter level, and callbacks. Borrowed tracks are never stopped. Advanced source demonstrates a getter, custom colors, band colors and typed geometry; its custom palette is authored separately from the scalar palette control.
  • The full typed API below covers every public option: geometry, envelope, processing, styling and callbacks. Additional per-layer/band/core/hue tuning, colors, bandColors, style, css, streams and callbacks are supplied in React code through VoiceBeamProps, never scalar metadata. Examples.tsx, ControlledExample.tsx, AdvancedExample.tsx and types.ts are included in every distribution.
  • Appearance and Pause preserve drafts and the signal clock; Replay restarts decoration without remounting local work. Reduced motion, hidden and offscreen instances stop continuous frames. Per-instance surface work is bounded; physical FPS and cross-browser certification are not claimed.
  • Legacy Demo.tsx retains its existing mode, level, colorVariant, reach and glowSize interface. Full MIT notices and portable shared lifecycle helpers are required. No paid recipes or reference artwork are included.
React 19.2Modern browsers

Libraries.dev — Jakub Antalik · MIT. See bundled notice.

Props

PropTypeDefaultDescription
children (required)ReactNodeundefinedContent to wrap with the voice beam effect
typeVoiceBeamType'default'Host preset: 'default' (chat input), 'pill' (recording pill) or 'mobile' (bottom of a phone screen). Sets the defaults of the geometry props below for that host; any prop you pass still wins.
lookVoiceBeamLook'glow'How the voice is drawn: coloured light, or a surface of dots or lines that the voice raises and gravity brings down.
dotSizenumber1Dot radius, as a multiplier on the tuned size. `look="dots"` only.
dotGapnumber1Spacing between dots, as a multiplier — below 1 is a denser, finer surface, above 1 a sparser, coarser one. `look="dots"` only.
dotShapeVoiceBeamDotShape'round'The dots' shape: round, or square for a pixel grid. `look="dots"` only.
lineWidthnumber1Line width, as a multiplier on the tuned width (lines thin out into the distance). `look="lines"` only.
lineGapnumber1Spacing between lines, as a multiplier — the rows and the columns alike. `look="lines"` only.
linePatternVoiceBeamLinePattern'rows'Which way the lines run: across the surface, into the depth, or both. `look="lines"` only.
seeThroughbooleanfalseDraw the lines as a wireframe: those behind a raised ridge show through it instead of being hidden by it. `look="lines"` only.
texturenumber0.6Organic texture, 0–1: a slow ripple the flow carries across the surface. 0 is a still sheet that only the voice moves. Dots and lines.
gravitynumber1How hard the surface falls when the voice drops, as a multiplier on its gravity. Lower floats down, higher drops like sand. Dots and lines.
surfaceHeightnumber1How tall the surface stands along the bottom, as a multiplier — how far back the sheet runs, and so how much of the host it covers. Dots and lines.
surfaceCurvenumber1How far the surface arcs, as a multiplier: its sides and far edge fall away like a horizon. 0 is a flat sheet; below 0 it cups upward instead. Dots and lines.
surfaceTailnumber0The surface's tails: how far its ends rise toward the corners, as a share of the sheet's height — the ends curl up into the host's corners instead of running flat into its sides. Below 0 they drop away instead. Dots and lines.
surfaceTailPositionnumber0.6Where the tails start, as a share of the distance from the centre to the side (0.8 = only the last 20%); they reach their full lift at the edge.
surfaceTailCurvenumber2.4Exponent of the tails' rise: 1 a straight ramp, 2 a parabola, higher a hook that stays low and whips up at the edge.
surfaceFadenumber0.2How far in from the sides the surface dissolves, as a share of its half-width, 0–1. 0 runs it hard into the edges; 1 fades it from the centre out. Dots and lines.
scalenumber1 (0.45 for `type="pill"`)Size of the whole effect. Multiplies every pixel dimension at once — lobes, their spacing, the visible range, the bend, the band, the core, the bloom blur, the flow speed — so the glow grows or shrinks as one thing, on top of the type preset and the individual geometry props.
streamMediaStream | nullundefinedAudio to react to. When set, the beam analyses this stream (level plus low / mid / high bands) and ignores `level`. Get one from the application’s `getUserMedia` / WebRTC capture flow or `useVoiceCapture`.
levelVoiceBeamLevel0Manual drive, 0–1, used when no `stream` is given. A number re-renders on change; a getter is sampled once per frame without re-rendering.
sensitivitynumber3.1Input gain on the analysed audio. The default suits a laptop microphone at conversational distance; raise it for quiet sources, lower it for a close or hot one.
thresholdnumber0.015Noise gate, 0–1. Levels below it read as silence, so room hum and fan noise do not keep the beam twitching.
attacknumber0.325Seconds the glow takes to rise toward a louder level.
releasenumber0.86Seconds the glow takes to settle after the sound drops.
idlenumber0.23Resting presence, 0–1 — how much the beam breathes while silent so it never looks dead. 0 hides it completely between sounds.
breatheDurationnumber5.2Period of the idle breathing in seconds.
reachnumber1.2 (1.8 on the light theme; 1.35 for `pill`, 3 for `mobile`)How tall the glow grows at full level, as a multiple of its resting height. The rise is centered on the bottom edge.
spreadnumber1.05 (0.8 on the light theme; 1.1 for `pill`, 0.45 for `mobile`)How far the glow widens at full level, as a fraction of its resting width. Side lobes drift outward as well, so a loud sound spreads.
bandsbooleantrueLet the low / mid / high bands move the colored lobes independently (center follows the lows, the sides the mids and highs). With a manual `level` the bands are synthesised from the level, so the lobes still dance. Off, every lobe follows the one level.
flownumber48How fast the spectrum travels sideways, in px per second at full level — the lobes slide left to right while a voice is heard and rest when it stops, so every colour takes a turn at the centre. Negative flows right to left; 0 holds the lobes in place.
processingbooleanfalseProcessing state — turn it on once the voice has been captured and something is working on it. The lobes gather into one compact beam that travels the glow's range left to right and back, eased at each end and looped — border-beam's `line` type, confined to the voice glow — and the glow is held lit at `processingLevel` so the beam has colour. Both blend in and out smoothly. The distortion settles out in about a quarter second and stays off while processing.
processingDurationnumber1.1 (1.05 for `type="mobile"`)Seconds for one pass of the processing beam (left to right, or back again).
processingLevelnumber0.55 (0.35 for `type="mobile"`)How lit the glow is held while processing, 0–1, as if a voice were speaking at that level.
processingEasenumber0.6Seconds the morph between the voice glow and the travelling beam takes, in either direction — the gather, the narrowing and the travel ease in and out over it.
processingTravelnumber1.55 (2 for `pill`, 1 for `mobile`)How far the processing beam travels to each side, as a multiple of half the lobe ring: 1 sweeps the glow's resting spread, lower keeps it near the centre, higher runs it out to the corners.
processingCurvenumber2.1How the processing beam eases into each turn of its sweep: 1 runs at a constant speed and turns sharply, 2 slows smoothly into the ends, higher dwells there longer before heading back.
cornerFollownumber0.45 (0 for `type="pill"`, 0.4 for `type="mobile"`)How much the coloured glow rides the element's corner arcs while processing, 0–1: 0 keeps it flat along the bottom edge, 1 lifts it along the rounded corner as it passes through. The band line follows the corner either way.
colorVariantVoiceBeamColorVariant'colorful'Color variant for the beam
colorsstring[]undefinedYour own lobe colours, centre first then the pairs outward — up to seven, any CSS hex or rgb. Slots you leave out (or that fail to parse) keep the variant's colour for the theme.
bandColors{ core?: string; above?: string; mid?: string; below?: string }undefinedThe band's colours: the core ridge and its chromatic fringes above, between and below. Any CSS hex or rgb; unset ones keep the theme's defaults (white core with red / green / blue fringes on dark, a pink core with rose / lavender / sky on light).
themeVoiceBeamTheme'dark'Theme mode — adapts beam colors for dark or light backgrounds; 'auto' follows prefers-color-scheme
staticColorsbooleanfalseDisable the slow hue drift for static colors
hueRangenumber24 (dark) / 40 (light)Hue drift range in degrees (the palette wanders ± this far)
hueDurationnumber12 (dark) / 8.5 (light)Period of the hue drift in seconds
activebooleantrueWhether the effect is on. Off fades the beam out and stops the audio analysis.
pausedbooleanfalseFreezes the effect where it is — the glow, the band and the audio analysis all hold their last frame — without fading it out. Other props still shape the held frame, and the clocks resume where they stopped.
replayTokennumberundefinedChange to reset the effect without remounting wrapped content.
borderRadiusnumberundefinedCustom border radius in pixels. When omitted, the component auto-detects the border-radius of the first child element.
brightnessnumber1.15 (dark chat input) / 0.95 (light); the dark theme itself is 1.1, `pill` runs 1.35, `mobile` 1.2 on darkBrightness multiplier for the glow
saturationnumber1.2 (dark) / 1.6 (light); `pill` and `mobile` run 1.5 on darkSaturation multiplier for the glow
glowSizenumber1Multiplies the bloom blur radius, so the halo reads tighter (< 1) or wider and softer (> 1).
strokeOpacitynumber1Per-layer opacity multipliers on the theme's own: the crisp edge stroke, the soft inner light and the blurred bloom. The same knobs as the `--voice-stroke-opacity` / `--voice-inner-opacity` / `--voice-bloom-opacity` CSS hooks.
innerOpacitynumberundefinedTyped primitive option. See the included canonical types and Advanced example for composition.
bloomOpacitynumberundefinedTyped primitive option. See the included canonical types and Advanced example for composition.
bendnumber60Bend — how much, in px, the glow's top contour humps up at the centre at full level. The ceiling the glow is masked to gains that height in the middle and none at the ends, and a faint rim traces the curve, so the glow's outline bows upward with the voice like space bending around it. 0 keeps the contour at its plain ellipse.
bandStrengthnumber1.55 (1.8 for `mobile`; on light 1.7, or 2 for `pill`)Opacity of the band, 0 hides it.
bandWidthnumber2.15Thickness of the band.
bandPositionnumber0.35Height of the band's peak as a fraction of the glow's ceiling, 0.1–1.3.
bandCurvenumber1.75Bell exponent: below 2 an exponential, cusp-like rise; 2 a gaussian; above, a flatter top.
bandSpreadnumber0.87Bell width as a fraction of the glow's half-range: small is a narrow spike with long tails, large a broad dome.
bandSkewnumber0.12Asymmetry, −0.6–0.6: positive widens the right side and steepens the left.
bandOffsetnumber-27Vertical shift of the whole band line in px; negative sinks it toward the edge.
bandTailnumber0.59 (0 for `pill`)How far the band's ends rise again toward the corners, as a fraction of its peak, 0–1 — the line opens upward at the edges instead of dying flat.
bandTailPositionnumber0.67Where the tail's rise starts, as a share of the distance from the beam's centre to the element's edge (0.85 = only the last 15%); it always reaches the full lift exactly at the corner.
bandTailCurvenumber2.4Exponent of the rise: 1 a straight ramp, 2 a parabola, higher a hook that stays low and whips up at the corner.
bandTailOverflownumber15Px the band runs past each side of the element, so the hook peaks outside and is cropped by the component's edge. Scales with `scale`.
bandAberrationnumber0.89Chromatic aberration — how far the red and blue fringes split from the core, 0–1.
distortionnumber0.62Distortion — how much the glow under the band warps sideways, 0–1. A slowly drifting noise field displaces the inner light and the bloom horizontally, stronger as the voice rises, so the colours shimmer and stretch like light through bent space. Only the glow UNDER the band line warps — the layers are split at the line — and it is independent of `bandStrength`, so the line can be invisible and the warp strong. The edge stroke stays crisp. 0 turns the filter off entirely.
distortionDetailnumber2.3Grain of the distortion's noise: below 1 broad slow waves, above 1 finer ripples.
glowWidthnumber0.65Width of every colour lobe, all layers — on the dots and lines, the width of each hill.
glowHeightnumber1.25Height of every colour lobe, all layers.
lobeSpacingnumber0.85Distance between the lobes (and the ring the flow travels) — on the dots and lines, between the hills.
rangeWidthnumber0.75Width of the visible ellipse the glow is masked to.
rangeHeightnumber1Height of the visible ellipse the glow is masked to.
softnessnumber1.07Where each lobe fades out — below 1 crisper, above 1 softer.
coreSizenumber1The white hot spot at the centre of the edge.
coreLightnumber0 (1.8 on the light theme)The epicentre: a soft white wash under the band line at the centre of the edge, so the source reads lighter than the band. 0–3: up to 1 the wash's opacity, past 1 its solid white core widens and the whole wash grows, washing out more of the colour beneath.
coreLightWidthnumber1Width of the epicentre wash.
coreLightHeightnumber1Height of the epicentre wash.
strokeScalenumber1Size of the colours painted into the 1px edge stroke.
innerScalenumber1Size of the soft light inside the element.
innerHeightnumber1Extra height of the inner light — how far it reaches into the element.
bloomScalenumber1Size of the blurred halo.
bloomHeightnumber1Extra height of the halo — how far the soft light climbs.
strengthnumber1 (dark) / 0.8 (light); 1 on both for `type="mobile"`Overall strength/opacity of the effect (0–1). Only affects the beam layers — not the children.
classNamestringundefinedAdditional class name for the container
styleCSSPropertiesundefinedAdditional inline styles for the container
cssstringundefinedExtra CSS appended after the beam's own generated stylesheet. Write `{id}` wherever the instance id belongs — the root is `[data-voice-beam="{id}"]`, its layers the `::before` / `::after` pseudo-elements and `[data-voice-beam-bloom]`, and keyframes are named `*-{id}` — and it is substituted per instance.
onLevel(level: number) => voidundefinedCalled every frame with the smoothed level (0–1) the beam is showing. Handy for a meter or a "listening" label; avoid setting React state from it on every call.
onActivate() => voidundefinedCallback when the fade-in completes
onDeactivate() => voidundefinedCallback when the fade-out completes