project-standalo-sonic-cloud/docs/COMPONENTS.md

18 KiB

Component Catalog

A comprehensive guide to all reusable React components in the Sonic Cloud platform.


Audio & Playback

AudioPlayer

Purpose: Fixed bottom audio player that displays the currently playing song with full playback controls Location: components/AudioPlayer.tsx

Props & Usage

Props:

Prop Type Description
currentSong Song Currently playing song object
isPlaying boolean Playback state flag
onPlayPause () => void Toggle play/pause handler
onNext () => void Skip to next track handler
onPrevious () => void Go to previous track handler
progress number Playback progress (0-100)
volume number Volume level (0-100)
onSeek (time: number) => void Seek to specific time handler
onVolumeChange (level: number) => void Volume adjustment handler

Usage Example:

<AudioPlayer
  currentSong={currentSong}
  isPlaying={isPlaying}
  onPlayPause={handlePlayPause}
  onNext={handleNext}
  onPrevious={handlePrevious}
  progress={progress}
  volume={volume}
  onSeek={handleSeek}
  onVolumeChange={setVolume}
/>

Dependencies: PlayerControls, WaveformDisplay Related: PlayerControls, WaveformDisplay


PlayerControls

Purpose: Reusable audio player control buttons for play/pause, skip, shuffle, and repeat Location: components/PlayerControls.tsx

Props & Usage

Props:

Prop Type Description
isPlaying boolean Current playback state
onPlayPause () => void Toggle play/pause
onNext () => void Skip to next track
onPrevious () => void Go to previous track
shuffle boolean Shuffle mode enabled
repeat 'none' | 'all' | 'one' Repeat mode
onShuffleToggle () => void Toggle shuffle
onRepeatToggle () => void Cycle repeat modes
size? 'sm' | 'md' | 'lg' Button size variant

Usage Example:

<PlayerControls
  isPlaying={isPlaying}
  onPlayPause={togglePlayback}
  onNext={skipNext}
  onPrevious={skipPrevious}
  shuffle={shuffleEnabled}
  repeat={repeatMode}
  onShuffleToggle={toggleShuffle}
  onRepeatToggle={cycleRepeat}
  size="md"
/>

Dependencies: None (presentational component) Related: AudioPlayer


WaveformDisplay

Purpose: Canvas-based audio waveform visualization with progress tracking and interactive seeking Location: components/WaveformDisplay.tsx

Props & Usage

Props:

Prop Type Description
audioUrl string URL of audio file to visualize
progress number Current playback progress (0-100)
onSeek (time: number) => void Callback when user seeks
height? number Canvas height in pixels (default: 80)
barWidth? number Waveform bar width (default: 2)
barGap? number Space between bars (default: 1)
primaryColor? string Waveform color (default: theme primary)
progressColor? string Played portion color (default: accent)

Usage Example:

<WaveformDisplay
  audioUrl={song.audioUrl}
  progress={currentProgress}
  onSeek={handleSeek}
  height={100}
  primaryColor="#3b82f6"
  progressColor="#10b981"
/>

Dependencies: Canvas API, Web Audio API Related: AudioPlayer


Content Cards

SongCard

Purpose: Displays song information with cover image, title, artist, and playback stats Location: components/SongCard.tsx

Props & Usage

Props:

Prop Type Description
song Song Song object with metadata
onClick? () => void Click handler for card
onPlay? () => void Play button handler
showArtist? boolean Display artist name (default: true)
showPlayCount? boolean Display play count (default: true)
variant? 'default' | 'compact' Card layout style

Usage Example:

<SongCard
  song={song}
  onClick={() => router.push(`/songs/${song.id}`)}
  onPlay={playSong}
  showArtist={true}
  showPlayCount={true}
  variant="default"
/>

Dependencies: Next.js Image, Link Related: TrackList, AudioPlayer


AlbumCard

Purpose: Displays album information with cover art, title, artist, release year, and track count Location: components/AlbumCard.tsx

Props & Usage

Props:

