Index: frontend/src/components/PlaylistDropdown.tsx
===================================================================
--- frontend/src/components/PlaylistDropdown.tsx	(revision ce45c7a7871379455b3a3c55a48f767ca2e0e739)
+++ frontend/src/components/PlaylistDropdown.tsx	(revision ce45c7a7871379455b3a3c55a48f767ca2e0e739)
@@ -0,0 +1,252 @@
+import { useEffect, useRef, useState } from "react";
+import { createPortal } from "react-dom";
+import axiosInstance from "../api/axiosInstance";
+import { useCreatedPlaylists } from "../context/playlistContext";
+
+interface PlaylistDropdownProps {
+  songId: number;
+  isOpen: boolean;
+  onClose: () => void;
+  position?: { top: number; left: number };
+
+  usePortal?: boolean;
+
+  direction?: "above" | "below";
+
+  onCreateNewPlaylist?: () => void;
+}
+
+const PlaylistDropdown = ({
+  songId,
+  isOpen,
+  onClose,
+  position,
+  usePortal = false,
+  direction = "above",
+  onCreateNewPlaylist,
+}: PlaylistDropdownProps) => {
+  const { createdPlaylists, refreshPlaylists } = useCreatedPlaylists();
+  const [containingPlaylistIds, setContainingPlaylistIds] = useState<number[]>(
+    [],
+  );
+  const [loading, setLoading] = useState(false);
+  const [processingPlaylistId, setProcessingPlaylistId] = useState<
+    number | null
+  >(null);
+  const dropdownRef = useRef<HTMLDivElement>(null);
+
+  useEffect(() => {
+    if (isOpen && songId) {
+      const fetchPlaylistIds = async () => {
+        setLoading(true);
+        setContainingPlaylistIds([]);
+        try {
+          const response = await axiosInstance.get<number[]>(
+            `/playlists/song/${songId}`,
+          );
+          setContainingPlaylistIds(response.data);
+        } catch (error) {
+          console.error("Failed to fetch song presence:", error);
+        } finally {
+          setLoading(false);
+        }
+      };
+      fetchPlaylistIds();
+    } else {
+      setContainingPlaylistIds([]);
+    }
+  }, [isOpen, songId]);
+
+  useEffect(() => {
+    const handleClickOutside = (event: MouseEvent) => {
+      if (
+        dropdownRef.current &&
+        !dropdownRef.current.contains(event.target as Node)
+      ) {
+        onClose();
+      }
+    };
+
+    if (isOpen) {
+      document.addEventListener("mousedown", handleClickOutside);
+    }
+    return () => document.removeEventListener("mousedown", handleClickOutside);
+  }, [isOpen, onClose]);
+
+  const handleTogglePlaylist = async (playlistId: number, songId: number) => {
+    if (processingPlaylistId !== null) return;
+
+    setProcessingPlaylistId(playlistId);
+
+    try {
+      const response = await axiosInstance.post<{
+        playlistId: number;
+        isSongAddedToPlaylist: boolean;
+      }>(`/playlists/${playlistId}/song/${songId}`);
+
+      const { playlistId: returnedPlaylistId, isSongAddedToPlaylist } =
+        response.data;
+
+      if (isSongAddedToPlaylist) {
+        setContainingPlaylistIds((prev) =>
+          prev.includes(returnedPlaylistId)
+            ? prev
+            : [...prev, returnedPlaylistId],
+        );
+      } else {
+        setContainingPlaylistIds((prev) =>
+          prev.filter((id) => id !== returnedPlaylistId),
+        );
+      }
+    } catch (error) {
+      console.error("Failed to toggle playlist:", error);
+    } finally {
+      refreshPlaylists(true);
+      setTimeout(() => {
+        setProcessingPlaylistId(null);
+      }, 500);
+    }
+  };
+
+  const handleCreateNew = () => {
+    onCreateNewPlaylist?.();
+    onClose();
+  };
+
+  if (!isOpen) return null;
+
+  const inlinePositionClass =
+    direction === "below"
+      ? "absolute left-0 top-full mt-2"
+      : "absolute right-0 bottom-full mb-2";
+
+  const dropdownContent = (
+    <div
+      ref={dropdownRef}
+      className={`${usePortal ? "fixed" : inlinePositionClass} w-56 bg-[#282828] rounded-lg shadow-2xl py-2 z-[9999] border border-white/10 max-h-60 overflow-y-auto custom-scrollbar`}
+      style={
+        usePortal && position
+          ? {
+              top: position.top,
+              left: position.left,
+              transform:
+                direction === "below" ? undefined : "translateY(-100%)",
+            }
+          : undefined
+      }
+      onClick={(e) => e.stopPropagation()}
+    >
+      <div className="px-4 py-2 text-xs font-bold text-gray-400 uppercase tracking-wider border-b border-white/5 mb-1">
+        Add to playlist
+      </div>
+
+      {loading ? (
+        <div className="flex items-center justify-center py-4">
+          <div className="w-5 h-5 border-2 border-white/10 border-t-[#1db954] rounded-full animate-spin"></div>
+        </div>
+      ) : createdPlaylists && createdPlaylists.length > 0 ? (
+        createdPlaylists.map((playlist) => {
+          const isProcessing = processingPlaylistId === playlist.id;
+          const isChecked = containingPlaylistIds.includes(playlist.id);
+
+          return (
+            <label
+              key={playlist.id}
+              className={`flex items-center px-4 py-2 hover:bg-white/10 transition-colors group/item ${
+                isProcessing ? "pointer-events-none" : "cursor-pointer"
+              }`}
+              onClick={(e) => e.stopPropagation()}
+            >
+              <div className="relative flex items-center justify-center">
+                <input
+                  type="checkbox"
+                  className="peer sr-only"
+                  checked={isChecked}
+                  disabled={processingPlaylistId !== null}
+                  onChange={() => handleTogglePlaylist(playlist.id, songId)}
+                />
+                <div
+                  className={`w-5 h-5 border-2 rounded bg-[#181818] transition-all ${
+                    isProcessing
+                      ? "border-[#1db954] animate-pulse"
+                      : isChecked
+                        ? "bg-[#1db954] border-[#1db954]"
+                        : "border-gray-500"
+                  }`}
+                >
+                  {isProcessing && (
+                    <div className="absolute inset-0 flex items-center justify-center">
+                      <div className="w-3 h-3 border-2 border-transparent border-t-[#1db954] rounded-full animate-spin"></div>
+                    </div>
+                  )}
+                </div>
+                <svg
+                  className={`absolute w-3 h-3  transition-opacity ${
+                    isChecked && !isProcessing ? "opacity-100" : "opacity-0"
+                  }`}
+                  fill="none"
+                  stroke="currentColor"
+                  strokeWidth="3"
+                  viewBox="0 0 24 24"
+                >
+                  <path
+                    strokeLinecap="round"
+                    strokeLinejoin="round"
+                    d="M5 13l4 4L19 7"
+                  />
+                </svg>
+              </div>
+              <span
+                className={`ml-3 text-sm truncate transition-all ${
+                  isProcessing
+                    ? "text-[#1db954] animate-pulse"
+                    : "text-gray-200 group-hover/item:text-white"
+                }`}
+              >
+                {playlist.name}
+              </span>
+              {isProcessing && (
+                <span className="ml-auto text-xs text-[#1db954] animate-pulse">
+                  •••
+                </span>
+              )}
+            </label>
+          );
+        })
+      ) : (
+        <div className="px-4 py-3 text-sm text-gray-500 italic">
+          No playlists created
+        </div>
+      )}
+
+      <button
+        onClick={(e) => {
+          e.stopPropagation();
+          handleCreateNew();
+        }}
+        className="w-full text-left px-4 py-2 mt-1 text-sm text-[#1db954] hover:bg-white/5 transition-colors border-t border-white/5 flex items-center gap-2 font-medium cursor-pointer"
+      >
+        <svg
+          className="w-4 h-4"
+          fill="none"
+          stroke="currentColor"
+          viewBox="0 0 24 24"
+        >
+          <path
+            strokeLinecap="round"
+            strokeLinejoin="round"
+            strokeWidth={2}
+            d="M12 4v16m8-8H4"
+          />
+        </svg>
+        Create new playlist
+      </button>
+    </div>
+  );
+
+  return usePortal
+    ? createPortal(dropdownContent, document.body)
+    : dropdownContent;
+};
+
+export default PlaylistDropdown;
Index: frontend/src/components/Sidebar.tsx
===================================================================
--- frontend/src/components/Sidebar.tsx	(revision 85512ff50bc46445db00d8c3ecea57616baddb36)
+++ frontend/src/components/Sidebar.tsx	(revision ce45c7a7871379455b3a3c55a48f767ca2e0e739)
@@ -48,5 +48,5 @@
       await axiosInstance.post("/playlists", { name: playlistName });
       toast.success("Playlist created successfully!");
