diff --git a/frontend/index.css b/frontend/index.css index 3df7059..b156e58 100644 --- a/frontend/index.css +++ b/frontend/index.css @@ -1,3 +1,10 @@ +*, +*::before, +*::after { + -webkit-user-select: none; + user-select: none; +} + html { height: 100%; } @@ -53,7 +60,7 @@ body div.sidebar { padding: 0.25em; background-color: #343a40; display: grid; - grid-template-columns: auto 1fr auto; + grid-template-columns: var(--now-playing-width, 200px) 1fr auto; align-items: center; #now-playing-info { @@ -88,7 +95,6 @@ body div.sidebar { } now-playing { - max-width: 250px; overflow: hidden; } diff --git a/frontend/src/components/now-playing/now-playing.ts b/frontend/src/components/now-playing/now-playing.ts index 4ea0ca9..70b1555 100644 --- a/frontend/src/components/now-playing/now-playing.ts +++ b/frontend/src/components/now-playing/now-playing.ts @@ -1,18 +1,34 @@ import { LitElement, html, css } from 'lit'; -import { customElement } from 'lit/decorators.js'; +import { customElement, state } from 'lit/decorators.js'; import '@awesome.me/webawesome/dist/components/icon/icon.js'; import { PlayerController } from '@store/controllers/player-controller'; +const MIN_WIDTH = 120; +const MAX_WIDTH = 350; +const DEFAULT_WIDTH = 200; + @customElement('now-playing') export class NowPlaying extends LitElement { private player = new PlayerController(this); + @state() + private isDragging = false; + static override styles = css` + :host { + display: block; + position: relative; + height: 100%; + overflow: hidden; + } + .now-playing { display: flex; align-items: center; gap: 12px; padding: 8px; + height: 100%; + box-sizing: border-box; } .cover-art { @@ -66,19 +82,52 @@ export class NowPlaying extends LitElement { text-overflow: ellipsis; } + .resize-handle { + position: absolute; + top: 0; + right: 0; + width: 4px; + height: 100%; + cursor: col-resize; + background-color: transparent; + transition: background-color 0.15s ease; + z-index: 10; + } + + .resize-handle:hover, + .resize-handle.dragging { + background-color: #6c757d; + } `; + override connectedCallback() { + super.connectedCallback(); + this.updateWidth(DEFAULT_WIDTH); + document.addEventListener('mousemove', this.handleMouseMove); + document.addEventListener('mouseup', this.handleMouseUp); + } + + override disconnectedCallback() { + super.disconnectedCallback(); + document.removeEventListener('mousemove', this.handleMouseMove); + document.removeEventListener('mouseup', this.handleMouseUp); + } + override render() { const track = this.player.currentTrack; if (!track) { return html` -
+ `; } + + private handleMouseDown = (e: MouseEvent) => { + e.preventDefault(); + this.isDragging = true; + }; + + private handleMouseMove = (e: MouseEvent) => { + if (!this.isDragging) return; + + const rect = this.getBoundingClientRect(); + const newWidth = e.clientX - rect.left; + const clampedWidth = Math.min(Math.max(newWidth, MIN_WIDTH), MAX_WIDTH); + + this.updateWidth(clampedWidth); + }; + + private handleMouseUp = () => { + this.isDragging = false; + }; + + private updateWidth(width: number) { + const bottomBar = this.closest('.bottom-bar'); + + if (bottomBar) { + (bottomBar as HTMLElement).style.setProperty( + '--now-playing-width', + `${width}px`, + ); + } + } +} + +declare global { + interface HTMLElementTagNameMap { + 'now-playing': NowPlaying; + } } diff --git a/frontend/src/pages/config/config.css b/frontend/src/pages/config/config.css index 1bee9c0..a3e4f0d 100644 --- a/frontend/src/pages/config/config.css +++ b/frontend/src/pages/config/config.css @@ -1,3 +1,10 @@ +*, +*::before, +*::after { + -webkit-user-select: none; + user-select: none; +} + body { background-color: black; color: white;