Skip to main content

Core Components

Player

The main audio player component that handles playback, controls, and state management. Location: src/components/player.tsx:27
playlist
Playlist
required
Array of playlist items containing surah information and audio links
Features:
  • Audio playback with play/pause controls
  • Shuffle and repeat modes
  • Volume control
  • Playback speed adjustment
  • Fullscreen mode
  • Media session integration
  • Sleep timer
import Player from '@/components/player';
import { Playlist } from '@/types';

const playlist: Playlist = [
  { surahId: '1', link: 'https://example.com/001.mp3' },
  { surahId: '2', link: 'https://example.com/002.mp3' },
];

<Player playlist={playlist} />

ReciterSelector

A button-style component for selecting reciters with search, favorite, and share functionality. Location: src/components/reciter-selector.tsx:18 Props: None (uses global state) Features:
  • Displays selected reciter name
  • Opens reciter selection dialog
  • Favorite/unfavorite functionality
  • Share reciter via Web Share API or clipboard
  • Skeleton loading state during SSR
import ReciterSelector from '@/components/reciter-selector';

<ReciterSelector />

Playlist

Displays a scrollable list of playlist items (surahs) with click handlers. Location: src/components/playlist.tsx:16
setIsOpen
(isOpen: boolean) => void
required
Function to control dialog open/close state
setCurrentTrack
React.Dispatch<React.SetStateAction<number | undefined>>
required
Function to set the currently playing track index
import Playlist from '@/components/playlist';
import { useState } from 'react';

const [isOpen, setIsOpen] = useState(false);
const [currentTrack, setCurrentTrack] = useState<number | undefined>(0);

<Playlist 
  setIsOpen={setIsOpen}
  setCurrentTrack={setCurrentTrack}
/>

TrackInfo

Displays information about the currently playing track including surah name and timestamps. Location: src/components/track-info.tsx:17
currentTrackId
number
required
Index of the currently playing track
duration
number
required
Total duration of the track in seconds
currentTime
number
required
Current playback position in seconds
import TrackInfo from '@/components/track-info';

<TrackInfo
  currentTrackId={0}
  duration={300}
  currentTime={45}
/>

AudioBarsVisualizer

Audio spectrum visualizer that displays animated bars during playback. Location: src/components/audio-bars-visualizer.tsx:14
audioId
string
required
DOM ID of the audio element to visualize
isPlaying
boolean
required
Whether audio is currently playing
Features:
  • Responsive width calculation
  • Only renders when visualizer is enabled (global state)
  • Smooth animations
  • Blue color scheme matching brand
import AudioBarsVisualizer from '@/components/audio-bars-visualizer';

<audio id="audio" src="track.mp3" />
<AudioBarsVisualizer audioId="audio" isPlaying={true} />

Range

Custom range slider for seeking through audio tracks. Location: src/components/range.tsx:12
currentTime
number
required
Current playback position in seconds
duration
number
required
Total track duration in seconds
setCurrentTime
(time: number) => void
required
Callback to update current time
audioRef
React.RefObject<HTMLAudioElement | null>
required
Reference to the audio element
Features:
  • RTL support (direction-aware gradient)
  • Smooth gradient fill showing progress
  • Custom thumb styling
  • Synchronized with audio element
import Range from '@/components/range';
import { useRef, useState } from 'react';

const audioRef = useRef<HTMLAudioElement>(null);
const [currentTime, setCurrentTime] = useState(0);
const [duration, setDuration] = useState(0);

<Range
  currentTime={currentTime}
  duration={duration}
  setCurrentTime={setCurrentTime}
  audioRef={audioRef}
/>

UI Components

Dialog

Reusable modal dialog component with backdrop and animations. Location: src/components/dialog.tsx:14
isOpen
boolean
required
Controls dialog visibility
setIsOpen
(isOpen: boolean) => void
required
Function to update open state
children
ReactNode
required
Dialog content
hideCloseButton
boolean
default:"false"
Hide the close button in top-right corner
className
string
Additional CSS classes for customization
Features:
  • Native <dialog> element
  • Backdrop click to close
  • ESC key to close
  • Slide-in animation
  • Scrollable content