Prop Type Description
album Album Album object with metadata
onClick? () => void Click handler for card
showArtist? boolean Display artist name (default: true)
showTrackCount? boolean Display track count (default: true)

Usage Example:

<AlbumCard
  album={album}
  onClick={() => router.push(`/album/${album.id}`)}
  showArtist={true}
  showTrackCount={true}
/>

Dependencies: Next.js Image, Link Related: ArtistCard


ArtistCard

Purpose: Displays artist profile with circular avatar, name, and verification badge Location: components/ArtistCard.tsx

Props & Usage

Props:

Prop Type Description
artist Artist Artist profile object
onClick? () => void Click handler for card
showVerified? boolean Display verified badge (default: true)
showFollowers? boolean Display follower count (default: false)
size? 'sm' | 'md' | 'lg' Avatar size variant

Usage Example:

<ArtistCard
  artist={artist}
  onClick={() => router.push(`/artist/${artist.id}`)}
  showVerified={true}
  size="md"
/>

Dependencies: Next.js Image, Link Related: AlbumCard, LabelCard


PlaylistCard

Purpose: Displays playlist with cover image, title, song count, and privacy indicator Location: components/PlaylistCard.tsx

Props & Usage

Props:

Prop Type Description
playlist Playlist Playlist object with metadata
onClick? () => void Click handler for card
showSongCount? boolean Display song count (default: true)
showPrivacy? boolean Display privacy badge (default: true)
editable? boolean Show edit actions (default: false)

Usage Example:

<PlaylistCard
  playlist={playlist}
  onClick={() => router.push(`/playlist/${playlist.id}`)}
  showSongCount={true}
  showPrivacy={true}
  editable={isOwner}
/>

Dependencies: Next.js Image, Link Related: TrackList


LabelCard

Purpose: Displays record label information with logo, name, and artist roster count Location: components/LabelCard.tsx

Props & Usage

Props:

Prop Type Description
label Label Label profile object
onClick? () => void Click handler for card
showArtistCount? boolean Display artist count (default: true)

Usage Example:

<LabelCard
  label={label}
  onClick={() => router.push(`/label/${label.id}`)}
  showArtistCount={true}
/>

Dependencies: Next.js Image, Link Related: ArtistCard


GenreBadge

Purpose: Small clickable badge displaying music genre with color-coded styling Location: components/GenreBadge.tsx

Props & Usage

Props:

Prop Type Description
genre Genre Genre object with name and color
onClick? () => void Click handler for badge
size? 'xs' | 'sm' | 'md' Badge size variant
removable? boolean Show remove button (default: false)
onRemove? () => void Remove button handler

Usage Example:

<GenreBadge
  genre={genre}
  onClick={() => filterByGenre(genre.slug)}
  size="sm"
/>

Dependencies: None (presentational component) Related: UploadForm


Forms

AuthForm

Purpose: Multi-mode authentication form for login, registration, and password reset flows Location: components/AuthForm.tsx

Props & Usage

Props:

Prop Type Description
mode 'login' | 'register' | 'forgot' | 'reset' Form mode
onSuccess? () => void Success callback
resetToken? string Password reset token (for reset mode)

Usage Example:

// Login mode
<AuthForm mode="login" onSuccess={handleLoginSuccess} />

// Register mode
<AuthForm mode="register" onSuccess={handleRegisterSuccess} />

// Password reset mode
<AuthForm mode="reset" resetToken={token} onSuccess={handleResetSuccess} />

API Calls:

  • Login: POST /api/auth/login
  • Register: POST /api/auth/register
  • Forgot: POST /api/auth/forgot-password
  • Reset: POST /api/auth/reset-password

Dependencies: React Hook Form, JWT storage Related: UserMenu, Header


UploadForm

Purpose: Multi-field form for uploading songs with audio file, metadata, and genre tagging Location: components/UploadForm.tsx

Props & Usage

Props:

Prop Type Description
onSuccess? (songId: string) => void Success callback with created song ID
onCancel? () => void Cancel button handler
initialData? Partial Pre-fill form data (for editing)

