mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-22 14:35:41 +00:00
fix(ui): shrink-wrap floating player bar instead of full-width strip (#969)
* fix(ui): shrink-wrap floating player bar instead of full-width strip The bar used fixed left and right insets, which stretched its background across the whole main column. Center it with max-content width so only the pill-shaped controls are painted, and soften the drop shadow. * docs: note PR #969 in changelog and settings credits
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { computeFloatingPlayerBarStyle } from './computeFloatingPlayerBarStyle';
|
||||
|
||||
describe('computeFloatingPlayerBarStyle', () => {
|
||||
it('centers in the main column and shrink-wraps instead of stretching', () => {
|
||||
const style = computeFloatingPlayerBarStyle(220, 1600, 1920);
|
||||
expect(style.left).toBe(910);
|
||||
expect(style.right).toBe('auto');
|
||||
expect(style.transform).toBe('translateX(-50%)');
|
||||
expect(style.width).toBe('max-content');
|
||||
expect(style.maxWidth).toBe(1332);
|
||||
});
|
||||
|
||||
it('accounts for a hidden queue panel', () => {
|
||||
const style = computeFloatingPlayerBarStyle(220, null, 1920);
|
||||
expect(style.left).toBe(1070);
|
||||
expect(style.maxWidth).toBe(1652);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
import type { CSSProperties } from 'react';
|
||||
|
||||
const HORIZONTAL_MARGIN_PX = 24;
|
||||
|
||||
/** Center the floating bar in the main column; shrink-wrap width instead of stretching. */
|
||||
export function computeFloatingPlayerBarStyle(
|
||||
sidebarRight: number,
|
||||
queueLeft: number | null,
|
||||
viewportWidth: number,
|
||||
): CSSProperties {
|
||||
const contentLeft = sidebarRight;
|
||||
const contentRight = queueLeft ?? viewportWidth;
|
||||
const contentWidth = Math.max(0, contentRight - contentLeft);
|
||||
const maxWidth = Math.max(100, contentWidth - HORIZONTAL_MARGIN_PX * 2);
|
||||
const centerX = contentLeft + contentWidth / 2;
|
||||
|
||||
return {
|
||||
left: centerX,
|
||||
right: 'auto',
|
||||
transform: 'translateX(-50%)',
|
||||
width: 'max-content',
|
||||
maxWidth,
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { computeFloatingPlayerBarStyle } from './computeFloatingPlayerBarStyle';
|
||||
|
||||
/** Computes the floating player-bar position based on the current sidebar +
|
||||
* queue panel widths. Returns an inline-style object (left/right/width); only
|
||||
@@ -14,17 +15,13 @@ export function useFloatingPlayerBar(
|
||||
if (!floatingPlayerBar) return;
|
||||
|
||||
const updatePosition = () => {
|
||||
const sidebar = document.querySelector('.sidebar') as HTMLElement;
|
||||
const queue = document.querySelector('.queue-panel') as HTMLElement;
|
||||
const sidebar = document.querySelector('.sidebar') as HTMLElement | null;
|
||||
const queue = document.querySelector('.queue-panel') as HTMLElement | null;
|
||||
|
||||
const leftOffset = sidebar ? sidebar.getBoundingClientRect().right : 0;
|
||||
const rightOffset = queue ? window.innerWidth - queue.getBoundingClientRect().left : 0;
|
||||
const sidebarRight = sidebar ? sidebar.getBoundingClientRect().right : 0;
|
||||
const queueLeft = queue ? queue.getBoundingClientRect().left : null;
|
||||
|
||||
setFloatingStyle({
|
||||
left: leftOffset + 24,
|
||||
right: rightOffset + 24,
|
||||
width: 'auto',
|
||||
});
|
||||
setFloatingStyle(computeFloatingPlayerBarStyle(sidebarRight, queueLeft, window.innerWidth));
|
||||
};
|
||||
|
||||
updatePosition();
|
||||
|
||||
Reference in New Issue
Block a user