Skip to main content

Components Overview

The Nadie Sabe Nada Podcast application is built with a modular React component architecture. All components leverage modern React patterns including hooks, Redux for state management, and Framer Motion for animations.

Architecture

The application follows these architectural principles:
  • Component-based structure: Each component is self-contained with its own JSX and CSS modules
  • Redux state management: Global state managed through Redux slices (podcast, player, filter, audioTime)
  • Custom hooks: Reusable logic extracted into custom hooks (useMobileDetect, useDownload, useWindowWidth)
  • Animations: Consistent animations using Framer Motion throughout the app
  • Material-UI integration: Icons and components from MUI for enhanced UI

Core Components

PodcastList

Displays a paginated, filterable grid of podcast episodes with search and filter capabilities

PodcastDetail

Shows detailed information for a single podcast episode with YouTube video integration

LastPodcast

Dedicated view for the most recent episode with full interaction features

PersistentPlayer

Fixed audio player that persists across page navigation with playback time tracking

MP3Player

Individual podcast card with play controls, favorites, and download functionality

Header

Navigation header with branding, links, and settings access

Settings

User preferences and data management interface

Component Dependencies

State Management

All major components connect to Redux store slices:
  • podcast: Manages episodes, favorites, listen later, completed episodes
  • player: Controls current playback state and current podcast
  • filter: Handles search, filtering, and pagination state
  • audioTime: Tracks playback times for each episode

Shared Libraries

  • framer-motion: Animation library for smooth transitions
  • react-router-dom: Navigation and routing
  • react-redux: Redux integration
  • @mui/icons-material: Material Design icons
  • react-hot-toast: Toast notifications
  • react-helmet-async: Dynamic document head management

Styling

All components use CSS Modules for scoped styling:
import styles from "./ComponentName.module.css";

<div className={styles.container}>...</div>
This prevents style conflicts and keeps component styles isolated.

Common Patterns

Tooltips

Most interactive components use custom Bootstrap-styled tooltips:
const BootstrapTooltip = useMemo(
  () =>
    styled(({ className, ...props }) => (
      <Tooltip {...props} arrow classes={{ popper: className }} />
    ))(({ theme }) => ({
      [`& .${tooltipClasses.arrow}`]: {
        color: "#14D993"
      },
      [`& .${tooltipClasses.tooltip}`]: {
        backgroundColor: "#14DB93",
        color: "#000000",
        fontSize: "14px",
        fontWeight: "bold",
        padding: "5px 10px",
        borderRadius: "5px"
      }
    })),
  []
);

Animations

Components use consistent Framer Motion variants:
const itemVariants = {
  hidden: { y: -20, opacity: 0 },
  visible: {
    y: 0,
    opacity: 1,
    transition: {
      type: "spring",
      stiffness: 400,
      damping: 12,
      mass: 0.95
    }
  },
  hover: {
    scale: 1.05,
    transition: {
      type: "spring",
      stiffness: 300,
      damping: 12
    }
  }
};

Redux Dispatch

Components use Redux hooks for state access and updates:
import { useDispatch, useSelector } from "react-redux";

const dispatch = useDispatch();
const { songs, favoriteEpisodes } = useSelector((state) => state.podcast);

// Dispatch actions
dispatch(toggleFavorite(song));

Next Steps

Explore individual component documentation for detailed prop types, usage examples, and implementation details:

Build docs developers (and LLMs) love