Add spotify integration
Deploy HEOS panel / deploy (push) Successful in 25s

This commit is contained in:
2026-09-15 22:07:43 +02:00
parent 6a0f1fa5e8
commit 7c19ff9096
17 changed files with 810 additions and 44 deletions
+21 -7
View File
@@ -45,7 +45,8 @@ button {
touch-action: manipulation;
}
svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
/* Every icon is a Font Awesome glyph: a solid shape, filled, never stroked. */
svg { width: 22px; height: 22px; fill: currentColor; }
.app {
max-width: 520px;
@@ -109,9 +110,9 @@ svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width:
width: 78px; height: 62px;
border-radius: 18px;
background: var(--raised);
font-size: 30px; font-weight: 500; line-height: 1;
display: grid; place-items: center;
}
.step svg { width: 20px; height: 20px; }
.step:active { background: var(--accent); transform: scale(.96); }
.step:disabled { opacity: .4; }
@@ -132,11 +133,6 @@ svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width:
.transport:active { background: var(--accent); transform: scale(.97); }
.transport:disabled { opacity: .5; }
.transport svg { width: 19px; height: 19px; }
/* A play triangle wants filling; the pause bars are drawn with the stroke
everything else in here uses. */
.transport .icon-play { fill: currentColor; stroke: none; }
.transport .icon-pause { stroke-width: 2.4; }
.transport[data-role="next"] svg { fill: currentColor; stroke: none; }
/* Which icon shows is a class on the button, not `hidden` on the svg:
`hidden` is an HTMLElement property and SVGElement does not inherit it,
@@ -160,6 +156,22 @@ svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width:
.toggle:disabled { opacity: .5; }
.toggle.busy { opacity: .6; }
/* --- Spotify: one resume button per account ----------------------------- */
.spotify-row { display: flex; gap: 10px; }
.spotify {
flex: 1; min-width: 0;
height: 50px; border-radius: 16px;
background: var(--raised);
display: flex; align-items: center; justify-content: center; gap: 9px;
font-size: 15px; font-weight: 550;
}
.spotify svg { flex: 0 0 auto; color: #fff; }
.spotify span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.spotify:active { transform: scale(.985); }
.spotify:disabled { opacity: .5; }
/* The account playing on this room right now. */
.spotify[aria-pressed="true"] { border: 2px solid var(--ink); }
/* --- source card ------------------------------------------------------ */
.source-button {
display: flex; align-items: center; gap: 12px;
@@ -192,6 +204,7 @@ svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width:
background: none; border: 1px solid var(--edge); color: var(--muted);
}
.joined .toggle .dot { display: none; }
.joined .spotify { height: 40px; font-size: 13px; font-weight: 500; }
.joined .toggle:active { background: var(--raised); color: var(--ink); }
/* --- misc ------------------------------------------------------------- */
@@ -242,6 +255,7 @@ svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width:
background: #2b1f24; border: 1px solid #52303a; color: #ffd9d4;
font-size: 14px; box-shadow: 0 10px 30px rgba(0, 0, 0, .45);
}
.toast.ok { background: #172a21; border-color: #2a5540; color: #c9f7df; }
@media (prefers-reduced-motion: reduce) {
* { animation: none !important; transition: none !important; }