import Dialog from '@/components/dialog';
import { useState } from 'react';

const [isOpen, setIsOpen] = useState(false);

<Dialog isOpen={isOpen} setIsOpen={setIsOpen}>
  <h2>Dialog Content</h2>
  <p>Your content here</p>
</Dialog>

Tooltip

Simple tooltip that appears on hover. Location: src/components/tooltip.tsx:13
content
string
required
Tooltip text to display
children
React.ReactNode
required
Element to attach tooltip to
className
string
Additional CSS classes
import Tooltip from '@/components/tooltip';

<Tooltip content="Click to play">
  <button>Play</button>
</Tooltip>

PlayerControls

Comprehensive player control panel with play/pause, navigation, volume, and advanced features. Location: src/components/player-controls.tsx:53
isPlaying
boolean
required
Current playback state
togglePlayPause
() => void
required
Toggle play/pause callback
handleNextTrack
() => void
required
Skip to next track callback
handlePreviousTrack
() => void
required
Skip to previous track callback
togglePlaylistOpen
() => void
required
Toggle playlist dialog callback
volumeRef
RefObject<HTMLDivElement | null>
required
Ref for volume control container (click-outside detection)
Features:
  • Responsive layout (mobile vs desktop)
  • Volume slider with mute
  • Playback speed control (1x, 1.5x, 2x)
  • Shuffle and repeat modes
  • Fullscreen toggle
  • Sleep timer with presets
  • Audio visualizer toggle
  • Playlist access
  • Internationalized labels
import PlayerControls from '@/components/player-controls';
import { useRef } from 'react';

const volumeRef = useRef<HTMLDivElement>(null);

<PlayerControls
  isPlaying={isPlaying}
  volumeRef={volumeRef}
  togglePlayPause={() => setIsPlaying(!isPlaying)}
  handleNextTrack={handleNext}
  handlePreviousTrack={handlePrev}
  togglePlaylistOpen={() => setPlaylistOpen(true)}
/>

LanguageSwitcher

Toggle component to switch between Arabic and English interface languages. Location: src/components/language-switcher.tsx:7 Props: None (reads/writes to localeAtom) Features:
  • Fixed position (top-right corner)
  • Animated sliding indicator
  • Toggles between ‘ar’ (Arabic) and ‘en’ (English)
  • Updates global locale state via Jotai
  • Accessible with ARIA labels
  • Responsive sizing (smaller on mobile)
import LanguageSwitcher from '@/components/language-switcher';

export function Layout({ children }) {
  return (
    <div>
      <LanguageSwitcher />
      {children}
    </div>
  );
}

PWAUpdater

Dialog that prompts users to reload when a new service worker version is available. Location: src/components/pwa-updater.tsx:7 Props: None (manages internal state) Features:
  • Listens for service worker waiting event
  • Shows update dialog automatically
  • Reloads page when user confirms
  • Skips waiting and activates new service worker
  • Essential for PWA update flow
import PWAUpdater from '@/components/pwa-updater';

export function RootLayout({ children }) {
  return (
    <html>
      <body>
        {children}
        <PWAUpdater />
      </body>
    </html>
  );
}

Application footer with navigation links to main pages. Location: src/components/footer.tsx:16 Props: None Features:
  • Fixed at bottom on mobile, static on desktop
  • Links to: Home, About, Privacy, Contact
  • SVG icons for each link
  • Internationalized labels
  • Clears selected reciter when navigating home
  • Responsive layout (icon-only on mobile, icon+text on desktop)
import Footer from '@/components/footer';

export function Layout({ children }) {
  return (
    <div>
      <main>{children}</main>
      <Footer />
    </div>
  );
}

Build docs developers (and LLMs) love