Skip to content

Commit fcb9937

Browse files
committed
- add dark mode support with dark: tailwind classes
- refactor css into semantic classes using tailwind utility classes - optimize button hover/active states with `transition-*` classes - replace manual shadow values with css variable `--shadow` - simplify positioning with `inset-0` shorthand - remove redundant css classes and consolidate styles - fix overflow handling on body and container elements
1 parent 8f6482e commit fcb9937

File tree

1 file changed

+55
-178
lines changed

1 file changed

+55
-178
lines changed

tools/spotify_music_quiz_cards.html

Lines changed: 55 additions & 178 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
66
<script src="https://cdn.tailwindcss.com"></script>
77
<style>
8+
:root {
9+
--shadow: rgba(0, 0, 0, 0.1);
10+
}
11+
812
@media print {
913
body * {
1014
visibility: hidden;
@@ -19,72 +23,12 @@
1923
}
2024
}
2125

22-
.card {
23-
width: 6cm;
24-
height: 6cm;
25-
border: 1px solid #e5e7eb;
26-
border-radius: 8px;
27-
background: white;
28-
padding: 10px;
29-
margin: 10px;
30-
page-break-inside: avoid !important;
31-
break-inside: avoid !important;
32-
}
33-
34-
.page {
35-
page-break-after: always !important;
36-
page-break-before: always !important;
37-
margin-bottom: 2cm;
38-
}
39-
40-
.card-container {
41-
display: grid;
42-
grid-template-columns: repeat(3, 1fr);
43-
gap: 20px;
44-
padding: 20px;
45-
page-break-inside: avoid !important;
46-
break-inside: avoid !important;
47-
}
48-
49-
.card-page {
50-
display: grid;
51-
grid-template-columns: repeat(3, 1fr);
52-
gap: 20px;
53-
padding: 20px;
54-
page-break-after: always;
55-
}
56-
57-
.qr-container {
58-
display: flex;
59-
justify-content: center;
60-
height: 100%;
61-
align-items: center;
62-
}
63-
64-
.metadata {
65-
text-align: center;
66-
height: 100%;
67-
display: flex;
68-
flex-direction: column;
69-
justify-content: center;
70-
}
71-
72-
.metadata .year {
73-
font-size: 24px;
74-
margin-top: 8px;
75-
}
76-
77-
#printArea {
78-
display: block;
79-
padding: 1cm;
80-
}
81-
82-
.hidden {
83-
display: none;
26+
body {
27+
overflow: hidden;
8428
}
8529

8630
#pauseResumeButton {
87-
width: min(60vmin, 300px); /* Cap the max size on desktop */
31+
width: min(60vmin, 300px);
8832
height: min(60vmin, 300px);
8933
border: none;
9034
border-radius: 50%;
@@ -97,7 +41,7 @@
9741
transition: all 0.4s cubic-bezier(0.22, 1, 0.36, 1);
9842
box-shadow:
9943
0 2rem 4rem rgba(29, 185, 84, 0.2),
100-
0 1rem 2rem rgba(0, 0, 0, 0.1),
44+
0 1rem 2rem var(--shadow),
10145
inset 0 -2px 0 rgba(0, 0, 0, 0.1),
10246
inset 0 2px 0 rgba(255, 255, 255, 0.2);
10347
overflow: hidden;
@@ -106,10 +50,7 @@
10650
#pauseResumeButton::before {
10751
content: '';
10852
position: absolute;
109-
top: 0;
110-
left: 0;
111-
right: 0;
112-
bottom: 0;
53+
inset: 0;
11354
border-radius: 50%;
11455
background: linear-gradient(145deg, rgba(255, 255, 255, 0.2), transparent);
11556
opacity: 0;
@@ -121,7 +62,7 @@
12162
background: linear-gradient(145deg, #34F07E, #1FCC5E);
12263
box-shadow:
12364
0 3rem 5rem rgba(29, 185, 84, 0.25),
124-
0 1.5rem 3rem rgba(0, 0, 0, 0.15),
65+
0 1.5rem 3rem var(--shadow),
12566
inset 0 -2px 0 rgba(0, 0, 0, 0.1),
12667
inset 0 2px 0 rgba(255, 255, 255, 0.2);
12768
}
@@ -135,138 +76,69 @@
13576
background: linear-gradient(145deg, #1DB954, #1AA54C);
13677
box-shadow:
13778
0 1rem 2rem rgba(29, 185, 84, 0.15),
138-
0 0.5rem 1rem rgba(0, 0, 0, 0.1),
79+
0 0.5rem 1rem var(--shadow),
13980
inset 0 -1px 0 rgba(0, 0, 0, 0.1),
14081
inset 0 1px 0 rgba(255, 255, 255, 0.1);
14182
}
14283

14384
#pauseResumeButton svg {
14485
filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.2));
14586
}
146-
147-
#player {
148-
display: flex;
149-
justify-content: center;
150-
align-items: center;
151-
height: 100vh;
152-
margin: 0;
153-
flex-direction: column;
154-
}
155-
156-
.button-container {
157-
display: flex;
158-
flex-direction: column;
159-
align-items: center;
160-
gap: 2rem;
161-
}
162-
163-
.scan-button {
164-
padding: 1.5rem 3rem;
165-
font-size: 1.5rem;
166-
font-weight: 600;
167-
color: white;
168-
background: linear-gradient(145deg, #1e1e1e, #2d2d2d);
169-
border: none;
170-
border-radius: 15px;
171-
cursor: pointer;
172-
text-decoration: none;
173-
transition: all 0.3s ease;
174-
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
175-
text-transform: uppercase;
176-
letter-spacing: 1px;
177-
}
178-
179-
.scan-button:hover {
180-
transform: translateY(-2px);
181-
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.3);
182-
}
183-
184-
.scan-button:active {
185-
transform: translateY(1px);
186-
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
187-
}
188-
189-
#playlistModal {
190-
z-index: 1000;
191-
}
192-
193-
input[type="range"] {
194-
-webkit-appearance: none;
195-
height: 8px;
196-
background: #e5e7eb;
197-
border-radius: 4px;
198-
outline: none;
199-
}
200-
201-
input[type="range"]::-webkit-slider-thumb {
202-
-webkit-appearance: none;
203-
width: 20px;
204-
height: 20px;
205-
background: #1DB954;
206-
border-radius: 50%;
207-
cursor: pointer;
208-
}
209-
210-
input[type="range"]::-moz-range-thumb {
211-
width: 20px;
212-
height: 20px;
213-
background: #1DB954;
214-
border-radius: 50%;
215-
cursor: pointer;
216-
border: none;
217-
}
21887
</style>
21988
</head>
220-
<body class="bg-gray-100 min-h-screen">
89+
<body class="bg-gray-100 dark:bg-black min-h-screen overflow-hidden">
22190
<div id="setup" class="max-w-md mx-auto p-6">
222-
<div class="bg-white rounded-lg shadow-xl p-8">
223-
<input type="text" id="clientId" placeholder="Enter Spotify Client ID" class="w-full px-4 py-2 mb-4 border rounded">
224-
<button onclick="startAuth()" class="w-full bg-green-500 text-white py-2 px-4 rounded">Initialize</button>
91+
<div class="bg-white dark:bg-gray-900 rounded-lg shadow-xl p-8">
92+
<input type="text" id="clientId" placeholder="Enter Spotify Client ID"
93+
class="w-full px-4 py-2 mb-4 border rounded bg-white dark:bg-gray-700 text-black dark:text-white">
94+
<button onclick="startAuth()"
95+
class="w-full bg-green-500 hover:bg-green-600 text-white py-2 px-4 rounded transition-colors">
96+
Initialize
97+
</button>
22598
</div>
22699
</div>
227100

