Stackbits
Cards > Skeumorphic Music Card

🎵 Skeumorphic Music Card

The Skeumorphic Music Card is a stylish React.js + Tailwind CSS music player with realistic shadows, beveled edges, and tactile buttons. Featuring play, pause, skip, and progress tracking, it's perfect for music apps, audio players, or portfolio projects. 🎵✨

Preview

Sideline

Sideline

David Dallas

Follow below steps 👇🏻

Install dependencies

1
npm i lucide-react

Component

Create a file skeumorphic-music-card.tsx in your components folder and paste this code

1
'use client';
2
3
import { Play, Pause, SkipForward, SkipBack } from 'lucide-react';
4
import { useState } from 'react';
5
6
interface SkeumorphicMusicCardProps {
7
title: string;
8
artist: string;
9
cover: string;
10
className?: string;
11
}
12
13
const ControlButton = ({
14
isPressed,
15
onMouseDown,
16
onMouseUp,
17
onMouseLeave,
18
onTouchStart,
19
onTouchEnd,
20
onClick,
21
children,
22
size = 'small'
23
}: {
24
isPressed: boolean;
25
onMouseDown: () => void;
26
onMouseUp: () => void;
27
onMouseLeave: () => void;
28
onTouchStart: () => void;
29
onTouchEnd: () => void;
30
onClick?: () => void;
31
children: React.ReactNode;
32
size?: 'small' | 'large';
33
}) => (
34
<div
35
className="rounded-full p-[3px] border-[1px] border-black/5"
36
style={{
37
background: 'linear-gradient(135deg, #c2d9f0 0%, #e6f0fa 100%)',
38
boxShadow: 'inset 1px 1px 2px rgba(255,255,255,0.6), inset -1px -1px 2px rgba(0,0,0,0.1)'
39
}}
40
>
41
<button
42
onClick={onClick}
43
onMouseDown={onMouseDown}
44
onMouseUp={onMouseUp}
45
onMouseLeave={onMouseLeave}
46
onTouchStart={onTouchStart}
47
onTouchEnd={onTouchEnd}
48
style={{
49
boxShadow: isPressed
50
? 'inset 3px 3px 7px rgba(0,0,0,0.2), inset -1px -1px 3px rgba(255,255,255,0.5)'
51
: '-3px -3px 7px rgba(255,255,255,0.7), 3px 3px 7px rgba(0,0,0,0.2)',
52
background: isPressed
53
? 'linear-gradient(135deg, #c2d9f0 0%, #d9e6f2 100%)'
54
: 'linear-gradient(135deg, #e6f0fa 0%, #c2d9f0 100%)',
55
transform: isPressed ? 'scale(0.95)' : 'scale(1)'
56
}}
57
className={`rounded-full transition-all duration-75 text-gray-700 hover:text-gray-900 ${
58
size === 'large' ? 'p-4' : 'p-2'
59
}`}
60
>
61
{children}
62
</button>
63
</div>
64
);
65
66
const ProgressBar = () => (
67
<div
68
style={{
69
boxShadow: 'inset 2px 2px 3px rgba(0,0,0,0.1), inset -1px -1px 3px rgba(255,255,255,0.7)',
70
background: 'linear-gradient(135deg, #c2d9f0 0%, #d9e6f2 100%)'
71
}}
72
className="h-2 rounded-full overflow-hidden"
73
>
74
<div
75
style={{
76
width: '35%',
77
background: 'linear-gradient(135deg, #6fa8dc 0%, #3d85c6 100%)',
78
boxShadow: '1px 1px 2px rgba(255,255,255,0.3)'
79
}}
80
className="h-full rounded-full"
81
/>
82
</div>
83
);
84
85
const SkeumorphicMusicCard = ({ title, artist, cover, className }: SkeumorphicMusicCardProps) => {
86
const [isPlaying, setIsPlaying] = useState(false);
87
const [isPlayButtonPressed, setIsPlayButtonPressed] = useState(false);
88
const [isBackButtonPressed, setIsBackButtonPressed] = useState(false);
89
const [isForwardButtonPressed, setIsForwardButtonPressed] = useState(false);
90
91
const togglePlayPause = () => setIsPlaying(!isPlaying);
92
93
return (
94
<div
95
style={{
96
boxShadow: 'inset -8px -8px 15px rgba(255,255,255,0.8), inset 8px 8px 15px rgba(0,0,0,0.2)',
97
background: 'linear-gradient(135deg, #e6ecf0 0%, #cfd8e2 100%)'
98
}}
99
className={`p-5 rounded-[30px] border-[1px] border-black/5 ${className}`}
100
>
101
<div
102
style={{
103
boxShadow:
104
'inset 2px 2px 5px rgba(255,255,255,0.7), inset -2px -2px 5px rgba(0,0,0,0.1), 5px 5px 15px rgba(0,0,0,0.1)',
105
background: 'linear-gradient(135deg, #e6f0fa 0%, #c2d9f0 100%)'
106
}}
107
className="relative w-80 p-6 rounded-[20px] flex flex-col items-center border-[1px] border-black/5"
108
>
109
{/* Album Cover */}
110
<div
111
style={{
112
boxShadow: '-2px -2px 5px rgba(255,255,255,0.5), 5px 5px 15px rgba(0,0,0,0.3)'
113
}}
114
className="w-40 h-40 rounded-xl overflow-hidden"
115
>
116
<img src={cover} alt={title} className="w-full h-full object-cover" />
117
</div>
118
119
{/* Song Info */}
120
<div className="mt-6 text-center">
121
<h3 className="text-lg font-semibold text-gray-800">{title}</h3>
122
<p className="text-sm text-gray-600">{artist}</p>
123
</div>
124
125
<div className="w-full mt-6 px-2">
126
<ProgressBar />
127
</div>
128
129
{/* Controls */}
130
<div className="flex items-center justify-center gap-5 w-full px-2 mt-3">
131
<ControlButton
132
isPressed={isBackButtonPressed}
133
onMouseDown={() => setIsBackButtonPressed(true)}
134
onMouseUp={() => setIsBackButtonPressed(false)}
135
onMouseLeave={() => setIsBackButtonPressed(false)}
136
onTouchStart={() => setIsBackButtonPressed(true)}
137
onTouchEnd={() => setIsBackButtonPressed(false)}
138
>
139
<SkipBack size={22} />
140
</ControlButton>
141
142
<ControlButton
143
isPressed={isPlayButtonPressed}
144
onMouseDown={() => setIsPlayButtonPressed(true)}
145
onMouseUp={() => setIsPlayButtonPressed(false)}
146
onMouseLeave={() => setIsPlayButtonPressed(false)}
147
onTouchStart={() => setIsPlayButtonPressed(true)}
148
onTouchEnd={() => setIsPlayButtonPressed(false)}
149
onClick={togglePlayPause}
150
size="large"
151
>
152
{isPlaying ? <Pause size={24} /> : <Play size={24} />}
153
</ControlButton>
154
155
<ControlButton
156
isPressed={isForwardButtonPressed}
157
onMouseDown={() => setIsForwardButtonPressed(true)}
158
onMouseUp={() => setIsForwardButtonPressed(false)}
159
onMouseLeave={() => setIsForwardButtonPressed(false)}
160
onTouchStart={() => setIsForwardButtonPressed(true)}
161
onTouchEnd={() => setIsForwardButtonPressed(false)}
162
>
163
<SkipForward size={22} />
164
</ControlButton>
165
</div>
166
</div>
167
</div>
168
);
169
};
170
171
export default SkeumorphicMusicCard;

Usage

1
<SkeumorphicMusicCard
2
title="Sideline"
3
artist="David Dallas"
4
cover="https://t2.genius.com/unsafe/680x680/https%3A%2F%2Fimages.genius.com%2Fcd9ba63203bb2d02e141581abf7beeb7.640x640x1.jpg"
5
/>

⭐️ Got a question or feedback?
Feel free to reach out!