removed queue panel slide-in animation and fixed resize flickering

This commit is contained in:
2026-02-17 10:32:05 -05:00
parent f8391ddd3d
commit cfeb01728c
2 changed files with 56 additions and 43 deletions
@@ -416,8 +416,9 @@ export class CoverGrid extends LitElement {
* Resize-aware scroll preservation * Resize-aware scroll preservation
* *
* When the container width changes (e.g. queue panel * When the container width changes (e.g. queue panel
* open/close/resize), the CSS grid reflows and the * open/close, drag-resize, or window resize), the CSS
* absolute scroll position becomes stale. * grid reflows and the absolute scroll position
* becomes stale.
* *
* We compute the fractional album index at the * We compute the fractional album index at the
* viewport center before the resize, then after the * viewport center before the resize, then after the
@@ -440,11 +441,13 @@ export class CoverGrid extends LitElement {
/** /**
* Wire up a ResizeObserver on the scroll container. * Wire up a ResizeObserver on the scroll container.
* *
* Uses a debounce pattern to handle animated * When the column count changes (e.g. queue panel
* transitions (e.g. the queue panel's 250ms width * open/close), scroll position is corrected
* animation). The center album index is captured on * synchronously in the same frame to avoid flicker.
* the first resize event, then restored once resizing * For continuous resizes that stay within the same
* settles. * column breakpoint (e.g. dragging the queue panel
* handle), a debounce ensures a final correction
* once resizing settles.
*/ */
private setupResizeObserver() { private setupResizeObserver() {
const container = this.scrollContainer; const container = this.scrollContainer;
@@ -465,10 +468,34 @@ export class CoverGrid extends LitElement {
this.currentColumnCount = this.currentColumnCount =
this.getColumnCount(); this.getColumnCount();
/** Restore scroll so the same album stays
* at the viewport center after a reflow. */
const restoreScroll = () => {
const pending =
this.pendingCenterIndex;
this.pendingCenterIndex = null;
if (!pending) return;
const newColumns =
this.getColumnCount();
const newRow =
pending.index / newColumns;
const newCenterY =
GRID_PADDING +
newRow * rowStep;
container.scrollTop =
newCenterY -
pending.viewportHeight / 2;
this.currentColumnCount = newColumns;
};
this.resizeObserver = new ResizeObserver(() => { this.resizeObserver = new ResizeObserver(() => {
// Capture on the first event using the // Capture on the first event using the
// pre-resize column count stored before // pre-resize column count.
// the animation started.
if (this.pendingCenterIndex === null) { if (this.pendingCenterIndex === null) {
const centerY = const centerY =
container.scrollTop + container.scrollTop +
@@ -485,38 +512,31 @@ export class CoverGrid extends LitElement {
}; };
} }
// Reset the debounce timer on every event const newColumns = this.getColumnCount();
// so we wait for the animation to finish.
if (newColumns !== this.currentColumnCount) {
// Column count changed — correct
// scroll immediately to avoid flicker.
if (this.resizeDebounceTimer !== null) {
clearTimeout(
this.resizeDebounceTimer,
);
this.resizeDebounceTimer = null;
}
restoreScroll();
return;
}
// Same column count — debounce for a
// final adjustment once resizing settles.
if (this.resizeDebounceTimer !== null) { if (this.resizeDebounceTimer !== null) {
clearTimeout(this.resizeDebounceTimer); clearTimeout(this.resizeDebounceTimer);
} }
this.resizeDebounceTimer = setTimeout( this.resizeDebounceTimer = setTimeout(
() => { restoreScroll,
const pending =
this.pendingCenterIndex;
this.pendingCenterIndex = null;
if (!pending) return;
const newColumns =
this.getColumnCount();
const newRow =
pending.index / newColumns;
const newCenterY =
GRID_PADDING +
newRow * rowStep;
container.scrollTop =
newCenterY -
pending.viewportHeight / 2;
// Update for the next resize
// cycle.
this.currentColumnCount =
newColumns;
},
100, 100,
); );
}); });
@@ -44,7 +44,6 @@ export class QueuePanel extends LitElement {
width: 0; width: 0;
overflow: hidden; overflow: hidden;
background-color: #212529; background-color: #212529;
transition: width 0.25s ease-in-out;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
} }
@@ -295,9 +294,6 @@ export class QueuePanel extends LitElement {
private handleMouseDown = (e: MouseEvent) => { private handleMouseDown = (e: MouseEvent) => {
e.preventDefault(); e.preventDefault();
this.isDragging = true; this.isDragging = true;
// Disable transition during drag for instant feedback.
this.style.transition = 'none';
}; };
private handleMouseMove = (e: MouseEvent) => { private handleMouseMove = (e: MouseEvent) => {
@@ -318,9 +314,6 @@ export class QueuePanel extends LitElement {
if (!this.isDragging) return; if (!this.isDragging) return;
this.isDragging = false; this.isDragging = false;
// Re-enable transition after drag ends.
this.style.removeProperty('transition');
}; };
override render() { override render() {