React Native Glow UI v1 is out now!
Logo
Components

Media List

Media List component for React Native.

Installation

npx rn-glow add media-list

🧾 MediaListProps<T>

PropTypeDefault
contentContainerStyle?
StyleProp<ViewStyle>
-
animationConfig?
AnimationConfig
-
blurIntensity?
number
-
screenWidth?
number
-
keyExtractor
(item: T, index: number) => string
-
renderItem?
(item: T, index: number) => ReactNode
-
chunkSize
number
-
data
T[]
-

🎞️ AnimationConfig

PropTypeDefault
translateY?
boolean
-
rotate?
boolean
-
scale?
boolean
-

🪄 MediaListWrapperProps

PropTypeDefault
style?
StyleProp<ViewStyle>
-
children
React.ReactNode
-

📝 MediaListTitleProps

PropTypeDefault
style?
StyleProp<TextStyle>
-
children
React.ReactNode
-

📦 MediaListTitleWrapperProps

PropTypeDefault
style?
StyleProp<ViewStyle>
-
children
React.ReactNode
-

🚀 Full Example

import Native, {
  View,
  Text,
  SafeAreaView,
  ScrollView,
  Dimensions,
  Image,
  TouchableOpacity,
  ScaledSize,
} from "react-native";
import * as React from "react";
import { MediaList, Row } from "@/components";
import { Feather, Ionicons, MaterialCommunityIcons } from "@expo/vector-icons";
const { width: WIDTH }: ScaledSize = Dimensions.get("window");