228-
<div id="player" class="hidden">
229-
<div class="button-container">
230-
<button id="pauseResumeButton"><span class="play"></span></button>
231-
<a href="https://www.gptgames.dev/tools/spotify_qr_scanner" class="scan-button">
101+
<div id="player" class="hidden h-screen flex justify-center items-center flex-col">
102+
<div class="flex flex-col items-center gap-8">
103+
<button id="pauseResumeButton">
104+
<span class="play"></span>
105+
</button>
106+
<a href="https://www.gptgames.dev/tools/spotify_qr_scanner"
107+
class="px-12 py-6 text-2xl font-semibold text-white dark:text-white bg-gray-800 dark:bg-gray-700
108+
hover:transform hover:-translate-y-1 rounded-2xl shadow-lg uppercase tracking-wide
109+
transition-all duration-300">
232110
Scan for next song
233111
</a>
234112
</div>
235-
<button id="createQRButton" class="fixed top-4 right-4 bg-green-500 text-white py-2 px-4 rounded">
113+
<button id="createQRButton"
114+
class="fixed top-4 right-4 bg-green-500 hover:bg-green-600 text-white py-2 px-4 rounded transition-colors">
236115
Create QR codes from Playlist
237116
</button>
238117
</div>
239118

240-
<div id="printArea"></div>
241-
242-
<div id="playlistModal" class="fixed inset-0 bg-black bg-opacity-50 hidden items-center justify-center">
243-
<div class="bg-white p-8 rounded-lg shadow-xl max-w-md w-full">
244-
<h2 class="text-xl font-bold mb-4">Create QR Codes from Playlist</h2>
245-
<input
246-
type="text"
247-
id="playlistUrl"
248-
placeholder="Enter Spotify playlist URL"
249-
class="w-full px-4 py-2 mb-4 border rounded"
250-
>
119+
<div id="printArea" class="p-[1cm]"></div>
120+
121+
<div id="playlistModal" class="fixed inset-0 bg-black/50 hidden items-center justify-center">
122+
<div class="bg-white dark:bg-gray-900 p-8 rounded-lg shadow-xl max-w-md w-full">
123+
<h2 class="text-xl font-bold mb-4 text-black dark:text-white">
124+
Create QR Codes from Playlist
125+
</h2>
126+
<input type="text" id="playlistUrl" placeholder="Enter Spotify playlist URL"
127+
class="w-full px-4 py-2 mb-4 border rounded bg-white dark:bg-gray-700 text-black dark:text-white">
251128
<div class="mb-4">
252-
<label class="block text-sm font-medium text-gray-700 mb-2">
129+
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
253130
Number of songs: <span id="songCount">21</span>
254131
</label>
255-
<input
256-
type="range"
257-
id="songSlider"
258-
min="3"
259-
max="300"
260-
step="3"
261-
value="21"
262-
class="w-full"
263-
>
132+
<input type="range" id="songSlider" min="3" max="300" step="3" value="21"
133+
class="w-full">
264134
</div>
265135
<div class="flex justify-end gap-4">
266-
<button onclick="closePlaylistModal()" class="px-4 py-2 text-gray-600 hover:text-gray-800">
136+
<button onclick="closePlaylistModal()"
137+
class="px-4 py-2 text-gray-600 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-200">
267138
Cancel
268139
</button>
269-
<button onclick="processPlaylist()" class="px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600">
140+
<button onclick="processPlaylist()"
141+
class="px-4 py-2 bg-green-500 hover:bg-green-600 text-white rounded transition-colors">
270142
Create
271143
</button>
272144
</div>
@@ -351,10 +223,11 @@ <h2 class="text-xl font-bold mb-4">Create QR Codes from Playlist</h2>
351223

