diff --git a/static/app.css b/static/app.css index 2f616d1..f012257 100644 --- a/static/app.css +++ b/static/app.css @@ -105,6 +105,11 @@ main > * { font-size: 17px; } +/* Spacing for alerts so they don't stick to edges or neighbors */ +.alert { + margin: 12px 0; +} + /* Carded content shell */ main.tab-content, section.tab-content { diff --git a/static/audioplayer.css b/static/audioplayer.css index 44bc120..6ce06ab 100644 --- a/static/audioplayer.css +++ b/static/audioplayer.css @@ -7,7 +7,7 @@ 0 12px 30px rgba(15, 23, 42, 0.22), inset 0 1px 0 rgba(255, 255, 255, 0.24); border: 2px solid rgba(255, 255, 255, 0.55); - outline: 1px solid rgba(12, 18, 32, 0.18); /* slightly stronger edge so front/back separate */ + outline: 1.5px solid rgba(12, 18, 32, 0.3); /* slightly stronger edge so front/back separate */ outline-offset: -1px; background-clip: padding-box; /* keep border separate from glass */ padding: 12px 12px; @@ -17,6 +17,7 @@ margin-left: 8px; margin-right: 8px; overflow: hidden; /* keep the glass blur clean at the edges */ + position: relative; } /* Now Playing Info */ @@ -52,11 +53,13 @@ -webkit-appearance: none; width: 100%; height: 0.5em; - background-color: #e6edf7; + background-color: rgba(255, 255, 255, 0.12); border-radius: 5px; background-size: 0% 100%; - background-image: linear-gradient(90deg, #0b1220, #0f172a); + background-image: linear-gradient(90deg, rgba(11, 18, 32, 0.9), rgba(15, 23, 42, 0.9)); background-repeat: no-repeat; + border: 1px solid rgba(15, 23, 42, 0.2); + background-clip: padding-box; /* keep gradient clean inside the border */ appearance: none; outline: none; } @@ -168,3 +171,61 @@ .timeline::-ms-thumb { box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18); } + +/* Minimize button */ +.minimize-button { + position: absolute; + top: 6px; + right: 6px; + width: 18px; + height: 18px; + border-radius: 8px; + border: 1px solid rgba(15, 23, 42, 0.18); + background: rgba(255, 255, 255, 0.65); + box-shadow: 0 6px 14px rgba(15, 23, 42, 0.16); + display: inline-flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease; + padding: 0; +} + +.minimize-button:hover { + transform: translateY(-1px); + box-shadow: 0 10px 20px rgba(15, 23, 42, 0.18); +} + +.minimize-button:active { + transform: translateY(0); +} + +.minimize-button svg { + width: 16px; + height: 16px; + stroke: currentColor; + stroke-width: 1.6; + fill: none; +} + +.minimize-button .icon-expand { + display: none; +} + +/* Collapsed state */ +.audio-player-container.collapsed { + padding: 8px 48px 8px 12px; +} + +.audio-player-container.collapsed .audio-player, +.audio-player-container.collapsed .now-playing-info { + display: none; +} + +.audio-player-container.collapsed .minimize-button .icon-collapse { + display: none; +} + +.audio-player-container.collapsed .minimize-button .icon-expand { + display: inline-flex; +} diff --git a/static/audioplayer.js b/static/audioplayer.js index 69ef2a2..5dab0aa 100644 --- a/static/audioplayer.js +++ b/static/audioplayer.js @@ -6,7 +6,8 @@ class SimpleAudioPlayer { infoSelector = '#timeInfo', nowPlayingSelector = '#nowPlayingInfo', containerSelector = '#audioPlayerContainer', - footerSelector = 'footer' + footerSelector = 'footer', + minimizeBtnSelector = '.minimize-button' } = {}) { // Elements this.audio = document.querySelector(audioSelector); @@ -16,6 +17,7 @@ class SimpleAudioPlayer { this.nowInfo = document.querySelector(nowPlayingSelector); this.container = document.querySelector(containerSelector); this.footer = document.querySelector(footerSelector); + this.minBtn = document.querySelector(minimizeBtnSelector); // State this.isSeeking = false; @@ -60,6 +62,9 @@ class SimpleAudioPlayer { _bindEvents() { this.playBtn.addEventListener('click', () => this.togglePlay()); + if (this.minBtn) { + this.minBtn.addEventListener('click', () => this.toggleCollapse()); + } this.audio.addEventListener('loadedmetadata', () => { this.timeline.min = 0; @@ -138,6 +143,14 @@ class SimpleAudioPlayer { } } + toggleCollapse() { + const collapsed = this.container.classList.toggle('collapsed'); + if (this.minBtn) { + this.minBtn.setAttribute('aria-expanded', (!collapsed).toString()); + this.minBtn.setAttribute('aria-label', collapsed ? 'Player ausklappen' : 'Player einklappen'); + } + } + async fileDownload() { const src = this.audio.currentSrc || this.audio.src; if (!src) return; diff --git a/templates/app.html b/templates/app.html index 2df64f5..fb9a3bb 100644 --- a/templates/app.html +++ b/templates/app.html @@ -187,6 +187,18 @@