const MediaListDemo: React.FC = (_$_): React.ReactNode => {
  const mediaData = [
    {
      id: "1",
      title: "Echoes of Dusk",
      subtitle: "Ambient Chill",
      imageUrl: "https://picsum.photos/200/200?random=11",
      artist: "Night Fade",
      lastPlayed: "2 days ago",
    },
    {
      id: "2",
      title: "Skyline Groove",
      subtitle: "Nu-Disco",
      imageUrl: "https://picsum.photos/200/200?random=12",
      artist: "Velvet Pulse",
      lastPlayed: "1 week ago",
    },
    {
      id: "3",
      title: "Hollow Moon",
      subtitle: "Alternative Rock",
      imageUrl: "https://picsum.photos/200/200?random=13",
      artist: "The Outliers",
      lastPlayed: "5 days ago",
    },
    {
      id: "4",
      title: "Celestial Drift",
      subtitle: "Dream Pop",
      imageUrl: "https://picsum.photos/200/200?random=14",
      artist: "Nova Bloom",
      lastPlayed: "3 weeks ago",
    },
    {
      id: "5",
      title: "Crimson Trails",
      subtitle: "Synth Rock",
      imageUrl: "https://picsum.photos/200/200?random=15",
      artist: "Crimson Atlas",
      lastPlayed: "1 month ago",
    },
    {
      id: "6",
      title: "Golden Hour",
      subtitle: "Indie Folk",
      imageUrl: "https://picsum.photos/200/200?random=16",
      artist: "Sunset Valley",
      lastPlayed: "4 days ago",
    },
    {
      id: "7",
      title: "Pixel Dreams",
      subtitle: "Chiptune",
      imageUrl: "https://picsum.photos/200/200?random=17",
      artist: "Bitscape",
      lastPlayed: "2 weeks ago",
    },
    {
      id: "8",
      title: "Midnight Taxi",
      subtitle: "Lo-Fi Jazz",
      imageUrl: "https://picsum.photos/200/200?random=18",
      artist: "Noir Tones",
      lastPlayed: "6 days ago",
    },
    {
      id: "9",
      title: "Rainy Metropolis",
      subtitle: "Downtempo",
      imageUrl: "https://picsum.photos/200/200?random=19",
      artist: "Echo District",
      lastPlayed: "3 days ago",
    },
    {
      id: "10",
      title: "Candlelit Code",
      subtitle: "Neo Classical",
      imageUrl: "https://picsum.photos/200/200?random=20",
      artist: "Digital Sonata",
      lastPlayed: "5 hours ago",
    },
    {
      id: "11",
      title: "Wanderlust",
      subtitle: "World Fusion",
      imageUrl: "https://picsum.photos/200/200?random=21",
      artist: "Nomad Spirits",
      lastPlayed: "2 weeks ago",
    },
    {
      id: "12",
      title: "Paper Planes",
      subtitle: "Bedroom Pop",
      imageUrl: "https://picsum.photos/200/200?random=22",
      artist: "Soft Static",
      lastPlayed: "8 days ago",
    },
    {
      id: "13",
      title: "Neon Samurai",
      subtitle: "Electro Funk",
      imageUrl: "https://picsum.photos/200/200?random=23",
      artist: "Blade Motion",
      lastPlayed: "1 week ago",
    },
    {
      id: "14",
      title: "Retro Heartbeat",
      subtitle: "Vaporwave",
      imageUrl: "https://picsum.photos/200/200?random=24",
      artist: "Y2K Phantom",
      lastPlayed: "2 days ago",
    },
    {
      id: "15",
      title: "Frozen Silence",
      subtitle: "Piano Ambient",
      imageUrl: "https://picsum.photos/200/200?random=25",
      artist: "Glacier Echo",
      lastPlayed: "6 hours ago",
    },
    {
      id: "16",
      title: "Gravity Rush",
      subtitle: "Drum & Bass",
      imageUrl: "https://picsum.photos/200/200?random=26",
      artist: "Pulse Reactor",
      lastPlayed: "3 weeks ago",
    },
    {
      id: "17",
      title: "Velvet Rain",
      subtitle: "Soul Jazz",
      imageUrl: "https://picsum.photos/200/200?random=27",
      artist: "Moody Waters",
      lastPlayed: "4 days ago",
    },
    {
      id: "18",
      title: "Serotonin Bloom",
      subtitle: "Indie Electronic",
      imageUrl: "https://picsum.photos/200/200?random=28",
      artist: "Lucid Violet",
      lastPlayed: "1 day ago",
    },
    {
      id: "19",
      title: "Signal Fade",
      subtitle: "Experimental",
      imageUrl: "https://picsum.photos/200/200?random=29",
      artist: "The Signalist",
      lastPlayed: "2 weeks ago",
    },
    {
      id: "20",
      title: "Sunset Alley",
      subtitle: "City Pop",
      imageUrl: "https://picsum.photos/200/200?random=30",
      artist: "Tokyo Mirage",
      lastPlayed: "9 days ago",
    },
  ];

  const suggestionSongs = [
    {
      id: "1",
      title: "Moral of the Story",
      artist: "Ashe",
      imagheUrl:
        "https://i.scdn.co/image/ab67616d0000b273aea0d98794e91056c608e069",
    },
    {
      id: "2",
      title: "Marry On A Cross",
      artist: "Ghost",
      imagheUrl:
        "https://i.scdn.co/image/ab67616d0000b273bef9b0a348ea8dd18a581025",
    },
    {
      id: "3",
      title: "The Night We Met",
      artist: "Lord Huron",
      imagheUrl:
        "https://i.scdn.co/image/ab67616d0000b273e5d72e7141406c974ff5f8f7",
    },
    {
      id: "4",
      title: "Lose Yourself to Dance",
      artist: "Daft Punk",
      imagheUrl:
        "https://i.scdn.co/image/ab67616d0000b2739b9b36b0e22870b9f542d937",
    },
    {
      id: "5",
      title: "Electric Feel",
      artist: "MGMT",
      imagheUrl:
        "https://i.scdn.co/image/ab67616d0000b2738b32b139981e79f2ebe005eb",
    },
    {
      id: "6",
      title: "Take Me Out",
      artist: "Franz Ferdinand",
      imagheUrl:
        "https://i.scdn.co/image/ab67616d0000b27334a9b88a4277baba983a3e0f",
    },
    {
      id: "7",
      title: "Electric Love",
      artist: "BØRNS",
      imagheUrl:
        "https://i.scdn.co/image/ab67616d0000b273cc2cf912462d8ae4ef856434",
    },
    {
      id: "8",
      title: "Young Folks",
      artist: "Peter Bjorn and John",
      imagheUrl:
        "https://i.scdn.co/image/ab67616d0000b273db2c07b93263280a636c1567",
    },
    {
      id: "9",
      title: "Electricity",
      artist: "Orchestral Manoeuvres in the Dark",
      imagheUrl:
        "https://i.scdn.co/image/ab67616d0000b27346c913077ad733cf423eab13",
    },
    {
      id: "10",
      title: "Electric Avenue",
      artist: "Eddy Grant",
      imagheUrl:
        "https://i.scdn.co/image/ab67616d0000b2731bb60b953cfcf692a4593dd0",
    },
    {
      id: "11",
      title: "Electricity",
      artist: " Dua Lipa",
      imagheUrl:
        "https://i.scdn.co/image/ab67616d0000b273a334001297c78a5da11d5b58",
    },
    {
      id: "12",
      title: "Electric Feel (Justice Remix)",
      artist: "MGMT",
      imagheUrl:
        "https://i.scdn.co/image/ab67616d0000b273a798fc88faec4742d22c59d6",
    },
    {
      id: "13",
      title: "Electric Daisy Violin",
      artist: "Lindsey Stirling",
      imagheUrl:
        "https://i.scdn.co/image/ab67616d0000b2735dd445aedd1a14524aa9ef79",
    },
    {
      id: "14",
      title: "Electricity (From 'Billy Elliot')",
      artist: "Elton John",
      imagheUrl:
        "https://i.scdn.co/image/ab67616d0000b27398c23219a69071231259c821",
    },
    {
      id: "15",
      title: "Electric Ladyland",
      artist: "The Jimi Hendrix Experience",
      imagheUrl:
        "https://i.scdn.co/image/ab67616d0000b273522088789d49e216d9818292",
    },
    //2
    {
      id: "16",
      title: "Fortnight",
      subtitle: "Pop",
      imagheUrl:
        "https://i.scdn.co/image/ab67616d0000b273e6b77b3eef9269d06e13fe17",
      artist: "Taylor Swift ft. Post Malone",
    },
    {
      id: "17",
      title: "Love Me JeJe",
      subtitle: "Afrobeats",
      imagheUrl:
        "https://i.scdn.co/image/ab67616d0000b273142605c02c45f3de0feb94d4",
      artist: "Tems",
      lastPlayed: "1 week ago",
    },
    {
      id: "18",
      title: "Die With A Smile",
      subtitle: "Pop",
      imagheUrl:
        "https://i.scdn.co/image/ab67616d0000b27382ea2e9e1858aa012c57cd45",
      artist: "Lady Gaga",
      lastPlayed: "3 days ago",
    },
    {
      id: "19",
      title: "São Paulo",
      subtitle: "Latin Pop",
      imagheUrl:
        "https://image-cdn-ak.spotifycdn.com/image/ab67706c0000da84192e13ef5b5e238b600d976c",
      artist: "Anitta ft. The Weeknd",
      lastPlayed: "5 days ago",
    },
    {
      id: "20",
      title: "Some Sexy Songs 4 U",
      subtitle: "R&B",
      imagheUrl:
        "https://i.scdn.co/image/ab6765630000ba8a3362a86489a185350b9fb12a",
      artist: "Drake & PartyNextDoor",
      lastPlayed: "1 day ago",
    },

    {
      id: "21",
      title: "Blinding Lights",
      subtitle: "Synthwave",
      imagheUrl:
        "https://i.scdn.co/image/ab67616d0000b273a3eff72f62782fb589a492f9",
      artist: "The Weeknd",
      lastPlayed: "1 day ago",
    },

    {
      id: "22",
      title: "Levitating",
      subtitle: "Disco-Pop",
      imagheUrl:
        "https://i.scdn.co/image/ab67616d0000b2734bc66095f8a70bc4e6593f4f",
      artist: "Dua Lipa ft. DaBaby",
      lastPlayed: "3 days ago",
    },

    {
      id: "23",
      title: "Watermelon Sugar",
      subtitle: "Pop",
      imagheUrl:
        "https://i.scdn.co/image/ab67616d0000b27377fdcfda6535601aff081b6a",
      artist: "Harry Styles",
      lastPlayed: "2 days ago",
    },

    {
      id: "24",
      title: "Peaches",
      subtitle: "R&B",
      imagheUrl:
        "https://i.scdn.co/image/ab67616d0000b273e6f407c7f3a0ec98845e4431",
      artist: "Justin Bieber ft. Daniel Caesar & Giveon",
      lastPlayed: "1 week ago",
    },
  ];

  return (
    <ScrollView
      style={{
        flex: 1,
        backgroundColor: "#0a0a0a",
      }}
      contentContainerStyle={{
        flexGrow: 1,
        paddingVertical: 20,
      }}
      showsVerticalScrollIndicator={false}
      scrollEnabled={true}
      contentInsetAdjustmentBehavior="always"
    >
      <SafeAreaView style={{ flex: 1 }}>
        <View
          style={{
            paddingHorizontal: 20,
            paddingBottom: 24,
          }}
        >
          <Row style={{ alignItems: "center", marginTop: 5 }}>
            <View className="top-3 mr-2">
              <MaterialCommunityIcons
                name="cards-playing"
                size={35}
                color="white"
              />
            </View>

            <Text
              style={{
                fontSize: 28,
                fontWeight: "700",
                color: "#fafafa",
                marginBottom: 6,
              }}
            >
              Recently Played
            </Text>
          </Row>
          <Text
            style={{
              fontSize: 15,
              color: "#71717a",
              marginLeft: 45,
              bottom: 5,
            }}
          >
            Your favorite tracks from this week
          </Text>
        </View>

        <MediaList
          data={mediaData}
          chunkSize={4}
          keyExtractor={(item) => item.id}
          screenWidth={WIDTH}
          blurIntensity={10}
          animationConfig={{
            rotate: true,
          }}
          contentContainerStyle={{
            paddingLeft: 20,
          }}
          renderItem={(item, index) => (
            <TouchableOpacity
              key={item.id}
              activeOpacity={0.7}
              style={{
                marginBottom: index === mediaData.length - 1 ? 0 : 1,
              }}
            >
              <View
                style={{
                  flexDirection: "row",
                  alignItems: "center",
                  paddingVertical: 12,
                  paddingHorizontal: 0,
                }}
              >
                <Image
                  source={{ uri: item.imageUrl }}
                  style={{
                    width: 48,
                    height: 48,
                    borderRadius: 6,
                    backgroundColor: "#18181b",
                  }}
                />

                <View style={{ flex: 1, marginLeft: 12 }}>
                  <Text
                    style={{
                      fontSize: 15,
                      fontWeight: "500",
                      color: "#fafafa",
                      marginBottom: 2,
                    }}
                    numberOfLines={1}
                  >
                    {item.title}
                  </Text>
                  <Text
                    style={{
                      fontSize: 13,
                      color: "#71717a",
                      fontWeight: "400",
                    }}
                    numberOfLines={1}
                  >
                    {item.artist}
                  </Text>
                </View>

                <View
                  style={{
                    flexDirection: "row",
                    alignItems: "center",
                  }}
                >
                  <Text
                    style={{
                      fontSize: 12,
                      color: "#52525b",
                      marginRight: 8,
                      fontWeight: "400",
                    }}
                  >
                    {item.lastPlayed}
                  </Text>
                  <TouchableOpacity
                    style={{
                      padding: 4,
                      marginRight: 10,
                    }}
                  >
                    <Ionicons
                      name="ellipsis-horizontal"
                      size={16}
                      color="#52525b"
                    />
                  </TouchableOpacity>
                </View>
              </View>

              {index !== mediaData.length - 1 && (
                <View
                  style={{
                    height: 0.96,
                    backgroundColor: "#18181b",
                    marginLeft: 60,
                    bottom: 8,
                  }}
                />
              )}
            </TouchableOpacity>
          )}
        />
        <View className="ml-5 mt-3">
          <Row style={{ alignItems: "center" }}>
            <Feather name="info" size={24} color="#b0b0b0" />
            <Text className="text-zinc-500">
              ∙ All of your recently played tracks in one place
            </Text>
          </Row>
        </View>

        <View
          style={{
            alignItems: "center",
            marginTop: 20,
            marginLeft: 20,
            flexDirection: "row",
          }}
        >
          <View className="justify-center items-center">
            <Ionicons name="sparkles" size={24} color="white" />
          </View>
          <View className="ml-5 justify-center">
            <Text
              style={{
                fontSize: 28,
                fontWeight: "700",
                color: "#fafafa",
                marginBottom: 6,
              }}
            >
              Suggestions
            </Text>
            <Text
              style={{
                fontSize: 15,
                color: "#71717a",

                bottom: 5,
              }}
            >
              Based on your recent listening habits
            </Text>
          </View>
        </View>

        <MediaList
          data={suggestionSongs}
          chunkSize={4}
          keyExtractor={(item) => item.id}
          screenWidth={WIDTH}
          blurIntensity={10}
          animationConfig={{
            scale: true,
            translateY: true,
            rotate: true,
          }}
          contentContainerStyle={{
            paddingLeft: 20,
          }}
          renderItem={(item, index) => (
            <TouchableOpacity
              key={item.id}
              activeOpacity={0.7}
              style={{
                marginBottom: index === mediaData.length - 1 ? 0 : 1,
              }}
            >
              <View
                style={{
                  flexDirection: "row",
                  alignItems: "center",
                  paddingVertical: 12,
                  paddingHorizontal: 0,
                }}
              >
                <Image
                  source={{ uri: item.imagheUrl }}
                  style={{
                    width: 48,
                    height: 48,
                    borderRadius: 6,
                    backgroundColor: "#18181b",
                  }}
                />

                <View style={{ flex: 1, marginLeft: 12 }}>
                  <Text
                    style={{
                      fontSize: 15,
                      fontWeight: "500",
                      color: "#fafafa",
                      marginBottom: 2,
                    }}
                    numberOfLines={1}
                  >
                    {item.title}
                  </Text>
                  <Text
                    style={{
                      fontSize: 13,
                      color: "#71717a",
                      fontWeight: "400",
                    }}
                    numberOfLines={1}
                  >
                    {item.artist}
                  </Text>
                </View>

                <View
                  style={{
                    flexDirection: "row",
                    alignItems: "center",
                  }}
                >
                  <Text
                    style={{
                      fontSize: 12,
                      color: "#52525b",
                      marginRight: 8,
                      fontWeight: "400",
                    }}
                  >
                    {item.lastPlayed}
                  </Text>
                  <TouchableOpacity
                    style={{
                      padding: 4,
                      marginRight: 10,
                    }}
                  >
                    <Ionicons
                      name="ellipsis-horizontal"
                      size={16}
                      color="#52525b"
                    />
                  </TouchableOpacity>
                </View>
              </View>

              {index !== mediaData.length - 1 && (
                <View
                  style={{
                    height: 0.96,
                    backgroundColor: "#18181b",
                    marginLeft: 60,
                    bottom: 8,
                  }}
                />
              )}
            </TouchableOpacity>
          )}
        />
      </SafeAreaView>
    </ScrollView>
  );
};

export default MediaListDemo;