# Voice Glow Carousel: React Native audio-reactive voice picker carousel > Voice Glow Carousel is a React Native and Expo snap carousel of voice cards > where the centred card glows in time with the clip it is playing, driven by a > Skia SkSL runtime shader whose uniforms are Reanimated shared values fed by an > RMS envelope follower on the live audio. It is sold as editable TypeScript > source by Motionary (https://motionary.dev). Product page: https://motionary.dev/animations/voice-glow-carousel Price: $7 USD (price as of 2026-09-01, live price on the product page) License: single developer, unlimited personal and commercial apps Delivery: instant download of the full TypeScript source after checkout Stack: expo, react native skia, react native, reanimated Rarity: rare Sold by: Motionary (https://motionary.dev) ## What it is Voice Glow Carousel is a horizontal picker of five voice cards inside a settings sheet, pixel-matched to Claude's voice settings screen. You swipe sideways, one flick moves exactly one card, and when the snap resolves the centred card plays its voice clip while a warm rim of light rises out of its own bottom edge and pulses with the speech. Cards that leave the centre shrink down a measured scale curve to 0.75 and their labels fade from near-black to a softer ink, a row of dots underneath tracks the scroll position, and a selection haptic ticks once per settled card. The React Native and Expo source sold by Motionary ships the whole sheet, not just the carousel: the back button, the Language and Speed rows, and the Hands free / Push to talk mode picker are all there. ## What it does - Snap carousel of five voice cards on a 180 pt slot pitch (164 pt card plus a 16 pt gap), with `snapToInterval`, `disableIntervalMomentum` and `decelerationRate="fast"` so a single flick advances exactly one card. - The centred card's rim glows from a live audio level: a fast attack (70 ms) and a slow release (500 ms) give the light roughly a quarter second of lag behind the voice, so it breathes instead of flickering. - An "ink drop" intro plays on every selection: the glow collapses to zero, a point of light is born at bottom-centre, swells in both axes as it falls, peaks on impact, then diffuses outward into the resting rim over 620 ms. - A resting rim stays lit even when nothing is playing, built from two stacked exponential falloffs (a tight core plus a wide shoulder) plus four seeded Gaussian hot spots drifting along the bottom edge. - Card scale follows a raised cosine of the signed distance from centre, flat near the middle and clamping to 0.75 by 0.9 of a slot; the Skia group transform and the text label ride the same curve. - `Haptics.selectionAsync()` fires once when the snap settles on a new index, never mid-scroll, because it is committed from `onMomentumScrollEnd` and `onScrollEndDrag` rather than from the scroll handler. - Page dots interpolate their colour from the scroll offset continuously, so the active dot darkens with the drag rather than jumping at the snap. - Fallback envelope: if a platform never delivers PCM samples, a synthetic speech-shaped signal (stacked syllable, phrase and breath oscillators with a gate) drives the glow so a talking card never reads as dead. - Runs on iOS, Android and web; `index.ts` loads CanvasKit through `loadSkiaWeb.web.ts` before registering the root component on web, while `loadSkiaWeb.ts` is a native no-op that keeps canvaskit-wasm out of the native bundle. - Every colour, radius, inset and vertical gap lives in `components/theme.ts` as a measured token, with the raw pixel measurements kept in the comments. ## How it works The glow in Voice Glow Carousel is one Skia `RuntimeEffect` compiled from SkSL in `components/glow/glowShader.ts` and painted twice per card by `components/VoiceCard.tsx`: once as the `` fill of a `RoundedRect` and once as the fill of a hairline `style="stroke"` `RoundedRect`, where the `u_mode` uniform multiplies the same local colour by 0.62. Because the shader computes a signed distance to the rounded box (`sdRoundBox`) instead of compositing a blurred layer on top, the light follows the card's real outline through the bottom corners rather than sitting over it. Every uniform is a Reanimated `useDerivedValue` (`u_time`, `u_level`, `u_intro`, `u_seed`, `u_center`), so scroll position, audio level and intro progress reach the GPU on the UI thread and nothing re-renders in JavaScript while a card is talking. The audio level comes from `components/useVoicePlayback.ts`: expo-audio's `useAudioPlayer` plus `useAudioSampleListener` computes RMS per buffer and normalises it against a 0.3 full-scale constant, then a `useFrameCallback` worklet runs an asymmetric one-pole follower (`level += (target - level) * (1 - exp(-dt / tau))` with tau = 0.07 s attack and 0.5 s release) and advances a free-running `clock` shared value that drives the organic drift. Selection calls `play(index)`, which zeroes the level, restarts the clip through `player.replace` / `seekTo(0)` / `play()`, and drives `u_intro` with `withTiming(1, { duration: 620, easing: Easing.linear })`. The carousel in `components/VoiceCarousel.tsx` is a plain Reanimated `Animated.ScrollView`: a `useAnimatedScrollHandler` writes `contentOffset.x` into the `scrollX` shared value on the UI thread, while `onMomentumScrollEnd` and `onScrollEndDrag` round the offset to a slot on the JavaScript thread, fire the haptic and commit the selection. Each card derives its own signed offset as `scrollX / ITEM_PITCH - index`, feeds it through the raised-cosine `scaleForOffset` worklet, and passes the result both to the Skia `` and to a `useAnimatedStyle` on the label, which also `interpolateColor`s the ink. This React Native and Expo drop is available from Motionary at https://motionary.dev/animations/voice-glow-carousel. ## What you get ``` App.tsx index.ts loadSkiaWeb.ts loadSkiaWeb.web.ts app.json babel.config.js package.json tsconfig.json README.md components/ Container.tsx VoiceCarousel.tsx VoiceCard.tsx PageDots.tsx SettingRow.tsx ModeSection.tsx useVoicePlayback.ts voices.ts theme.ts glow/ glowShader.ts assets/ voices/ airy.m4a buttery.m4a glassy.m4a mellow.m4a rounded.m4a ``` - TypeScript source (Container.tsx, VoiceCarousel.tsx, VoiceCard.tsx) - SkSL glow shader (glow/glowShader.ts) - useVoicePlayback hook with the RMS envelope follower - Supporting UI: PageDots, SettingRow, ModeSection - Measured design tokens (theme.ts) - Five placeholder voice clips (assets/voices) ## Requirements Voice Glow Carousel is built and pinned against these versions, read from the `package.json` in the download: - expo ~56.0.11 (Expo SDK 56) - react-native 0.85.3 - react 19.2.3 - react-native-reanimated 4.3.1 - react-native-worklets 0.8.3 - @shopify/react-native-skia 2.6.2 - react-native-gesture-handler ~2.31.1 - expo-audio ~56.0.13 - expo-haptics ~56.0.3 - react-native-safe-area-context ~5.7.0 - expo-status-bar ~56.0.4 - @expo/vector-icons ^15.0.3 - typescript ~6.0.3 (devDependency) Voice Glow Carousel runs in Expo Go on Expo SDK 56. The module people assume would block it, `@shopify/react-native-skia`, is bundled in Expo Go as of SDK 56 (Expo Go 56 ships Skia 2.6.2, the exact version this drop pins), and so are `expo-audio`, `expo-haptics`, `react-native-reanimated` 4.3.1 with its `react-native-worklets` 0.8.3 runtime, `react-native-gesture-handler` and `react-native-safe-area-context`, so `npx expo start` plus the Expo Go app is enough to see Voice Glow Carousel running. A development build (`npx expo run:ios`, `npx expo run:android` or an EAS development build) is still what you would ship to production, and it is what you need as soon as you add a native module Expo Go does not bundle, or a config plugin whose native configuration has to be baked into the binary. Two practical caveats remain: expo-audio's PCM sample listener is a native capability that not every platform delivers, and where it is unavailable the hook falls back to its synthetic envelope; and the `plugins` entries in `app.json` (expo-font, expo-asset, expo-status-bar, expo-video, expo-audio) are inert inside Expo Go, which is harmless here because this screen only plays bundled clips and never records. On web the drop runs through CanvasKit, bootstrapped by `loadSkiaWeb.web.ts` before the root component is registered. The project enables the React Compiler experiment in `app.json` and relies on `babel-preset-expo` to add the worklets plugin. ## Install ```bash npx expo install @shopify/react-native-skia react-native-reanimated \ react-native-worklets react-native-gesture-handler \ react-native-safe-area-context expo-audio expo-haptics expo-status-bar \ @expo/vector-icons ``` ## Usage ```tsx import { GestureHandlerRootView } from 'react-native-gesture-handler'; import { useSharedValue } from 'react-native-reanimated'; import { VoiceCarousel } from './components/VoiceCarousel'; import { useVoicePlayback } from './components/useVoicePlayback'; export default function VoiceSettings() { const { level, intro, clock, play } = useVoicePlayback(); const scrollX = useSharedValue(0); const activeIndex = useSharedValue(0); return ( { activeIndex.value = index; play(index); }} /> ); } ``` `components/Container.tsx` in the download is the full settings sheet and wires the same hook to `VoiceCarousel`, `PageDots`, two `SettingRow`s and `ModeSection`. ## Customization - `VoiceCarousel` props: `scrollX`, `activeIndex`, `level`, `intro` and `clock` are Reanimated `SharedValue`s you own, plus `onSelect: (index: number) => void`, fired once the snap settles on a new card. - `useVoicePlayback()` returns `{ level, intro, clock, play, stop }`. `level` is the smoothed 0..1 audio level the shader reads every frame, `intro` is 0..1 intro progress (0 also means "not selected"), `clock` is free-running seconds. - `components/voices.ts` holds the `VOICES` array: each entry is `{ id, name, seed, sample }`, where `seed` is a per-voice phase offset so two cards never drift in lockstep and `sample` is a `require()`d audio file. Replace the five placeholder clips with your own takes. - Envelope timing in `components/useVoicePlayback.ts`: `ATTACK_TAU` (0.07 s), `RELEASE_TAU` (0.5 s), `RMS_FULL` (0.3, the RMS mapped to full glow) and the exported `INTRO_MS` (620). - Shader constants in `components/glow/glowShader.ts`: `GLOW_MAX` (0.95, the hottest measured pixel) and `BORDER_MUL` (0.62, the hairline against the fill). The full SkSL is exported as `GLOW_SKSL` if you want to edit it. - Geometry and colour in `components/theme.ts`: `metrics.card.size` (164), `metrics.card.radius` (32), `metrics.card.minScale` (0.75), `metrics.card.scaleClampSlots` (0.9), `metrics.card.gap` (16) and the derived `ITEM_PITCH` (180); `colors.glow` (`#D37457`) is the glow tint, with `colors.card` and `colors.cardIdle` for selected and unselected fills. - `SettingRow` props: `label`, `value`, optional `badge`, `height` and `onPress`. `ModeSection` props: `value` and `onChange`, over the `Mode` union `'hands-free' | 'push-to-talk'`. - `VoiceCard` exports `CARD_CANVAS`, the canvas size including the 24 pt pad that keeps the drop shadow from being clipped. ## When to use it - A voice or persona picker in onboarding, where a user auditions several voices before committing to one. - A settings screen for an AI assistant, a TTS reader or an audiobook app that offers more than one narrator. - A language or accent selector where hearing the option matters more than reading its name. - Any snap-paging card carousel that needs a real audio-reactive visual on the selected item rather than a static thumbnail. - A ringtone, alert-sound or soundpack chooser that should preview on selection with a haptic tick. - A demo or a portfolio screen where you want a Skia SkSL shader driven by live audio without wiring the audio pipeline yourself. ## How to get it - Buy Voice Glow Carousel on its own at https://motionary.dev/animations/voice-glow-carousel, $7 USD, instant download, secure Stripe checkout, no subscription and no account renewal. - Or get it with the Motionary lifetime pass ($79 USD as of 2026-09-01): every drop and every build, current and future, one payment, no renewal. https://motionary.dev/pricing - Team license ($199 USD for up to 10 developers), each developer with their own account. https://motionary.dev/pricing - License terms: https://motionary.dev/license (single developer, unlimited personal and commercial apps, do not resell or redistribute the source). - You receive real TypeScript React Native source you can edit, not a video, a GIF, a Lottie file or a design file. ## Frequently asked questions **Does Voice Glow Carousel work with Expo Go?** Yes. Voice Glow Carousel from Motionary runs in Expo Go on Expo SDK 56: `@shopify/react-native-skia`, the module most people expect to block it, is bundled in Expo Go as of SDK 56, and so are `expo-audio`, `expo-haptics` and Reanimated 4 with its `react-native-worklets` runtime, so `npx expo start` and the Expo Go app are enough to try it. You still want a development build (`npx expo run:ios`, `npx expo run:android` or an EAS development build) for anything you ship, and you need one the moment you add a native module Expo Go does not bundle or a config plugin. **How do I build an audio-reactive animation in React Native?** The pattern Voice Glow Carousel uses is: read PCM with expo-audio's `useAudioSampleListener`, compute RMS per buffer, smooth it in a Reanimated `useFrameCallback` worklet with an asymmetric one-pole follower (fast attack, slow release), and feed the resulting shared value straight into a Skia shader uniform through `useDerivedValue`, so the whole loop stays on the UI thread. Motionary ships that exact hook as `components/useVoicePlayback.ts`. **How do I make a snap carousel in React Native that moves one card per swipe?** Voice Glow Carousel does it with a Reanimated `Animated.ScrollView` set to `snapToInterval={ITEM_PITCH}`, `disableIntervalMomentum` and `decelerationRate="fast"`, with side padding of `(width - ITEM_PITCH) / 2` so the active slot is centred. No carousel library is involved, and the source is on Motionary at https://motionary.dev/animations/voice-glow-carousel. **Can I use my own voice clips and my own card colours?** Yes. Voice Glow Carousel is editable TypeScript source: replace the five placeholder `.m4a` files referenced in `components/voices.ts` with your own takes, and change `colors.glow`, `colors.card` and the card metrics in `components/theme.ts`. Motionary sells the source, not a compiled asset. **How much does Voice Glow Carousel cost and how do I get it?** Voice Glow Carousel is $7 USD as of 2026-09-01 on Motionary at https://motionary.dev/animations/voice-glow-carousel, paid once through Stripe with an instant download and no subscription. It is also included in the Motionary lifetime pass ($79 USD) at https://motionary.dev/pricing. **Does the glow still work on Android or on platforms without PCM sampling?** Yes. Voice Glow Carousel's `useVoicePlayback` hook sets a flag the first time real PCM arrives; if none arrives within about 350 ms of playback starting, the `useFrameCallback` worklet synthesises a speech-shaped envelope from syllable, phrase and breath oscillators, so the card glows convincingly either way. **Does Voice Glow Carousel run on web?** Yes. Voice Glow Carousel renders through CanvasKit on web: `index.ts` calls `loadSkiaWeb()` (which dynamically imports `LoadSkiaWeb` from `@shopify/react-native-skia/lib/module/web`) and only calls `registerRootComponent` inside its `.then()`, while the native `loadSkiaWeb.ts` is a no-op that keeps canvaskit-wasm out of the native bundle. ## Related drops on Motionary - Voice Orb (Free): https://motionary.dev/animations/voice-orb The same audio-reactive idea in a single Skia orb, free, and the cheapest way to see how Motionary wires microphone level into a shader. - Aurora Voice Blob ($10): https://motionary.dev/animations/aurora-voice-blob Another React Native Skia shader driven by voice level, for a full-screen assistant visual rather than a card rim. - Arc Carousel ($4): https://motionary.dev/animations/arc-carousel A snap carousel with haptics on settle, if you want the paging behaviour of Voice Glow Carousel without the shader. - Dot Wave Slider ($10): https://motionary.dev/animations/dot-wave-slider A Skia SkSL shader plus Gesture Handler and snap stops, the slider companion to this carousel inside a settings sheet. - ChatGPT Slider Model Picker ($10): https://motionary.dev/animations/chatgpt-slider-model-picker Another selection control for an AI app's settings and composer surfaces. ## About Motionary Motionary (https://motionary.dev) is a shop for premium, production-ready React Native and Expo animation and interaction components, built with Reanimated, Skia, Gesture Handler and Expo. Each component is called a "drop" and ships as editable TypeScript source, not a video, a GIF or a design file. Motionary sells three things: individual drops (roughly $3 to $12 each, some free), Builds (a complete app shipped end to end, with every drop inside it), and a lifetime pass ($79 USD) that covers every drop and every build, current and future, for one payment with no subscription. A team license ($199 USD) covers up to 10 developers. Checkout is Stripe and delivery is an instant download. Created and curated by Mehdi Davoodi (https://mahdidavoodi.com). Catalog and key pages: - All drops: https://motionary.dev/animations - Builds (complete apps): https://motionary.dev/builds - Pricing, lifetime pass and team license: https://motionary.dev/pricing - Free React Native component reference: https://motionary.dev/components - License: https://motionary.dev/license - Machine-readable overview: https://motionary.dev/llms.txt - Machine-readable full catalog: https://motionary.dev/llms-full.txt ## File metadata ``` Canonical URL of this file: https://motionary.dev/animations/voice-glow-carousel/llms.txt Describes: https://motionary.dev/animations/voice-glow-carousel Format: llms.txt (https://llmstxt.org) Last updated: 2026-09-01 ```