-      await refreshPlaylists();
+      await refreshPlaylists(false);
     } catch (error) {
       toast.error(getErrorMessage(error));
Index: frontend/src/components/SongItem.tsx
===================================================================
--- frontend/src/components/SongItem.tsx	(revision 85512ff50bc46445db00d8c3ecea57616baddb36)
+++ frontend/src/components/SongItem.tsx	(revision ce45c7a7871379455b3a3c55a48f767ca2e0e739)
@@ -1,259 +1,248 @@
-import { useEffect, useRef, useState } from "react";
+import { useRef, useState } from "react";
 import { useNavigate } from "react-router-dom";
 import { baseURL } from "../api/axiosInstance";
 import { usePlayer } from "../context/playerContext";
 import { toEmbedUrl } from "../utils/utils";
+import PlaylistDropdown from "./PlaylistDropdown";
 
 export interface SongItemData {
-	id: number;
-	title: string;
-	cover?: string | null;
-	genre?: string;
-	link?: string | null;
-	releasedBy?: string;
-	isLikedByCurrentUser?: boolean;
+  id: number;
+  title: string;
+  cover?: string | null;
+  genre?: string;
+  link?: string | null;
+  releasedBy?: string;
+  isLikedByCurrentUser?: boolean;
 }
 
 interface SongItemProps {
-	song: SongItemData;
-	/** Optional label shown before the artist, e.g. "Song" for search results */
-	label?: string;
-	/** Optional role badge for artist contributions, e.g. "PERFORMER" */
-	role?: string;
-	/** Optional index number for playlist/collection views */
-	index?: number;
-	/** Callback when the like button is clicked */
-	onLikeToggle?: (songId: number) => void;
+  song: SongItemData;
+  /** Optional label shown before the artist, e.g. "Song" for search results */
+  label?: string;
+  /** Optional role badge for artist contributions, e.g. "PERFORMER" */
+  role?: string;
+  /** Optional index number for playlist/collection views */
+  index?: number;
+  /** Callback when the like button is clicked */
+  onLikeToggle?: (songId: number) => void;
+  /** Controlled: whether the playlist dropdown is open */
+  isDropdownOpen?: boolean;
+  /** Controlled: callback when dropdown should open/close */
+  onDropdownToggle?: (songId: number | null) => void;
 }
 
 const ROLE_COLORS: { [key: string]: string } = {
-	COMPOSER: "bg-purple-500/20 text-purple-300",
-	PERFORMER: "bg-blue-500/20 text-blue-300",
-	PRODUCER: "bg-green-500/20 text-green-300",
-	MAIN_VOCAL: "bg-pink-500/20 text-pink-300",
+  COMPOSER: "bg-purple-500/20 text-purple-300",
+  PERFORMER: "bg-blue-500/20 text-blue-300",
+  PRODUCER: "bg-green-500/20 text-green-300",
+  MAIN_VOCAL: "bg-pink-500/20 text-pink-300",
 };
 
 const SongItem = ({
-	song,
-	label,
-	role,
-	index,
-	onLikeToggle,
+  song,
+  label,
+  role,
+  index,
+  onLikeToggle,
+  isDropdownOpen,
+  onDropdownToggle,
 }: SongItemProps) => {
-	const navigate = useNavigate();
-	const { play, currentSong } = usePlayer();
-	const [playlistOpen, setPlaylistOpen] = useState(false);
-	const dropdownRef = useRef<HTMLDivElement>(null);
-
-	const isPlaying = currentSong?.id === song.id;
-
-	useEffect(() => {
-		const handleClickOutside = (event: MouseEvent) => {
-			if (
-				dropdownRef.current &&
-				!dropdownRef.current.contains(event.target as Node)
-			) {
-				setPlaylistOpen(false);
-			}
-		};
-		if (playlistOpen) {
-			document.addEventListener("mousedown", handleClickOutside);
-		}
-		return () => document.removeEventListener("mousedown", handleClickOutside);
-	}, [playlistOpen]);
-
-	const handleAddToPlaylist = (playlistName: string) => {
-		console.log(`Adding song ${song.id} to ${playlistName}`);
-		// TODO: Implement actual API call
-		setPlaylistOpen(false);
-	};
-
-	const handleCreateNewPlaylist = () => {
-		console.log(`Creating new playlist for song ${song.id}`);
-		// TODO: Implement actual playlist creation
-		setPlaylistOpen(false);
-	};
-
-	// Build subtitle
-	const subtitleParts: string[] = [];
-	if (label) subtitleParts.push(label);
-	if (song.releasedBy) subtitleParts.push(song.releasedBy);
-	const subtitle = subtitleParts.join(" • ");
-
-	return (
-		<div
-			onClick={() => navigate(`/songs/${song.id}`)}
-			className="flex items-center gap-4 p-3 rounded-lg hover:bg-white/5 cursor-pointer transition-colors group"
-		>
-			{/* Optional index */}
-			{index != null && (
-				<span className="text-gray-500 font-medium w-8 text-center text-sm shrink-0">
-					{index}
-				</span>
-			)}
-
-			{/* Cover */}
-			<img
-				src={song.cover ? `${baseURL}/${song.cover}` : "/favicon.png"}
-				alt={song.title}
-				className="w-12 h-12 rounded object-cover shrink-0"
-				onError={(e) => {
-					(e.target as HTMLImageElement).src = "/favicon.png";
-				}}
-			/>
-
-			{/* Title & subtitle */}
-			<div className="flex-1 min-w-0">
-				<p
-					className={`font-medium truncate ${
-						isPlaying ? "text-[#1db954]" : "text-white"
-					}`}
-				>
-					{song.title}
-				</p>
-				{subtitle && (
-					<p className="text-sm text-gray-400 truncate">{subtitle}</p>
-				)}
-			</div>
-
-			{/* Role badge (artist contributions) */}
-			{role && (
-				<span
-					className={`px-3 py-1 rounded-full text-xs font-medium hidden sm:block ${
-						ROLE_COLORS[role] || "bg-white/10 text-gray-300"
-					}`}
-				>
-					{role.replace("_", " ")}
-				</span>
-			)}
-
-			{/* Genre */}
-			{song.genre && (
-				<span className="text-xs text-gray-500 uppercase tracking-wider mr-2 hidden sm:block">
-					{song.genre}
-				</span>
-			)}
-
-			{/* Play button */}
-			{song.link && (
-				<button
-					onClick={(e) => {
-						e.stopPropagation();
-						play({
-							id: song.id,
-							title: song.title,
-							artist: song.releasedBy || "",
-							cover: song.cover,
-							embedUrl: toEmbedUrl(song.link!),
-						});
-					}}
-					className={`p-2 rounded-full transition-all cursor-pointer ${
-						isPlaying
-							? "bg-white text-[#1db954] opacity-100"
-							: "bg-[#1db954] text-black hover:scale-110 opacity-0 group-hover:opacity-100"
-					}`}
-					aria-label={isPlaying ? "Now playing" : "Play song"}
-				>
-					{isPlaying ? (
-						<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
-							<path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
-						</svg>
-					) : (
-						<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
-							<path d="M8 5v14l11-7z" />
-						</svg>
-					)}
-				</button>
-			)}
-
-			{/* Like button */}
-			{onLikeToggle && (
-				<button
-					onClick={(e) => {
-						e.stopPropagation();
-						onLikeToggle(song.id);
-					}}
-					className="p-2 hover:bg-white/10 rounded-full transition-colors cursor-pointer"
-					aria-label={song.isLikedByCurrentUser ? "Unlike" : "Like"}
-				>
-					<svg
-						className="w-5 h-5"
-						fill={song.isLikedByCurrentUser ? "#ef4444" : "none"}
-						stroke={song.isLikedByCurrentUser ? "#ef4444" : "#6b7280"}
-						strokeWidth="2"
-						viewBox="0 0 24 24"
-					>
-						<path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
-					</svg>
-				</button>
-			)}
-
-			{/* Three-dot menu */}
-			<div className="relative" ref={dropdownRef}>
-				<button
-					onClick={(e) => {
-						e.stopPropagation();
-						setPlaylistOpen((prev) => !prev);
-					}}
-					className="p-2 hover:bg-white/10 rounded-full transition-colors cursor-pointer text-gray-400 hover:text-white"
-					aria-label="More options"
-				>
-					<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
-						<circle cx="12" cy="5" r="1.5" />
-						<circle cx="12" cy="12" r="1.5" />
-						<circle cx="12" cy="19" r="1.5" />
-					</svg>
-				</button>
-
-				{playlistOpen && (
-					<div className="absolute right-0 bottom-full mb-2 w-48 bg-[#282828] border border-white/10 rounded-lg shadow-lg py-1 z-50">
-						<div className="px-3 py-2 text-xs text-gray-400 border-b border-white/10">
-							Add to playlist
-						</div>
-						<button
-							onClick={(e) => {
-								e.stopPropagation();
-								handleAddToPlaylist("Playlist 1");
-							}}
-							className="w-full text-left px-4 py-2 text-sm text-white hover:bg-white/10 transition-colors"
-						>
-							Playlist 1
-						</button>
-						<button
-							onClick={(e) => {
-								e.stopPropagation();
-								handleAddToPlaylist("Playlist 2");
-							}}
-							className="w-full text-left px-4 py-2 text-sm text-white hover:bg-white/10 transition-colors"
-						>
-							Playlist 2
-						</button>
-						<button
-							onClick={(e) => {
-								e.stopPropagation();
-								handleCreateNewPlaylist();
-							}}
-							className="w-full text-left px-4 py-2 text-sm text-[#1db954] hover:bg-white/10 transition-colors border-t border-white/10 flex items-center gap-2"
-						>
-							<svg
-								className="w-4 h-4"
-								fill="none"
-								stroke="currentColor"
-								viewBox="0 0 24 24"
-							>
-								<path
-									strokeLinecap="round"
-									strokeLinejoin="round"
-									strokeWidth={2}
-									d="M12 4v16m8-8H4"
-								/>
-							</svg>
-							Create new playlist
-						</button>
-					</div>
-				)}
-			</div>
-		</div>
-	);
+  const navigate = useNavigate();
+  const { play, currentSong } = usePlayer();
+  const [internalOpen, setInternalOpen] = useState(false);
+  const [dropdownPosition, setDropdownPosition] = useState({ top: 0, left: 0 });
+  const [dropdownDirection, setDropdownDirection] = useState<"above" | "below">(
+    "below",
+  );
+  const buttonRef = useRef<HTMLButtonElement>(null);
+
+  const playlistOpen = isDropdownOpen ?? internalOpen;
+  const setPlaylistOpen = (open: boolean) => {
+    if (onDropdownToggle) {
+      onDropdownToggle(open ? song.id : null);
+    } else {
+      setInternalOpen(open);
+    }
+  };
+
+  const isPlaying = currentSong?.id === song.id;
+
+  const handleCreateNewPlaylist = () => {
+    console.log(`Creating new playlist for song ${song.id}`);
+    // TODO: Implement actual playlist creation
+    setPlaylistOpen(false);
+  };
+
+  const subtitleParts: string[] = [];
+  if (label) subtitleParts.push(label);
+  if (song.releasedBy) subtitleParts.push(song.releasedBy);
+  const subtitle = subtitleParts.join(" • ");
+
+  return (
+    <div
+      onClick={() => navigate(`/songs/${song.id}`)}
+      onMouseEnter={() => {
+        if (onDropdownToggle && !playlistOpen) {
+          onDropdownToggle(null);
+        }
+      }}
+      className="flex items-center gap-4 p-3 rounded-lg hover:bg-white/5 cursor-pointer transition-colors group"
+    >
+      {/* Optional index */}
+      {index != null && (
+        <span className="text-gray-500 font-medium w-8 text-center text-sm shrink-0">
+          {index}
+        </span>
+      )}
+
+      {/* Cover */}
+      <img
+        src={song.cover ? `${baseURL}/${song.cover}` : "/favicon.png"}
+        alt={song.title}
+        className="w-12 h-12 rounded object-cover shrink-0"
+        onError={(e) => {
+          (e.target as HTMLImageElement).src = "/favicon.png";
+        }}
+      />
+
+      {/* Title & subtitle */}
+      <div className="flex-1 min-w-0">
+        <p
+          className={`font-medium truncate ${
+            isPlaying ? "text-[#1db954]" : "text-white"
+          }`}
+        >
+          {song.title}
+        </p>
+        {subtitle && (
+          <p className="text-sm text-gray-400 truncate">{subtitle}</p>
+        )}
+      </div>
+
+      {/* Role badge (artist contributions) */}
+      {role && (
+        <span
+          className={`px-3 py-1 rounded-full text-xs font-medium hidden sm:block ${
+            ROLE_COLORS[role] || "bg-white/10 text-gray-300"
+          }`}
+        >
+          {role.replace("_", " ")}
+        </span>
+      )}
+
+      {/* Genre */}
+      {song.genre && (
+        <span className="text-xs text-gray-500 uppercase tracking-wider mr-2 hidden sm:block">
+          {song.genre}
+        </span>
+      )}
+
+      {/* Play button */}
+      {song.link && (
+        <button
+          onClick={(e) => {
+            e.stopPropagation();
+            play({
+              id: song.id,
+              title: song.title,
+              artist: song.releasedBy || "",
+              cover: song.cover,
+              embedUrl: toEmbedUrl(song.link!),
+            });
+          }}
+          className={`p-2 rounded-full transition-all cursor-pointer ${
+            isPlaying
+              ? "bg-white text-[#1db954] opacity-100"
+              : "bg-[#1db954] text-black hover:scale-110 opacity-0 group-hover:opacity-100"
+          }`}
+          aria-label={isPlaying ? "Now playing" : "Play song"}
+        >
+          {isPlaying ? (
+            <svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
+              <path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
+            </svg>
+          ) : (
+            <svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
+              <path d="M8 5v14l11-7z" />
+            </svg>
+          )}
+        </button>
+      )}
+
+      {/* Like button */}
+      {onLikeToggle && (
+        <button
+          onClick={(e) => {
+            e.stopPropagation();
+            onLikeToggle(song.id);
+          }}
+          className="p-2 hover:bg-white/10 rounded-full transition-colors cursor-pointer"
+          aria-label={song.isLikedByCurrentUser ? "Unlike" : "Like"}
+        >
+          <svg
+            className="w-5 h-5"
+            fill={song.isLikedByCurrentUser ? "#ef4444" : "none"}
+            stroke={song.isLikedByCurrentUser ? "#ef4444" : "#6b7280"}
+            strokeWidth="2"
+            viewBox="0 0 24 24"
+          >
+            <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
+          </svg>
+        </button>
+      )}
+
+      {/* Three-dot menu */}
+      <div className="relative">
+        <button
+          ref={buttonRef}
+          onClick={(e) => {
+            e.stopPropagation();
+            if (playlistOpen) {
+              setPlaylistOpen(false);
+            } else {
+              if (buttonRef.current) {
+                const rect = buttonRef.current.getBoundingClientRect();
+                const spaceBelow = window.innerHeight - rect.bottom;
+                const dropdownHeight = 260;
+
+                if (spaceBelow < dropdownHeight) {
+                  setDropdownDirection("above");
+                  setDropdownPosition({
+                    top: rect.top - 8,
+                    left: rect.right - 224,
+                  });
+                } else {
+                  setDropdownDirection("below");
+                  setDropdownPosition({
+                    top: rect.bottom + 8,
+                    left: rect.right - 224,
+                  });
+                }
+              }
+              setPlaylistOpen(true);
+            }
+          }}
+          className="p-2 hover:bg-white/10 rounded-full transition-colors cursor-pointer text-gray-400 hover:text-white"
+          aria-label="More options"
+        >
+          <svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
+            <circle cx="12" cy="5" r="1.5" />
+            <circle cx="12" cy="12" r="1.5" />
+            <circle cx="12" cy="19" r="1.5" />
+          </svg>
+        </button>
+
+        <PlaylistDropdown
+          songId={song.id}
+          isOpen={playlistOpen}
+          onClose={() => setPlaylistOpen(false)}
+          position={dropdownPosition}
+          usePortal={true}
+          direction={dropdownDirection}
+          onCreateNewPlaylist={handleCreateNewPlaylist}
+        />
+      </div>
+    </div>
+  );
 };
 
Index: frontend/src/components/userProfile/ArtistView.tsx
===================================================================
--- frontend/src/components/userProfile/ArtistView.tsx	(revision 85512ff50bc46445db00d8c3ecea57616baddb36)
+++ frontend/src/components/userProfile/ArtistView.tsx	(revision ce45c7a7871379455b3a3c55a48f767ca2e0e739)
@@ -8,144 +8,149 @@
 
 interface ArtistViewProps {
-	contributions: ArtistContribution[];
+  contributions: ArtistContribution[];
 }
 
 const ArtistView = ({ contributions }: ArtistViewProps) => {
-	const navigate = useNavigate();
-	const [items, setItems] = useState(contributions);
+  const navigate = useNavigate();
+  const [items, setItems] = useState(contributions);
+  const [openDropdownSongId, setOpenDropdownSongId] = useState<number | null>(
+    null,
+  );
 
-	const albums = items.filter((c) => c.entityType === "ALBUM");
-	const songs = items.filter((c) => c.entityType === "SONG");
+  const albums = items.filter((c) => c.entityType === "ALBUM");
+  const songs = items.filter((c) => c.entityType === "SONG");
 
-	const getRoleColor = (role: string) => {
-		const colors: { [key: string]: string } = {
-			COMPOSER: "bg-purple-500/20 text-purple-300",
-			PERFORMER: "bg-blue-500/20 text-blue-300",
-			PRODUCER: "bg-green-500/20 text-green-300",
-			MAIN_VOCAL: "bg-pink-500/20 text-pink-300",
-		};
-		return colors[role] || "bg-white/10 text-gray-300";
-	};
+  const getRoleColor = (role: string) => {
+    const colors: { [key: string]: string } = {
+      COMPOSER: "bg-purple-500/20 text-purple-300",
+      PERFORMER: "bg-blue-500/20 text-blue-300",
+      PRODUCER: "bg-green-500/20 text-green-300",
+      MAIN_VOCAL: "bg-pink-500/20 text-pink-300",
+    };
+    return colors[role] || "bg-white/10 text-gray-300";
+  };
 
-	const handleLike = async (id: number, title: string) => {
-		try {
-			const response = await axiosInstance.post(`/musical-entity/${id}/like`);
-			const data = response.data;
+  const handleLike = async (id: number, title: string) => {
+    try {
+      const response = await axiosInstance.post(`/musical-entity/${id}/like`);
+      const data = response.data;
 
-			setItems((prevItems) =>
-				prevItems.map((item) =>
-					item.id === data.entityId
-						? { ...item, isLikedByCurrentUser: data.isLiked }
-						: item,
-				),
-			);
-			toast.success(
-				data.isLiked ? `Liked "${title}"` : `Removed "${title}" from likes`,
-			);
-		} catch (err: any) {
-			toast.error(err.response?.data?.error || "Failed to like the item");
-		}
-	};
+      setItems((prevItems) =>
+        prevItems.map((item) =>
+          item.id === data.entityId
+            ? { ...item, isLikedByCurrentUser: data.isLiked }
+            : item,
+        ),
+      );
+      toast.success(
+        data.isLiked ? `Liked "${title}"` : `Removed "${title}" from likes`,
+      );
+    } catch (err: any) {
+      toast.error(err.response?.data?.error || "Failed to like the item");
+    }
+  };
 
-	return (
-		<div className="mt-8">
-			{albums.length > 0 && (
-				<div className="mb-12">
-					<div className="flex items-center gap-3 mb-6">
-						<Disc3 className="w-6 h-6 text-[#1db954]" />
-						<h2 className="text-2xl font-bold text-white">Albums</h2>
-					</div>
-					<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
-						{albums.map((album) => (
-							<div
-								key={album.id}
-								className="group cursor-pointer"
-								onClick={() => navigate(`/collection/album/${album.id}`)}
-							>
-								<div className="relative aspect-square rounded-lg mb-3 overflow-hidden shadow-md group-hover:shadow-xl transition-all duration-300 bg-[#181818]">
-									<img
-										src={
-											album.cover ? `${baseURL}/${album.cover}` : "/favicon.png"
-										}
-										alt={album.title}
-										className="w-full h-full object-cover"
-										onError={(e) => {
-											(e.target as HTMLImageElement).src = "/favicon.png";
-										}}
-									/>
+  return (
+    <div className="mt-8">
+      {albums.length > 0 && (
+        <div className="mb-12">
+          <div className="flex items-center gap-3 mb-6">
+            <Disc3 className="w-6 h-6 text-[#1db954]" />
+            <h2 className="text-2xl font-bold text-white">Albums</h2>
+          </div>
+          <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
+            {albums.map((album) => (
+              <div
+                key={album.id}
+                className="group cursor-pointer"
+                onClick={() => navigate(`/collection/album/${album.id}`)}
+              >
+                <div className="relative aspect-square rounded-lg mb-3 overflow-hidden shadow-md group-hover:shadow-xl transition-all duration-300 bg-[#181818]">
+                  <img
+                    src={
+                      album.cover ? `${baseURL}/${album.cover}` : "/favicon.png"
+                    }
+                    alt={album.title}
+                    className="w-full h-full object-cover"
+                    onError={(e) => {
+                      (e.target as HTMLImageElement).src = "/favicon.png";
+                    }}
+                  />
 
-									<button
-										className="absolute top-2 right-2 p-2 bg-black/70 hover:bg-black/90 rounded-full shadow-md transition-all duration-200 opacity-0 group-hover:opacity-100 cursor-pointer"
-										title={album.isLikedByCurrentUser ? "Unlike" : "Like"}
-										onClick={(e) => {
-											e.stopPropagation();
-											handleLike(album.id, album.title);
-										}}
-									>
-										<svg
-											className="w-5 h-5"
-											fill={album.isLikedByCurrentUser ? "#ef4444" : "none"}
-											stroke={
-												album.isLikedByCurrentUser ? "#ef4444" : "#9ca3af"
-											}
-											strokeWidth="2"
-											viewBox="0 0 24 24"
-										>
-											<path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
-										</svg>
-									</button>
+                  <button
+                    className="absolute top-2 right-2 p-2 bg-black/70 hover:bg-black/90 rounded-full shadow-md transition-all duration-200 opacity-0 group-hover:opacity-100 cursor-pointer"
+                    title={album.isLikedByCurrentUser ? "Unlike" : "Like"}
+                    onClick={(e) => {
+                      e.stopPropagation();
+                      handleLike(album.id, album.title);
+                    }}
+                  >
+                    <svg
+                      className="w-5 h-5"
+                      fill={album.isLikedByCurrentUser ? "#ef4444" : "none"}
+                      stroke={
+                        album.isLikedByCurrentUser ? "#ef4444" : "#9ca3af"
+                      }
+                      strokeWidth="2"
+                      viewBox="0 0 24 24"
+                    >
+                      <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
+                    </svg>
+                  </button>
 
-									<div className="absolute bottom-0 left-0 right-0 bg-linear-to-t from-black/80 to-transparent p-3">
-										<span
-											className={`text-xs px-2 py-1 rounded-full font-medium ${getRoleColor(album.role)}`}
-										>
-											{album.role.replace("_", " ")}
-										</span>
-									</div>
-								</div>
-								<h3 className="font-semibold text-sm line-clamp-2 text-white group-hover:text-[#1db954] transition-colors">
-									{album.title}
-								</h3>
-							</div>
-						))}
-					</div>
-				</div>
-			)}
+                  <div className="absolute bottom-0 left-0 right-0 bg-linear-to-t from-black/80 to-transparent p-3">
+                    <span
+                      className={`text-xs px-2 py-1 rounded-full font-medium ${getRoleColor(album.role)}`}
+                    >
+                      {album.role.replace("_", " ")}
+                    </span>
+                  </div>
+                </div>
+                <h3 className="font-semibold text-sm line-clamp-2 text-white group-hover:text-[#1db954] transition-colors">
+                  {album.title}
+                </h3>
+              </div>
+            ))}
+          </div>
+        </div>
+      )}
 
-			{songs.length > 0 && (
-				<div className="mb-12">
-					<div className="flex items-center gap-3 mb-6">
-						<Music className="w-6 h-6 text-[#1db954]" />
-						<h2 className="text-2xl font-bold text-white">Songs</h2>
-					</div>
-					<div className="space-y-1">
-						{songs.map((song) => (
-							<SongItem
-								key={song.id}
-								song={{
-									id: song.id,
-									title: song.title,
-									cover: song.cover,
-									genre: song.genre,
-									link: song.link,
-									isLikedByCurrentUser: song.isLikedByCurrentUser,
-								}}
-								role={song.role}
-								onLikeToggle={() => handleLike(song.id, song.title)}
-							/>
-						))}
-					</div>
-				</div>
-			)}
+      {songs.length > 0 && (
+        <div className="mb-12">
+          <div className="flex items-center gap-3 mb-6">
+            <Music className="w-6 h-6 text-[#1db954]" />
+            <h2 className="text-2xl font-bold text-white">Songs</h2>
+          </div>
+          <div className="space-y-1">
+            {songs.map((song) => (
+              <SongItem
+                key={song.id}
+                song={{
+                  id: song.id,
+                  title: song.title,
+                  cover: song.cover,
+                  genre: song.genre,
+                  link: song.link,
+                  isLikedByCurrentUser: song.isLikedByCurrentUser,
+                }}
+                role={song.role}
+                onLikeToggle={() => handleLike(song.id, song.title)}
+                isDropdownOpen={openDropdownSongId === song.id}
+                onDropdownToggle={setOpenDropdownSongId}
+              />
+            ))}
+          </div>
+        </div>
+      )}
 
-			{contributions.length === 0 && (
-				<div className="flex flex-col items-center justify-center py-16 text-gray-500">
-					<Music className="w-20 h-20 mb-4 opacity-20" />
-					<p className="text-lg font-medium">No contributions yet</p>
-					<p className="text-sm mt-2">Start creating music to see it here</p>
-				</div>
-			)}
-		</div>
-	);
+      {contributions.length === 0 && (
+        <div className="flex flex-col items-center justify-center py-16 text-gray-500">
+          <Music className="w-20 h-20 mb-4 opacity-20" />
+          <p className="text-lg font-medium">No contributions yet</p>
+          <p className="text-sm mt-2">Start creating music to see it here</p>
+        </div>
+      )}
+    </div>
+  );
 };
 
Index: frontend/src/components/userProfile/ListenerView.tsx
===================================================================
--- frontend/src/components/userProfile/ListenerView.tsx	(revision 85512ff50bc46445db00d8c3ecea57616baddb36)
+++ frontend/src/components/userProfile/ListenerView.tsx	(revision ce45c7a7871379455b3a3c55a48f767ca2e0e739)
@@ -25,4 +25,7 @@
   const [createdItems, setCreatedItems] = useState(createdPlaylists);
   const [savedItems, setSavedItems] = useState(savedPlaylists);
+  const [openDropdownSongId, setOpenDropdownSongId] = useState<number | null>(
+    null,
+  );
 
   const likedSongs = items.filter((e) => e.type === "SONG");
@@ -258,4 +261,6 @@
                 index={index + 1}
                 onLikeToggle={() => handleLike(song.id, song.title)}
+                isDropdownOpen={openDropdownSongId === song.id}
+                onDropdownToggle={setOpenDropdownSongId}
               />
             ))}
