Introduction
Components
- Accordion
- Action Sheet
- Alert
- Audio Player
- Audio Recorder
- Audio Waveform
- Avatar
- AvoidKeyboard
- Badge
- BottomSheet
- Button
- Camera
- Camera Preview
- Card
- Carousel
- Checkbox
- Collapsible
- Color Picker
- Combobox
- Date Picker
- File Picker
- Gallery
- Hello Wave
- Icon
- Image
- Input
- Input OTP
- Link
- MediaPicker
- Mode Toggle
- Onboarding
- ParallaxScrollView
- Picker
- Popover
- Progress
- Radio
- ScrollView
- SearchBar
- Separator
- Share
- Sheet
- Skeleton
- Spinner
- Switch
- Table
- Tabs
- Text
- Toast
- Toggle
- Video
- View
Charts
Installation
pnpm dlx bna-ui add audio-waveform
Usage
import { AudioWaveform } from '@/components/ui/audio-waveform';
Basic Usage
function MyComponent() {
const [isPlaying, setIsPlaying] = useState(false);
const [progress, setProgress] = useState(0);
return (
<AudioWaveform
isPlaying={isPlaying}
progress={progress}
showProgress={true}
height={60}
/>
);
}
With Custom Data
function MyComponent() {
const audioData = [0.2, 0.5, 0.8, 0.3, 0.6, 0.9, 0.4, 0.7, 0.1, 0.5];
return (
<AudioWaveform
data={audioData}
isPlaying={isPlaying}
progress={progress}
showProgress={true}
onSeek={(position) => setProgress(position)}
interactive={true}
/>
);
}
Interactive Seeking
function AudioPlayer() {
const [progress, setProgress] = useState(0);
const [isPlaying, setIsPlaying] = useState(false);
const [isSeeking, setIsSeeking] = useState(false);
const handleSeek = (position: number) => {
setProgress(position);
// Update your audio player position here
};
return (
<AudioWaveform
isPlaying={isPlaying}
progress={progress}
showProgress={true}
interactive={true}
onSeek={handleSeek}
onSeekStart={() => setIsSeeking(true)}
onSeekEnd={() => setIsSeeking(false)}
activeColor='#007AFF'
inactiveColor='#E5E5E7'
/>
);
}
Examples
Default
Recording Mode
Interactive Seeking
Custom Styling
Real-time Data
Compact Size
API Reference
AudioWaveform
The main AudioWaveform component.
Prop | Type | Default | Description |
---|---|---|---|
data | number[] | - | Audio amplitude data (0-1 range). Auto-generated if not provided. |
isPlaying | boolean | false | Whether the audio is currently playing. |
progress | number | 0 | Current playback progress (0-100). |
onSeek | (position: number) => void | - | Callback fired when user seeks to a position. |
onSeekStart | () => void | - | Callback fired when seeking starts. |
onSeekEnd | () => void | - | Callback fired when seeking ends. |
style | ViewStyle | - | Additional styles for the container. |
height | number | 60 | Height of the waveform in pixels. |
barCount | number | 50 | Number of bars in the waveform. |
barWidth | number | 3 | Width of each bar in pixels. |
barGap | number | 2 | Gap between bars in pixels. |
activeColor | string | theme color | Color for played/active portion. |
inactiveColor | string | theme color | Color for unplayed/inactive portion. |
animated | boolean | true | Whether to animate the waveform during playback. |
showProgress | boolean | false | Whether to show progress indicator. |
interactive | boolean | false | Whether to enable touch-based seeking. |
Usage Patterns
Audio Player Integration
function AudioPlayer({ audioUrl }: { audioUrl: string }) {
const [isPlaying, setIsPlaying] = useState(false);
const [progress, setProgress] = useState(0);
const [duration, setDuration] = useState(0);
const [audioData, setAudioData] = useState<number[]>([]);
// Load audio data from file
useEffect(() => {
loadAudioWaveform(audioUrl).then(setAudioData);
}, [audioUrl]);
const handleSeek = (position: number) => {
const newTime = (position / 100) * duration;
// Seek audio to newTime
setProgress(position);
};
return (
<View>
<AudioWaveform
data={audioData}
isPlaying={isPlaying}
progress={progress}
showProgress={true}
interactive={true}
onSeek={handleSeek}
height={80}
activeColor='#007AFF'
/>
<Button onPress={() => setIsPlaying(!isPlaying)}>
{isPlaying ? 'Pause' : 'Play'}
</Button>
</View>
);
}
Voice Message
function VoiceMessage({ duration, audioData }: VoiceMessageProps) {
const [isPlaying, setIsPlaying] = useState(false);
const [progress, setProgress] = useState(0);
return (
<View style={styles.voiceMessage}>
<TouchableOpacity onPress={() => setIsPlaying(!isPlaying)}>
<Icon name={isPlaying ? 'pause' : 'play'} />
</TouchableOpacity>
<AudioWaveform
data={audioData}
isPlaying={isPlaying}
progress={progress}
showProgress={true}
interactive={true}
height={32}
barCount={30}
barWidth={2}
barGap={1}
style={{ flex: 1, marginHorizontal: 12 }}
/>
<Text>{formatDuration(duration)}</Text>
</View>
);
}
Recording Visualization
function RecordingView() {
const [isRecording, setIsRecording] = useState(false);
const [recordingData, setRecordingData] = useState<number[]>([]);
// Update waveform with real-time audio levels
useEffect(() => {
if (isRecording) {
const interval = setInterval(() => {
const newLevel = getCurrentAudioLevel(); // Your audio level function
setRecordingData((prev) => [...prev.slice(-49), newLevel]);
}, 100);
return () => clearInterval(interval);
}
}, [isRecording]);
return (
<View>
<AudioWaveform
data={recordingData}
isPlaying={isRecording}
animated={true}
showProgress={false}
height={60}
barCount={50}
activeColor='#FF3B30'
/>
<Button onPress={() => setIsRecording(!isRecording)}>
{isRecording ? 'Stop' : 'Record'}
</Button>
</View>
);
}
Accessibility
The AudioWaveform component follows accessibility best practices:
- Proper touch target sizes for interactive elements
- Screen reader support for progress information
- Respects system accessibility settings
- Keyboard navigation support where applicable
Performance
The component is optimized for performance:
- Uses
react-native-reanimated
for smooth native animations - Efficient rendering with minimal re-renders
- Configurable bar count to balance detail vs performance
- Native driver animations where possible
Theming
The AudioWaveform automatically adapts to your app's theme:
- Uses theme colors by default for active/inactive states
- Supports both light and dark modes
- Customizable colors through props
- Respects theme opacity values
Data Format
Audio data should be provided as an array of numbers between 0 and 1:
const audioData = [
0.1, // Very quiet
0.3, // Quiet
0.5, // Medium
0.8, // Loud
1.0, // Maximum
];
If no data is provided, the component generates realistic sample data automatically.
On This Page
InstallationUsageBasic UsageWith Custom DataInteractive SeekingExamplesDefaultRecording ModeInteractive SeekingCustom StylingReal-time DataCompact SizeAPI ReferenceAudioWaveformUsage PatternsAudio Player IntegrationVoice MessageRecording VisualizationAccessibilityPerformanceThemingData Format