Usage Example:

<UploadForm
  onSuccess={(songId) => router.push(`/songs/${songId}`)}
  onCancel={() => router.back()}
/>

Form Fields:

  • Audio file upload (required)
  • Title (required)
  • Album selection (optional)
  • Genre tags (multi-select)
  • Cover image URL (optional)
  • Lyrics (optional)
  • Privacy toggle (public/private)

API Calls:

  • Upload: POST /api/songs/upload

Dependencies: File upload handling, GenreBadge Related: GenreBadge


ProfileForm

Purpose: User profile editing form with username, display name, bio, and website fields Location: components/ProfileForm.tsx

Props & Usage

Props:

Prop Type Description
user User Current user object
onSuccess? () => void Success callback
onCancel? () => void Cancel button handler

Usage Example:

<ProfileForm
  user={currentUser}
  onSuccess={() => toast.success('Profile updated')}
  onCancel={() => router.back()}
/>

Form Fields:

  • Username (unique, alphanumeric + underscore)
  • Display name (optional)
  • Bio (optional, max 500 chars)
  • Website URL (optional, validated)
  • Avatar URL (optional)

API Calls:

  • Update: PUT /api/users/me

Dependencies: React Hook Form, URL validation Related: UserMenu


CreatePlaylistModal

Purpose: Modal dialog for creating new playlists with title, description, and privacy settings Location: components/CreatePlaylistModal.tsx

Props & Usage

Props:

Prop Type Description
isOpen boolean Modal open state
onClose () => void Close modal handler
onSuccess? (playlistId: string) => void Success callback with playlist ID

Usage Example:

<CreatePlaylistModal
  isOpen={isModalOpen}
  onClose={() => setIsModalOpen(false)}
  onSuccess={(id) => router.push(`/playlist/${id}`)}
/>

Form Fields:

  • Playlist title (required)
  • Description (optional)
  • Privacy toggle (public/private)

API Calls:

  • Create: POST /api/playlists

Dependencies: Modal backdrop, React Hook Form Related: PlaylistCard


Navigation

Header

Purpose: Fixed top navigation header with logo, navigation links, search, and user menu Location: components/Header.tsx

Props & Usage

Props:

Prop Type Description
transparent? boolean Transparent background (default: false)

Usage Example:

<Header transparent={false} />

Features:

  • Logo with home link
  • Primary navigation links (Discover, Artists, Genres, Labels)
  • Search bar integration
  • User menu with auth state
  • Mobile hamburger menu
  • Responsive breakpoints

Dependencies: NavLink, UserMenu, SearchBar Related: NavLink, UserMenu, SearchBar


Purpose: Navigation link component with automatic active state highlighting Location: components/NavLink.tsx

Props & Usage

Props:

Prop Type Description
href string Link destination path
children ReactNode Link text/content
exact? boolean Exact path match (default: false)
activeClassName? string Custom active state class

Usage Example:

<NavLink href="/discover" exact>
  Discover
</NavLink>

<NavLink href="/artist" activeClassName="text-blue-500">
  Artists
</NavLink>

Dependencies: Next.js usePathname, Link Related: Header


UserMenu

Purpose: Dropdown menu showing authentication state with profile, upload, playlists, and logout actions Location: components/UserMenu.tsx

Props & Usage

Props:

Prop Type Description
user User | null Current authenticated user

Usage Example:

<UserMenu user={currentUser} />

Menu Items (Authenticated):

  • Profile link
  • Upload song link
  • My playlists link
  • Settings link (if applicable)
  • Logout button

Menu Items (Unauthenticated):

  • Login link
  • Register link

Dependencies: JWT auth context, Next.js Link Related: Header, AuthForm


Purpose: Search input with real-time suggestions dropdown, debouncing, and loading indicator Location: components/SearchBar.tsx

Props & Usage

Props:

Prop Type Description
placeholder? string Input placeholder text
onSearch? (query: string) => void Search submit handler
debounceMs? number Debounce delay (default: 300ms)