352224
function createQRCard(track, isQRSide) {
353225
const card = document.createElement('div');
354-
card.className = 'card';
226+
card.className = 'w-[6cm] h-[6cm] border border-gray-200 rounded-lg bg-white p-2.5 m-2.5 break-inside-avoid';
227+
355228
if (isQRSide) {
356229
const qrContainer = document.createElement('div');
357-
qrContainer.className = 'qr-container';
230+
qrContainer.className = 'flex justify-center items-center h-full';
358231
qrContainer.id = `qr-${track.id}`;
359232
card.appendChild(qrContainer);
360233
new QRCode(qrContainer, {
@@ -367,8 +240,12 @@ <h2 class="text-xl font-bold mb-4">Create QR Codes from Playlist</h2>
367240
});
368241
} else {
369242
const metadata = document.createElement('div');
370-
metadata.className = 'metadata';
371-
metadata.innerHTML = `<h3 class="title">${track.name}</h3><p class="artist">${track.artist}</p><p class="year">${track.year}</p>`;
243+
metadata.className = 'text-center h-full flex flex-col justify-center text-black';
244+
metadata.innerHTML = `
245+
<h3 class="text-lg font-semibold">${track.name}</h3>
246+
<p class="text-gray-600">${track.artist}</p>
247+
<p class="text-2xl mt-2">${track.year}</p>
248+
`;
372249
card.appendChild(metadata);
373250
}
374251
return card;

0 commit comments

Comments
 (0)