Usage Example:

<SearchBar
  placeholder="Search songs, artists, albums..."
  onSearch={(query) => router.push(`/search?q=${query}`)}
  debounceMs={300}
/>

Features:

  • Real-time search as you type
  • Suggestion dropdown with categorized results (Songs, Artists, Albums)
  • Loading spinner during API calls
  • Keyboard navigation (arrow keys, enter, escape)
  • Click outside to close

API Calls:

  • Search: GET /api/search?q={query}

Dependencies: Debounce hook, fetch API Related: Header


Sharing

ShareButton

Purpose: Button that generates shareable links and opens the share modal Location: components/ShareButton.tsx

Props & Usage

Props:

Prop Type Description
type 'song' | 'playlist' | 'album' Content type to share
id string Content ID
variant? 'icon' | 'button' Display style (default: 'button')

Usage Example:

<ShareButton type="song" id={song.id} variant="button" />
<ShareButton type="playlist" id={playlist.id} variant="icon" />

API Calls:

  • Generate link: POST /api/share/{type}/{id}

Dependencies: ShareModal Related: ShareModal


ShareModal

Purpose: Modal displaying shareable link with copy-to-clipboard and social media share buttons Location: components/ShareModal.tsx

Props & Usage

Props:

Prop Type Description
isOpen boolean Modal open state
onClose () => void Close modal handler
shareUrl string Full shareable URL
title string Content title for social sharing

Usage Example:

<ShareModal
  isOpen={isShareModalOpen}
  onClose={() => setIsShareModalOpen(false)}
  shareUrl={shareUrl}
  title={song.title}
/>

Features:

  • Copy link to clipboard button
  • Social share buttons (Twitter, Facebook, WhatsApp)
  • QR code generation (optional)
  • Share analytics tracking

Dependencies: Clipboard API, social share URLs Related: ShareButton


Display

TrackList

Purpose: Scrollable list of tracks with position numbers, song information, artist details, and duration Location: components/TrackList.tsx

Props & Usage

Props:

Prop Type Description
tracks Song[] Array of song objects
onTrackClick? (song: Song, index: number) => void Track selection handler
showArtist? boolean Display artist name (default: true)
showAlbum? boolean Display album name (default: false)
showDuration? boolean Display duration (default: true)
numbered? boolean Show track numbers (default: true)
currentTrackId? string ID of currently playing track

Usage Example:

<TrackList
  tracks={albumTracks}
  onTrackClick={(song, index) => playTrack(song, index)}
  showArtist={true}
  showAlbum={false}
  numbered={true}
  currentTrackId={currentSong?.id}
/>

Features:

  • Hover states for interactivity
  • Currently playing track highlight
  • Click to play functionality
  • Responsive column layout

Dependencies: SongCard (data structure) Related: AudioPlayer, AlbumCard, PlaylistCard


Component Dependencies Tree

AudioPlayer
├── PlayerControls
└── WaveformDisplay

Header
├── NavLink
├── UserMenu
│   └── AuthForm
└── SearchBar

ShareButton
└── ShareModal

UploadForm
└── GenreBadge

TrackList
└── (uses Song type)

Standalone Components:
- SongCard
- AlbumCard
- ArtistCard
- PlaylistCard
- LabelCard
- ProfileForm
- CreatePlaylistModal

Styling Conventions

All components use Tailwind CSS for styling with the following patterns:

  • Color Palette: Primary (blue), Accent (green), Neutral (gray)
  • Spacing: Consistent use of p-4, m-2, gap-4 units
  • Typography: text-sm, text-base, text-lg, font-semibold
  • Responsive: Mobile-first with sm:, md:, lg: breakpoints
  • Dark Mode: Not currently implemented (future consideration)

Type Definitions

All components use types defined in /types:

  • types/song.ts - Song, Album, Artist entities
  • types/user.ts - User, AuthState
  • types/playlist.ts - Playlist, PlaylistSong
  • types/api.ts - API request/response types